# `npx pkg@latest` is a different program every launch

> An agent entry that runs through npx, bunx or pnpx resolves its package against the registry each time it starts. How Cydonia installs registry agents once, at a pinned version, and what it does with a hand-written entry that floats.

The usual way to configure an ACP agent is a line like `npx some-acp-agent@latest`. It also means the program you run is decided at launch: `npx`, `bunx` and `pnpx` resolve the package name against the npm registry every time they start, so the agent you open a session on tomorrow is whatever was published last.

Cydonia deals with this in two places: agents installed from the registry, and entries you write yourself.

## Registry installs, once

**Settings › Agents** lists the ACP registry, the catalog of agents for the [Agent Client Protocol](https://agentclientprotocol.com), fetched from `cdn.agentclientprotocol.com` and cached for a day. Each agent in it is published at an exact version, and that version is what Cydonia installs.

The registry says `npx` for an npm package. Cydonia reads that as "install this package", not "run it through npx":

```sh
npm install --prefix ~/.local/share/cydonia/agents/<id> \
  --ignore-scripts --no-fund --no-audit <package>@<version>
```

The executable comes from the installed package's own `bin` field, and the entry written into `settings.toml` points straight at it. From then on the agent starts from that path, and npm is not involved. This was in the first pull request: installs land in `$XDG_DATA_HOME/cydonia`, defaulting to `~/.local/share/cydonia`, "so npm never runs during a chat turn".

`--ignore-scripts` keeps a dependency's `postinstall` from running as you before the agent has ever been launched.

Where the registry offers both an npm package and a release archive for this machine, npm is taken. An archive is downloaded by the app, checked against its sha256 when the registry publishes one, and unpacked into the same directory.

## Hand-written entries

You can still write an agent yourself:

```toml
[[agents]]
name = "pinned-agent"
command = "npx"
args = ["some-acp-agent@1.4.2"]
```

Since PR #6 (4 September), Cydonia checks this kind of entry when it reads `settings.toml`. If `command` is `npx`, `bunx` or `pnpx`, every argument that does not start with `-` has to be a package with a version after its `@`, and the version has to start with a digit. Scoped names are handled: the version separator is the last `@` that is not the scope's leading one.

| Spec | Passes |
| --- | --- |
| `some-acp-agent@1.4.2` | yes |
| `@scope/agent@0.70.0` | yes |
| `some-acp-agent` | no |
| `some-acp-agent@latest` | no |
| `some-acp-agent@next` | no |
| `some-acp-agent@^1.2` | no |
| `@scope/agent` | no |

An entry that fails is dropped when settings load. The line stays in the file, where it can be read and fixed; it just never launches. Any other command, a binary on your path for instance, is not checked.

## Nothing by default

A fresh install used to ship `npx` lines for Claude and Codex. Those offered two agents nobody had installed, and the first session on one fetched a package off npm and ran it. The default agent list is now empty. An agent arrives through **Settings › Agents** or a line you write, and until then nothing can spawn.

## What is not covered

- Pinning a package does not pin its dependency tree. `npm install` resolves the dependencies of `some-acp-agent@1.4.2` at install time.
- The check applies to agent entries. MCP servers in `mcp.toml` are launched as written, `npx` lines included.

How to install an agent, from the registry or by hand, is in the [docs](https://cydonia.sh/docs/agents/install/).
