Notes7 min · 28 Jul 2026

How does code reach what it needs?

A page needs data and a coding agent needs tools. In both, where the code runs decides what it may reach, and where a file sits decides who gets it.

  1. 01The question
  2. 02Waiting without freezing
  3. 03On the server or in the browser
  4. 04Why the browser needs an API
  5. 05A command that decides
  6. 06Plugins are files in the right place
  7. 07Three places for settings
  8. 08The same choice in npm
  9. 09Back to the question

01The question

Next.js lets a component await its data, on the server or in the browser. What is await actually doing, why does the browser need an API when the server doesn't, and where does the data come from when the database belongs to another company?

The same question, asked of a different program: Claude Code is a command like ls, and it can be given plugins and settings. Where do those go, and how does it find them? Both halves come down to place. This picks up from What does Next.js do with my code?, which explains Server and Client Components, and How does my terminal find a tool?, on how a command is found.

02Waiting without freezing

Fetching data means waiting: a request goes out over the network and the answer comes back some hundreds of milliseconds later. JavaScript runs on one thread, so if it simply stopped and waited, nothing else could happen meanwhile; in a browser the page would freeze. Instead it hands the wait to the system and carries on, and the runs the code waiting for the answer when it arrives.

Saying what to do when it arrives has been written three ways. First callbacks: pass a function to be called with the answer. Steps that depend on each other nest inside each other, and three deep it is hard to read. Then promises: a stands for an answer that isn't here yet, and .then() says what to do with it. Then async and await, which is promises written as if nothing waited at all.

await pauses the function it is in until the promise settles, then carries on with the value. Only that function pauses; the rest of the program keeps going. A function marked async may use await, and always returns a promise itself. Three dependent steps become three lines in order: get the user, then their posts, then the comments on the first post.

The catch is that await waits even when it doesn't need to. Three requests that don't depend on each other, awaited one after another, take as long as all three together. Started together and awaited together with Promise.all, they take as long as the slowest.

Fig 01
const user = await getUser()
const weather = await getWeather()
const news = await getNews()
  1. getUser()
    300 ms
  2. getWeather()
    500 ms
  3. getNews()
    200 ms

1000 ms. Each await waits for the one before, though none of them needed its answer.

Three requests. Awaited in turn, the waits add up; started together, they overlap. The lengths are illustrative.

03On the server or in the browser

A can be async and await its data inside itself. The await runs on the server, before anything is sent, so the HTML arrives with the data in it and the visitor never sees a gap. A can't be async. It renders first with nothing, starts the fetch from a useEffect once it is in the browser, and renders again when the data arrives, so it needs something to show in between.

Fig 02
  1. A request for /posts/42 arrivesServer
  2. await fetch(…) runs here, with the keyServer
  3. The HTML is made with the post in itServer
  4. The HTML arrives and is shownBrowser
On screen
Nothing yet
The same post, fetched in two places. Watch what is on screen at each moment.
  • Fetch on the server when the data is the same for everyone (an article, a product, documentation), and whenever the fetch needs a secret.
  • Fetch in the browser when the data only exists there or has to stay live: what someone types into a search box, a feed that updates every second, the size of their window.
  • Personal is not the same as client. The server can read the visitor's cookies, so a page that differs per person can still arrive with its data in it.

Start on the server. Move a piece to the browser when it has to react to the person using it. One page usually has both: a product's details fetched on the server, its live stock count in the browser.

04Why the browser needs an API

It looks as if the server reaches the database directly and the browser has to go through an API. But the database is rarely in the same place as the server. A Next.js site on Vercel with its data on Convex makes a network call either way. The difference is who makes the call, and whether they can be trusted with the key.

A database lets in callers that show a secret key. Code on your server can hold that key: it never leaves the server, and nobody can read it. Code in the browser runs on the visitor's own machine, where everything it has can be read in the developer tools, so the browser can't be given the key. So it asks your server instead, through an address you make for it (in Next.js, a Route Handler such as /api/posts), and your server makes the call with the key and sends back only the answer.

Fig 03
  1. Server Component, on VercelHolds the key
  2. ↓
    Database, on Convex
  3. ↓
    HTML with the data, to the browser
Can a visitor read the key?No

The key never leaves the server. The browser only ever gets the finished page.

Three routes to the same data. Where is the key, and could a visitor read it?

It was never API or no API. It is where the call is made from, and whether that place can keep a secret.

Services built to be called from the browser, Convex and Supabase among them, give the browser only an address or a public key that names the project, and their own rules decide what each signed-in person may read. Anything that must stay secret still stays on a server.

05A command that decides

Claude Code is a command-line tool like ls or curl: one file on , ~/.local/bin/claude, installed the way Bun is. The difference is what it does with what you type. ls -la does the same thing every time: the pick from behaviour written in advance. Claude Code takes a sentence, and a language model decides what to do: which files to read, what to change, which other commands to run. It runs ls, git and curl itself. It is a tool that uses tools, the round a model from Three layers.

Inside it, a line starting with / is one of Claude Code's own commands, not the shell's, the way :wq means something only inside Vim. /plugin is one of them.

06Plugins are files in the right place

A plugin adds to what Claude Code can do: skills it can follow, commands, hooks that run at set moments, connections to other services. Adding one takes two commands, because there are two things to add.

  • /plugin marketplace add bradautomates/claude-video adds a marketplace: a catalogue of plugins, here a GitHub repository. Claude Code copies it to ~/.claude/plugins/marketplaces/claude-video and remembers it in known_marketplaces.json. Nothing is installed yet; the name is grander than the thing, which is a list, like the one npm or Homebrew read from.
  • /plugin install watch@claude-video installs one plugin, watch, from that marketplace. Its files go to ~/.claude/plugins/cache/claude-video/watch/0.2.0/, one folder per version, and a line "watch@claude-video": true goes into enabledPlugins in a settings file. From the next session, Claude Code loads it.

That plugin shows what most are: instructions plus a few ordinary commands. To watch a video, it runs yt-dlp to download it, ffmpeg to cut frames out of it as images, and takes the words from its captions or a speech-to-text model. The model can read images and text, not video, so the plugin turns the one into the other.

npx plugins add vercel/vercel-plugin is a third way in, and not Claude Code's at all. It runs an npm package called plugins, which converts a plugin written in a format several agents share into each agent's own, then installs it through that agent's own plugin system. It downloads the source to ~/.cache/plugins first; what reaches Claude Code ends up in the same folders as above.

07Three places for settings

Claude Code is installed once, for you. Its settings, and the plugins they switch on, can sit in three places, and the place decides who gets them.

Fig 04
  • ~
  • .claude
  • settings.json
    "watch@claude-video": true
  • plugins/
  • dev/my-app
  • .claude
  • settings.json
  • settings.local.json
  • .gitignore
Saved in
~/.claude/settings.json
Who gets the plugin
You, in every project
Goes into git
No. It isn't in a project

The plugin's files are downloaded to ~/.claude/plugins whatever the scope. The scope only decides which settings file switches it on.

The same line, saved at three scopes. Where does the file go, and who else gets it?

When you start claude in a folder, it reads your user settings, then that project's .claude/settings.json, then .claude/settings.local.json; where two disagree, the more local one wins. The project's file is committed, so everyone who clones the project gets the same plugins and rules. The local one is git-ignored and only yours. CLAUDE.md files follow the same pattern, and those are also read from the folders above where you started.

Not everything lives in settings.json. Connections to other services (MCP servers) are kept in ~/.claude.json for you, or .mcp.json in a project. And ~/.claude holds more than settings: projects/ keeps each project's transcripts and memory, skills/ your own skills, plugins/ all of the above.

08The same choice in npm

npm makes the same choice between you and a project. npm install prettier puts it in the project's node_modules and records it in package.json, so it goes wherever the project goes. npm install -g prettier puts it in one place for you: under npm's prefix, the files in lib/node_modules/prettier and a in bin so the shell can find it. The prefix is wherever the Node that runs npm says, so it isn't always /usr/local: with a Node installed in your home folder it is often ~/.local, and npm config get prefix says which.

npx prettier runs a package's command without installing it. It looks in the project's node_modules/.bin first. If it isn't there, npx downloads it into a cache, ~/.npm/_npx, and runs it from there. Nothing is installed for good, but it isn't gone either: the next run finds it in the cache.

Claude Code's own installer takes the third way from Two ways to move in: a folder of its own in your home, ~/.local/share/claude, and one link on PATH. Its settings then take npm's two places: ~/.claude for you, .claude for a project.

09Back to the question

Both halves were the same question. A component reaches data according to where it runs: on the server it can hold keys, in the browser it can only ask. Claude Code reaches tools and settings according to where they sit: a file in ~/.claude is yours everywhere, a file in a project's .claude belongs to everyone who has the project.

Code reaches what is where it looks, and is allowed what the place it runs can be trusted with.

Connected

  • Note · same thingSuggested
    What does Next.js do with my code?

    Server and Client Components from that note, now fetching: where a component runs decides when its data arrives and what it can hold.

  • Note · same patternSuggested
    How does my terminal find a tool?

    A program finds what it needs by looking in agreed places: the shell in PATH's folders, Claude Code in ~/.claude and the project's .claude.

  • Note · same thingSuggested
    What actually runs my code?

    await is that note's event loop seen from the code: park this function, serve something else, come back when the answer is in.

  • Chat · no note yet
    Streaming and Suspense

    The chat listed it as the next thing in Next.js's data fetching: sending the page in parts so slow data doesn't hold up the rest.

  • Chat · no note yet
    Server Actions

    Offered at the end of the data half: calling server code from a button without writing an API route.

Terms

Checked

What the chat had wrong or only half right, against sources. The note above already says the corrected thing.

  1. await only works inside an async function; at the top of a file it breaks.In a JavaScript module, await also works at the top level. Inside any other function, the function has to be async.MDN, await
  2. A Server Component reaches the database directly, with no API.It usually calls the database's API too, over the network. What differs is that the call comes from the server, which can hold the secret key. The chat corrects itself on this.Next.js docs, Fetching data
  3. /plugin marketplace add downloads the plugin; /plugin install switches on one tool in this session.marketplace add registers a catalogue. install installs a whole plugin from it, named plugin@marketplace, and enables it in a settings file, not just for one session.Claude Code docs, Discover and install plugins
  4. ~/.claude holds settings.json, settings.local.json and todos.md, and settings.json lists the plugins and MCP servers.There is no todos.md. Plugins are listed under enabledPlugins; MCP servers live in ~/.claude.json or a project's .mcp.json.Claude Code docs, Settings
  5. npx downloads a package, runs it, and it's gone.It is kept in npm's cache, ~/.npm/_npx, and found there the next time. It is never installed into the project or globally.npm docs, npx
  6. npm install -g puts files in /usr/local/lib/node_modules.Under npm's prefix, which depends on where the Node running npm was installed. /usr/local is one common answer.npm docs, folders
  7. The dlp in yt-dlp stands for download playlist.The project doesn't say. yt-dlp is a fork of youtube-dlc, itself a fork of youtube-dl.yt-dlp, README
  8. npx plugins add saves the plugin to ~/.claude/plugins/vercel/vercel-plugin.It clones the source to ~/.cache/plugins, converts it, and installs it through each agent's own plugin system; for Claude Code that is the usual plugins folders.vercel-labs/plugins, README