@cotal-ai/connector-opencode 0.11.2 → 0.11.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -42251,7 +42251,7 @@ config(en_default());
42251
42251
 
42252
42252
  // ../connector-core/dist/docs-bundle.generated.js
42253
42253
  var DOCS_BUNDLE = {
42254
- "version": "0.11.2",
42254
+ "version": "0.11.3",
42255
42255
  "generatedFrom": "docs/*.md + SPEC.md + spec/cotal.schema.json",
42256
42256
  "pages": [
42257
42257
  {
@@ -42273,7 +42273,7 @@ var DOCS_BUNDLE = {
42273
42273
  "title": "Architecture",
42274
42274
  "kind": "Concept (informative)",
42275
42275
  "summary": "Cotal is built as a thin waist: the normative wire contract (subjects, message schemas, presence/discovery, delivery semantics, the auth grammar) is the standard (SPEC), and everything else is a pl\u2026",
42276
- "body": "# Architecture\n\n> **Concept** (informative) \xB7 **For:** anyone who wants to know how Cotal is built, and why \xB7 **Normative:** [SPEC](../SPEC.md)\n\nCotal is built as a thin waist: the normative wire contract (subjects, message schemas,\npresence/discovery, delivery semantics, the auth grammar) is the standard\n([SPEC](../SPEC.md)), and everything else is a pluggable edge over existing building\nblocks. Identity, transport, storage, and discovery compose from proven pieces (NATS,\nJetStream, JWT/nkeys) rather than being reinvented. Adapters stay thin and swappable, and\nnothing adapter-specific leaks into the core.\n\n## Influences: A2A\n\nCotal reuses A2A's vocabulary and shapes so it stays interoperable rather than siloed, and\nimplements them over NATS/JetStream.\n\n**From A2A** come the *data shapes*: `AgentCard` (identity / role / tags / skills),\n`Message` / `Part` (text and data), and correlation ids (`contextId`). We do not adopt\nA2A's HTTP/JSON-RPC transport, `Task` RPCs, or its request/response server model, none of\nwhich fit lateral pub/sub.\n\nThe *addressing model* is Cotal's own: the hierarchical address `space / service / instance`\nand three delivery modes, multicast, unicast, anycast\n([presence & delivery](presence-and-delivery.md)). **Mentions** are a priority hint on a\nmulticast, not a routing target. NATS/JetStream is the data plane, adding the durability and\npresence a bare pub/sub layer leaves to the app.\n\nIdentity is an A2A `AgentCard` whose instance id is shaped to later become a **DID**\n(`did:key`) so authenticity can survive an untrusted relay ([roadmap](roadmap.md)).\n\n## One wire, mapped onto NATS\n\nThe whole protocol rides four subject kinds, with the sender encoded in the subject\nitself, where the server can police it, rather than in a self-asserted payload field\n([SPEC \xA73](../SPEC.md#3-subject-layout)):\n\n| Delivery | Subject |\n|---|---|\n| multicast | `cotal.<space>.chat.<owner>.<actor>.<channel\u2026>` |\n| unicast | `cotal.<space>.inst.<toOwner>.<toActor>.<owner>.<actor>` |\n| anycast | `cotal.<space>.svc.<role>.<owner>.<actor>` |\n| control | `cotal.<space>.ctl.<service>.<owner>.<actor>` |\n\nThe sender is a **principal**, an `owner.actor` pair: the account the agent acts on behalf\nof, then the agent's own handle under it ([identity & auth](identity-and-auth.md)). Two\ntokens instead of one means the broker can deny cross-owner *and* same-owner cross-actor\nforgery in the subject grammar itself.\n\nBehind the subjects, each space gets three **JetStream streams** (chat / DM / task, for\nstorage, per-reader bookmarks, and history), **KV buckets** for presence and the channel\nregistry, and the control plane as request/reply. Rather than re-implementing delivery\nguarantees, Cotal uses the native NATS mechanisms: streams for at-least-once and late\njoin, queue groups for anycast load-balancing, KV TTL for liveness ([SPEC \xA78](../SPEC.md#8-nats--jetstream-binding);\nthe reasoning: [presence & delivery](presence-and-delivery.md)). Isolation is one NATS\n**account per space** ([spaces & channels](spaces.md)); authorization is per-agent JWT\nACLs ([identity & auth](identity-and-auth.md)). Large artifacts are reserved for a\nper-space Object Store ([roadmap](roadmap.md)).\n\nWhether any of this *requires* NATS is answered in\n[transport vs protocol](transport.md): the contract is transport-agnostic; NATS/JetStream\nis the reference binding.\n\n## Package layout: one-way tiers\n\n```\nexamples \u2500\u2500\u2192 implementations \u2500\u2500\u2192 workspace \u2500\u2500\u2192 core \u2190(peer)\u2500\u2500 extensions\n (interoperate at runtime over NATS, not via imports)\n```\n\n- **`@cotal-ai/core`**, the protocol: subjects, schemas, the NATS client layer, and the\n extension contracts (`Connector`, `Command`, `Runtime`) with the `Registry` they\n self-register into. Depends on nothing else in the repo.\n- **`@cotal-ai/workspace`**, the machine-local operator layer over `~/.cotal`: mesh\n registry, target resolution, auth-path helpers. Not part of the wire standard, so a\n third party can embed core without inheriting workstation plumbing.\n- **`extensions/*`**: pluggable adapters (connectors, runtimes). Each **peer-depends** on\n core (binding to the host's single core instance) and self-registers on import; an\n unknown agent type **throws**, no silent fallback.\n- **`implementations/*`**, opinionated surfaces over core: the CLI, the manager, the\n delivery daemon, the web dashboard. Implementations never import each other; they meet\n at runtime, in a shared space over NATS. A composition root (the `cotal` binary, or an\n example) wires the pieces it wants.\n- **`examples/*`**: use-cases and composition roots, never published\n ([examples](examples.md)). An example only configures and orchestrates; new message\n kinds or subjects go into core, generalized, never into an example.\n\nThe published binary also loads **operator-installed extensions**: `cotal ext add\n<npm-package>` installs into a cotal-owned prefix, imports once so the package\nself-registers, then caches every contributed `kind:name`. Command metadata is cached for\n`--help`/completion; running a command or requesting a provider imports its owner lazily and\nuses the live object. Version skew or a stranded link fails loudly with instructions to re-add.\nThe repo's `@cotal-ai/web` dashboard and optional tmux/cmux/Orca runtimes use this mechanism; the\npublished binary does not hardcode those packages.\n\nMachine-local processes use the same registry. The base CLI contributes broker/control-plane\n`local-process` descriptors, while an installed package contributes its own (for example `web`).\nThat keeps `cotal down <component>` and `cotal status` extensible without teaching the base CLI\npackage-specific pidfiles. A provider process claims its declared pidfile with exclusive create;\nextension removal reserves that same path so startup cannot cross uninstall.\n\n## Connectors: four surfaces, one runtime\n\nEvery coding-agent integration exposes the same four surfaces:\n\n| Surface | Carries |\n|---|---|\n| Outbound, ambient | lifecycle \u2192 presence and activity, automatically |\n| Outbound, deliberate | the messaging tools (`cotal_send` / `cotal_dm` / `cotal_anycast`) |\n| Inbound, pull | `cotal_inbox` |\n| Inbound, push | wake-and-inject into the live session |\n\nThe shared runtime lives in [`@cotal-ai/connector-core`](../extensions/connector-core):\nthe mesh agent, the [`cotal_*` tool surface](mcp-tools.md) (defined once in its tool\nspecs, so it cannot drift across hosts), and the delivery buffer with its attention\npolicy. Each adapter is a thin client\nover it that binds to its host's native mechanism: an installed plugin + MCP server for\n[Claude Code](connect-claude.md), an in-process plugin for\n[OpenCode](connect-opencode.md) (beta), a Python sidecar for\n[Hermes](connect-hermes.md) (alpha).\n\nThe endpoint underneath self-heals: when the transport connection dies terminally, a\nsupervisor rebuilds it (rebuilds are serialized and coalesced), and unacked in-flight\nmessages redeliver on the rebound durables, so nothing is lost across the gap. A manual\n`/reconnect` is the human-invoked counterpart.\n\n## Manager: a supervisor, not an orchestrator\n\nThe CLI does not spawn agents itself; a long-lived **manager** owns their lifecycle,\nasked over the mesh (it is the control plane's first real consumer). It owns process\nlifecycle and config binding (start / stop / restart, binding env and policy) and has\nno say in what work the agents do. Agents coordinate laterally; the manager only births\nand configures them.\n\n- **Off the message hot path.** Each agent self-connects to the mesh through its own\n connector. The manager owns processes in order to control them, but observes everything\n through presence, so a bring-your-own-terminal agent it never spawned still shows up in\n `ps`.\n- **Pluggable runtimes.** Spawning is abstracted behind a `Runtime` contract (like pm2 or\n docker for agent TUIs): **`pty`** ships built-in (the manager owns a pseudo-terminal;\n watch or type via `cotal attach`); **`tmux`**, **`cmux`**, and **`orca`** are extensions\n that put each teammate in its own native terminal surface (explicit opt-ins that throw when the extension\n isn't loaded, never a silent fallback); **byo** is the floor (a human's own terminal,\n tracked via presence); **host** (Agent SDK, true mid-turn interrupt) is the documented\n upgrade path ([roadmap](roadmap.md)).\n- **Control schema:** `start {role, name, agent, model?, variant?}` \xB7 `models {agent?,\n refresh?}` \xB7 `stop {name, graceful?}` \xB7 `definePersona {name, persona, model?}` \xB7 `ps` \xB7\n `status` \xB7 `attach` \xB7 `bind`, request/reply messages any authorized node can send,\n policy-gated ([identity & auth](identity-and-auth.md)).\n- **Bounded spawn.** A synchronous gate caps concurrent + in-flight agents and a\n minimum-lifetime floor bounds spawn\u2194despawn churn, so a capability-holding but\n compromised peer cannot fork-bomb the host.\n- **Declared env, not inherited.** Runtimes pass spawned children an explicit allow-list\n (PATH / HOME / locale / TERM + the model key + opted-in shared-server vars, forwarded by\n name), never `process.env`, so the operator's unrelated secrets stop bleeding into every\n agent. This closes env-var bleed; it does not prevent filesystem reads or exfiltration\n of the model key itself.\n- **Watching is two channels.** The console/dashboard discovers agents over the **mesh**\n (presence, `ps`) but streams terminal pixels over a **direct attach connection** to the\n PTY owner; high-bandwidth terminal I/O never rides NATS. On attach, the manager replays\n a serialized snapshot of a headless terminal mirror, so a late attach repaints the full\n screen (including alternate-screen TUIs).\n\nThe result is that an agent can grow and shape its own team: ask for a teammate\n(`cotal_spawn`), mint a persona on the fly (`cotal_persona`), or tear one down\n(`cotal_despawn`). Every newcomer joins as a peer, not as a child of whoever requested\nit. Destructive space-wide operations (history purge) stay operator-only.\n\n## Observers\n\nA watch surface is a read-only observer: an endpoint that consumes without registering\npresence (invisible to peers) while watching everyone else's. All three surfaces\n(terminal console, plain stream, web dashboard) derive from that one observer through a\nshared render-agnostic model, so no surface re-implements wire semantics. The guide is\n[watch a mesh](watch-a-mesh.md); the model is [MeshView](mesh-view.md).\n\n## Names, roles, instances\n\nThree identity layers, in increasing permanence\n([SPEC \xA72](../SPEC.md#2-identity), [\xA76](../SPEC.md#6-presence-and-discovery)):\n\n- **`name`** is a cosmetic, reusable human handle. Addressing by name is best-effort\n convenience, with deterministic and fail-loud resolution: a unique live name resolves,\n and a collision among live peers throws with the candidate ids rather than silently\n picking one. The manager auto-numbers its own spawns (`reviewer` \u2192 `reviewer-2`).\n- **`role`** is the addressable service, which makes it the anycast address:\n `svc.reviewer` reaches \"whoever is a reviewer\", so the label carries routing meaning.\n- **The instance id** is the authoritative address: the presence key, the unicast target,\n the credential subject.\n\n**Instance continuity:** the id tracks *context* continuity, not the label. A resumed\nsession (same context window) keeps its id; presence, thread correlation, and in-flight\nDMs stay continuous. A fresh context, even reusing the name, is a **new** instance with a\nnew id: reusing an id across a discontinuous context would tell peers \"same agent, same\nmemory\" when the new session has none. One deliberate exception: OpenCode's `/new` inside\nthe same managed process keeps the mesh identity and advances only the thread correlation\nid: process continuity, not credential reuse.\n\n## Deferred\n\nSessions/moderator, signed envelopes + DID identity, instant offline, artifact delivery,\nauth-callout, and federation are designed for but not built yet; each is tracked, with\nits direction, in the [roadmap](roadmap.md).\n"
42276
+ "body": "# Architecture\n\n> **Concept** (informative) \xB7 **For:** anyone who wants to know how Cotal is built, and why \xB7 **Normative:** [SPEC](../SPEC.md)\n\nCotal is built as a thin waist: the normative wire contract (subjects, message schemas,\npresence/discovery, delivery semantics, the auth grammar) is the standard\n([SPEC](../SPEC.md)), and everything else is a pluggable edge over existing building\nblocks. Identity, transport, storage, and discovery compose from proven pieces (NATS,\nJetStream, JWT/nkeys) rather than being reinvented. Adapters stay thin and swappable, and\nnothing adapter-specific leaks into the core.\n\n## Influences: A2A\n\nCotal reuses A2A's vocabulary and shapes so it stays interoperable rather than siloed, and\nimplements them over NATS/JetStream.\n\n**From A2A** come the *data shapes*: `AgentCard` (identity / role / tags / skills),\n`Message` / `Part` (text and data), and correlation ids (`contextId`). We do not adopt\nA2A's HTTP/JSON-RPC transport, `Task` RPCs, or its request/response server model, none of\nwhich fit lateral pub/sub.\n\nThe *addressing model* is Cotal's own: the hierarchical address `space / service / instance`\nand three delivery modes, multicast, unicast, anycast\n([presence & delivery](presence-and-delivery.md)). **Mentions** are a priority hint on a\nmulticast, not a routing target. NATS/JetStream is the data plane, adding the durability and\npresence a bare pub/sub layer leaves to the app.\n\nIdentity is an A2A `AgentCard` whose instance id is shaped to later become a **DID**\n(`did:key`) so authenticity can survive an untrusted relay ([roadmap](roadmap.md)).\n\n## One wire, mapped onto NATS\n\nThe whole protocol rides four subject kinds, with the sender encoded in the subject\nitself, where the server can police it, rather than in a self-asserted payload field\n([SPEC \xA73](../SPEC.md#3-subject-layout)):\n\n| Delivery | Subject |\n|---|---|\n| multicast | `cotal.<space>.chat.<owner>.<actor>.<channel\u2026>` |\n| unicast | `cotal.<space>.inst.<toOwner>.<toActor>.<owner>.<actor>` |\n| anycast | `cotal.<space>.svc.<role>.<owner>.<actor>` |\n| control | `cotal.<space>.ctl.<service>.<owner>.<actor>` |\n\nThe sender is a **principal**, an `owner.actor` pair: the account the agent acts on behalf\nof, then the agent's own handle under it ([identity & auth](identity-and-auth.md)). Two\ntokens instead of one means the broker can deny cross-owner *and* same-owner cross-actor\nforgery in the subject grammar itself.\n\nBehind the subjects, each space gets three **JetStream streams** (chat / DM / task, for\nstorage, per-reader bookmarks, and history), **KV buckets** for presence and the channel\nregistry, and the control plane as request/reply. Rather than re-implementing delivery\nguarantees, Cotal uses the native NATS mechanisms: streams for at-least-once and late\njoin, queue groups for anycast load-balancing, KV TTL for liveness ([SPEC \xA78](../SPEC.md#8-nats--jetstream-binding);\nthe reasoning: [presence & delivery](presence-and-delivery.md)). Isolation is one NATS\n**account per space** ([spaces & channels](spaces.md)); authorization is per-agent JWT\nACLs ([identity & auth](identity-and-auth.md)). Large artifacts are reserved for a\nper-space Object Store ([roadmap](roadmap.md)).\n\nWhether any of this *requires* NATS is answered in\n[transport vs protocol](transport.md): the contract is transport-agnostic; NATS/JetStream\nis the reference binding.\n\n## Package layout: one-way tiers\n\n```\nexamples \u2500\u2500\u2192 implementations \u2500\u2500\u2192 workspace \u2500\u2500\u2192 core \u2190(peer)\u2500\u2500 extensions\n (interoperate at runtime over NATS, not via imports)\n```\n\n- **`@cotal-ai/core`**, the protocol: subjects, schemas, the NATS client layer, and the\n extension contracts (`Connector`, `Command`, `Runtime`) with the `Registry` they\n self-register into. Depends on nothing else in the repo.\n- **`@cotal-ai/workspace`**, the machine-local operator layer over `~/.cotal`: mesh\n registry, target resolution, auth-path helpers. Not part of the wire standard, so a\n third party can embed core without inheriting workstation plumbing.\n- **`extensions/*`**: pluggable adapters (connectors, runtimes). Each **peer-depends** on\n core (binding to the host's single core instance) and self-registers on import; an\n unknown agent type **throws**, no silent fallback.\n- **`implementations/*`**, opinionated surfaces over core: the CLI, the manager, the\n delivery daemon, the web dashboard. Implementations never import each other; they meet\n at runtime, in a shared space over NATS. A composition root (the `cotal` binary, or an\n example) wires the pieces it wants.\n- **`examples/*`**: use-cases and composition roots, never published\n ([examples](examples.md)). An example only configures and orchestrates; new message\n kinds or subjects go into core, generalized, never into an example.\n\nThe published binary also loads **operator-installed extensions**: `cotal ext add\n<npm-package>` installs into a cotal-owned prefix, imports once so the package\nself-registers, then caches every contributed `kind:name`. Command metadata is cached for\n`--help`/completion; running a command or requesting a provider imports its owner lazily and\nuses the live object. Version skew or a stranded link fails loudly with instructions to re-add.\nThe repo's `@cotal-ai/web` dashboard and optional tmux/cmux/Orca runtimes use this mechanism.\nRuntime resolution stays registry-driven and open-ended: a name with no registered/installed\nprovider fails loud (never a fallback), and a third-party runtime installs under its own package\nname. The CLI does carry a small, non-authoritative map of the first-party runtime names\n(`orca`/`tmux`/`cmux`) to their `@cotal-ai/*` packages, used only to print an exact `cotal ext add`\nhint for a known-but-uninstalled runtime and to list them in `cotal runtimes`; it never resolves or\nregisters a provider.\n\nMachine-local processes use the same registry. The base CLI contributes broker/control-plane\n`local-process` descriptors, while an installed package contributes its own (for example `web`).\nThat keeps `cotal down <component>` and `cotal status` extensible without teaching the base CLI\npackage-specific pidfiles. A provider process claims its declared pidfile with exclusive create;\nextension removal reserves that same path so startup cannot cross uninstall.\n\nBeyond the app-bound connectors, `@cotal-ai/pi` is a **host-native plugin**: a pi extension\nloaded into the user's own pi (CLI or SDK-embedded), placing a Cotal endpoint inside the\nsession's process and driving its run loop off the inbox \u2014 see\n[agent-frameworks](agent-frameworks.md).\n\n## Connectors: four surfaces, one runtime\n\nEvery coding-agent integration exposes the same four surfaces:\n\n| Surface | Carries |\n|---|---|\n| Outbound, ambient | lifecycle \u2192 presence and activity, automatically |\n| Outbound, deliberate | the messaging tools (`cotal_send` / `cotal_dm` / `cotal_anycast`) |\n| Inbound, pull | `cotal_inbox` |\n| Inbound, push | wake-and-inject into the live session |\n\nThe shared runtime lives in [`@cotal-ai/connector-core`](../extensions/connector-core):\nthe mesh agent, the [`cotal_*` tool surface](mcp-tools.md) (defined once in its tool\nspecs, so it cannot drift across hosts), and the delivery buffer with its attention\npolicy. Each adapter is a thin client\nover it that binds to its host's native mechanism: an installed plugin + MCP server for\n[Claude Code](connect-claude.md), an in-process plugin for\n[OpenCode](connect-opencode.md) (beta), a Python sidecar for\n[Hermes](connect-hermes.md) (alpha).\n\nThe endpoint underneath self-heals: when the transport connection dies terminally, a\nsupervisor rebuilds it (rebuilds are serialized and coalesced), and unacked in-flight\nmessages redeliver on the rebound durables, so nothing is lost across the gap. A manual\n`/reconnect` is the human-invoked counterpart.\n\n## Manager: a supervisor, not an orchestrator\n\nThe CLI does not spawn agents itself; a long-lived **manager** owns their lifecycle,\nasked over the mesh (it is the control plane's first real consumer). It owns process\nlifecycle and config binding (start / stop / restart, binding env and policy) and has\nno say in what work the agents do. Agents coordinate laterally; the manager only births\nand configures them.\n\n- **Off the message hot path.** Each agent self-connects to the mesh through its own\n connector. The manager owns processes in order to control them, but observes everything\n through presence, so a bring-your-own-terminal agent it never spawned still shows up in\n `ps`.\n- **Pluggable runtimes.** Spawning is abstracted behind a `Runtime` contract (like pm2 or\n docker for agent TUIs): **`pty`** ships built-in (the manager owns a pseudo-terminal;\n watch or type via `cotal attach`); **`tmux`**, **`cmux`**, and **`orca`** are extensions\n that put each teammate in its own native terminal surface (explicit opt-ins that throw when the extension\n isn't loaded, never a silent fallback); **byo** is the floor (a human's own terminal,\n tracked via presence); **host** (Agent SDK, true mid-turn interrupt) is the documented\n upgrade path ([roadmap](roadmap.md)).\n- **Control schema:** `start {role, name, agent, model?, variant?}` \xB7 `models {agent?,\n refresh?}` \xB7 `stop {name, graceful?}` \xB7 `definePersona {name, persona, model?}` \xB7 `ps` \xB7\n `status` \xB7 `attach` \xB7 `bind`, request/reply messages any authorized node can send,\n policy-gated ([identity & auth](identity-and-auth.md)).\n- **Bounded spawn.** A synchronous gate caps concurrent + in-flight agents and a\n minimum-lifetime floor bounds spawn\u2194despawn churn, so a capability-holding but\n compromised peer cannot fork-bomb the host.\n- **Declared env, not inherited.** Runtimes pass spawned children an explicit allow-list\n (PATH / HOME / locale / TERM + the model key + opted-in shared-server vars, forwarded by\n name), never `process.env`, so the operator's unrelated secrets stop bleeding into every\n agent. This closes env-var bleed; it does not prevent filesystem reads or exfiltration\n of the model key itself.\n- **Watching is two channels.** The console/dashboard discovers agents over the **mesh**\n (presence, `ps`) but streams terminal pixels over a **direct attach connection** to the\n PTY owner; high-bandwidth terminal I/O never rides NATS. On attach, the manager replays\n a serialized snapshot of a headless terminal mirror, so a late attach repaints the full\n screen (including alternate-screen TUIs).\n\nThe result is that an agent can grow and shape its own team: ask for a teammate\n(`cotal_spawn`), mint a persona on the fly (`cotal_persona`), or tear one down\n(`cotal_despawn`). Every newcomer joins as a peer, not as a child of whoever requested\nit. Destructive space-wide operations (history purge) stay operator-only.\n\n## Observers\n\nA watch surface is a read-only observer: an endpoint that consumes without registering\npresence (invisible to peers) while watching everyone else's. All three surfaces\n(terminal console, plain stream, web dashboard) derive from that one observer through a\nshared render-agnostic model, so no surface re-implements wire semantics. The guide is\n[watch a mesh](watch-a-mesh.md); the model is [MeshView](mesh-view.md).\n\n## Names, roles, instances\n\nThree identity layers, in increasing permanence\n([SPEC \xA72](../SPEC.md#2-identity), [\xA76](../SPEC.md#6-presence-and-discovery)):\n\n- **`name`** is a cosmetic, reusable human handle. Addressing by name is best-effort\n convenience, with deterministic and fail-loud resolution: a unique live name resolves,\n and a collision among live peers throws with the candidate ids rather than silently\n picking one. The manager auto-numbers its own spawns (`reviewer` \u2192 `reviewer-2`).\n- **`role`** is the addressable service, which makes it the anycast address:\n `svc.reviewer` reaches \"whoever is a reviewer\", so the label carries routing meaning.\n- **The instance id** is the authoritative address: the presence key, the unicast target,\n the credential subject.\n\n**Instance continuity:** the id tracks *context* continuity, not the label. A resumed\nsession (same context window) keeps its id; presence, thread correlation, and in-flight\nDMs stay continuous. A fresh context, even reusing the name, is a **new** instance with a\nnew id: reusing an id across a discontinuous context would tell peers \"same agent, same\nmemory\" when the new session has none. One deliberate exception: OpenCode's `/new` inside\nthe same managed process keeps the mesh identity and advances only the thread correlation\nid: process continuity, not credential reuse.\n\n## Deferred\n\nSessions/moderator, signed envelopes + DID identity, instant offline, artifact delivery,\nauth-callout, and federation are designed for but not built yet; each is tracked, with\nits direction, in the [roadmap](roadmap.md).\n"
42277
42277
  },
42278
42278
  {
42279
42279
  "slug": "mcp-tools",
@@ -42303,6 +42303,13 @@ var DOCS_BUNDLE = {
42303
42303
  "summary": "An agent's identity and persona live in one Markdown file instead of being passed flag-by-flag, the same shape Claude Code uses for subagents:",
42304
42304
  "body": "# Agent files\n\n> **Reference** (the persisted form of an agent's identity + persona, read by every launcher) \xB7 **For:** operators \xB7 **ACL semantics:** [SPEC \xA79](../SPEC.md#9-nats--jetstream-security-and-authorization), [Appendix B](../SPEC.md#appendix-b-profile-acls)\n\nAn agent's identity and persona live in one Markdown file instead of being passed\nflag-by-flag, the same shape Claude Code uses for subagents:\n\n```markdown\n.cotal/agents/<name>.md\n---\nname: dave # \u2192 COTAL_NAME / card.name\nrole: builder # \u2192 COTAL_ROLE / card.role (presence + anycast address)\ndescription: \u2026 # \u2192 card.description\ntags: [edit, test] # \u2192 card.tags (\"what it can do\")\nsubscribe: [general, team.backend] # channels it reads at boot\nallowSubscribe: [general, team.>] # read ACL (omit = same as subscribe)\nallowPublish: [general, team.backend] # post ACL (omit = none, default-deny)\nmodel: opus # optional model override\nvariant: high # optional connector-defined model variant\ncapabilities: [spawn] # control-plane capabilities (may start/despawn teammates)\n---\nYou are a builder on a shared mesh of peer agents\u2026 \u2190 the body is the persona\n```\n\n**Frontmatter is identity** (an A2A-style `AgentCard`,\n[SPEC \xA76](../SPEC.md#6-presence-and-discovery)); **the body is the persona**, appended to\nthe session's system prompt at launch: the one field that *must* be applied at launch,\nbecause a session cannot change its system prompt afterward.\n\n## Fields\n\nAuthoritative shape: [`agent-file.ts`](../packages/core/src/agent-file.ts).\n\n| Field | Type | Meaning |\n|---|---|---|\n| `name` | string, required | Display name \u2192 `card.name`. A launcher resolves a bare name to `.cotal/agents/<name>.md`. |\n| `role` | string | The addressable **service**: presence label *and* the anycast address ([SPEC \xA73](../SPEC.md#3-subject-layout)). |\n| `kind` | `agent` \\| `endpoint` | Participation class; default `agent`. |\n| `description` | string | One-line summary \u2192 `card.description`. |\n| `tags` | string[] | Capability tags \u2192 `card.tags`. |\n| `subscribe` | string[] | The **active read set**: channels subscribed at boot (mutable at runtime via join/leave). Must be \u2286 `allowSubscribe`. Default `[general]`. |\n| `allowSubscribe` | string[] | The **read ACL**: channels it *may* read. Wildcard subtrees allowed (`team.>`). Omitted \u21D2 same as `subscribe`. |\n| `allowPublish` | string[] | The **post ACL**: channels it may publish to. **Omitted \u21D2 deny**; posting is the dangerous capability, declare it explicitly. |\n| `quiet` | string[] | Per-channel attention *default*: delivered but never wakes this agent (per-channel dnd). Concrete channels within the read ACL. |\n| `muted` | string[] | Per-channel attention *default*: dropped on receive, `@mentions` included. |\n| `model` | string | Model override handed to the agent CLI (Claude: `opus` / full id; OpenCode: `provider/model`). |\n| `variant` | string | Connector-defined model variant (e.g. an OpenCode variant, see `cotal models`). |\n| `launchOptions` | map | Opaque per-connector launch options forwarded **raw** to the harness (Claude flags, OpenCode agent config; Hermes has no option surface and fails loud). A CLI `--opt key=value` overrides a key set here. See [run a mesh](run-a-mesh.md#spawning-agents). |\n| `capabilities` | string[] | Control-plane capabilities minted into the cred. `spawn` grants the privileged control subject (spawn / named stop / persona definition), default-deny when absent, enforced by the broker, not a handler. On a per-user-auth mesh, `role:<r>` additionally lets the agent delegate role `r` when spawning ([identity & auth](identity-and-auth.md)); `admin` is never a persona capability. |\n| `owner` | string | **Policy, not content**: set once by `definePersona` (owner = creator); only the owner (or admin) may redefine the file over the wire. Never write it by hand. |\n| *(any other key)* | string | Kept verbatim in `meta` so a connector can read its own launcher hints without core knowing them. |\n\nThe three channel verbs on one card, with the common recipes:\n[Channels & permissions](channels-and-permissions.md). Attention semantics (`quiet` /\n`muted` are one-way *defaults*; the runtime toggle is per-instance and resets on restart):\n[Connect Claude](connect-claude.md#attention-how-much-traffic-wakes-you).\n\n## Discovery and resolution\n\n- **By name.** A launcher resolves a bare name to `.cotal/agents/<name>.md` (project\n catalog). This is a directory convention, not an HTTP well-known; mesh discovery stays\n NATS presence. The card built from the file is what gets broadcast.\n- **One ref.** The launcher sets `COTAL_AGENT_FILE=<abs path>` (the *who*) the way\n `COTAL_LINK` carries the *where*; the joined session reads its card straight from the\n file. Individual `COTAL_*` vars still override it ([config](config.md)).\n- **Defaults.** A bare `cotal spawn` uses the `default` persona\n (`COTAL_DEFAULT_PERSONA` changes the fallback); the harness comes from `--agent` /\n `COTAL_DEFAULT_AGENT`, else Claude. An explicit flag always wins over the file\n ([run a mesh](run-a-mesh.md)).\n\nEvery launcher consumes the file the same way; they differ only in how they run the spec:\n\n| Launcher | How to point at a file |\n|---|---|\n| Manager (`cotal spawn --detach dave`) | auto-discovers `.cotal/agents/dave.md` in the manager's workspace, or `--config <persona-or-path>`; same grammar as foreground (`--model`, `--variant`, `--cwd`, `--prompt`, ACL overrides, `--share-tools`). |\n| Foreground (`cotal spawn dave`) | same resolution; the real agent TUI takes over this terminal. Works from any directory via the mesh registry. |\n\n`.cotal/` is gitignored (user-local, like `.claude/`); commit persona files you want\nshared some other way. The demo ships committed examples under\n[`examples/01-lateral-coordination/agents/`](../examples/01-lateral-coordination/agents/).\n\n## Personas: short contracts, not titles\n\nExpert-persona prompts (\"you are a world-class\u2026\") do not reliably improve accuracy. Keep\nthe body to what the agent *does* and how it *coordinates*; a persona that needs facts\nshould point at the source (the repo's docs, a URL), not assert them.\n\n## Defining one at runtime\n\n`cotal_persona(name, prompt, model?)` sends a persona to the manager, which writes the\nsame file and announces it; a later `cotal_spawn(name, role?, agent?, model?, variant?)`\nbrings it online, so a peer can mint a teammate with no hand-written file\n([tool catalog](mcp-tools.md)). The write path takes **content only** (`model` /\n`persona`); `role`, `allowPublish`, `capabilities`, and `owner` are policy and have no\nslot, so a peer cannot grant itself a capability by redefining a file.\n\nThe operator-side counterpart is `cotal personas` (list / show / edit / new / rm); it\nreads and writes the same files directly, offline, no mesh ([CLI](cli.md)).\n"
42305
42305
  },
42306
+ {
42307
+ "slug": "agent-frameworks",
42308
+ "title": "Agent frameworks",
42309
+ "kind": "",
42310
+ "summary": "@cotal-ai/pi is Cotal's first host-native framework adapter.",
42311
+ "body": "# Agent frameworks\n\n`@cotal-ai/pi` is Cotal's first host-native framework adapter. It loads into the operator's own\n[Pi coding agent](https://github.com/earendil-works/pi), rather than bundling a runtime, and uses the\nsame Cotal subjects, presence, attention, and messaging tools as the app-bound connectors.\n\n## Surfaces\n\nOne standalone artifact supports three Pi-hosted surfaces:\n\n1. `cotal spawn --agent pi` launches the installed `pi` binary in the manager's PTY.\n2. Interactive Pi discovers a copied `~/.pi/agent/extensions/cotal.js`.\n3. Pi SDK applications using the default resource loader discover that same copy. SDK applications\n must bind Pi's extension lifecycle when they expect an idle session to be driven proactively.\n\nThis release pins Pi `0.79.10`. The Cotal package remains installable on Node 20; the separately\ninstalled Pi host requires Node 22.19 or newer.\n\n## Lifecycle\n\nThe adapter sends peer traffic as Pi custom messages with `triggerTurn: true` and\n`deliverAs: \"steer\"`. This removes an idle/streaming race while preserving structured batch details.\nReliability uses three distinct points:\n\n1. The matching custom `message_start` proves Pi dequeued the batch locally.\n2. A `context` event containing that exact batch proves it entered one provider request.\n3. A successful `after_provider_response` proves acceptance early when the transport exposes an HTTP\n response. Some transports, including the Codex subscription, omit that hook; their following clean\n terminal assistant boundary proves acceptance for the exact context instead.\n\nOnly provider-confirmed IDs become eligible for acknowledgement, and only at a terminal agent\nboundary. The Pi-local ledger re-reads `MeshAgent.peekInbox()`, verifies an exact front prefix, and\ncalls `drainInbox(n)` only for a positive exact count. Missing older IDs may have been evicted by the\nbounded inbox; out-of-order IDs are tombstoned and discarded only when they later reach the front.\nThis keeps acknowledgement correct without adding a shared connector-core API.\n\nPi emits `agent_end` to extensions without exposing whether it will retry. Error, abort, unknown\nreasons, and zero/missing-output `length` therefore\nretain the delivery association in `waiting`; a later `agent_start` proves continuation. Non-aborted\n`stop`, `toolUse`, and positive-output `length` are locally provable terminal boundaries and may\ncommit confirmed work.\n`session_before_compact { reason: \"overflow\", willRetry: true }` identifies the overflow path but is\nnot itself a terminal decision. User abort is identified from the `AbortSignal` captured while the\nturn is active. An abort or dispatch watchdog blocks automatic replay. In managed headless use,\nrestart is the safe recovery because it terminates any possibly-live provider call before durable\nredelivery.\n\n`reload`, `new`, `resume`, and `fork` tear down Pi's extension runtime. The adapter keeps its mesh,\ncontrol listener, delivery association, and ordered presence chain in a process-global identity map,\nthen binds the replacement runtime on its next `session_start`. Only `session_shutdown { reason:\n\"quit\" }` stops the mesh.\n\n## Host boundaries\n\n- With no mesh identity the extension is inert, even if `COTAL_HOME` or `COTAL_DEFAULT_AGENT` exists.\n- A partial managed control endpoint fails loudly; cooperative stop uses connector-core's existing\n authenticated control server and Pi's active `ctx.shutdown()`.\n- Peer traffic bypasses Pi's human `input` transformations, but provider, tool, permission, and\n sandbox hooks remain on the normal agent path.\n- `cotal_inbox` is read-only in Pi because the driver owns acknowledgement.\n- Pi resume, variants, MCP sharing, and raw launch options fail loudly until implemented.\n\n## Install\n\n```bash\nnpm install -g cotal-ai @earendil-works/pi-coding-agent@0.79.10\ncotal up\ncotal spawn default --detach --agent pi\n```\n\nFor interactive/default-loader discovery:\n\n```bash\nnpm install @cotal-ai/pi\nmkdir -p ~/.pi/agent/extensions\ncp node_modules/@cotal-ai/pi/dist/standalone.js ~/.pi/agent/extensions/cotal.js\n```\n\nSee [`extensions/pi/README.md`](../extensions/pi/README.md) for the exact delivery policy and\ncontributor credits.\n"
42312
+ },
42306
42313
  {
42307
42314
  "slug": "build-a-client",
42308
42315
  "title": "Build a Cotal client",
@@ -42315,7 +42322,7 @@ var DOCS_BUNDLE = {
42315
42322
  "title": "`cotal` CLI reference",
42316
42323
  "kind": "Reference: describes the TypeScript reference implementation (the `cotal` CLI), not the wire contract.",
42317
42324
  "summary": "cotal is the operator command line for the reference implementation: bring a mesh up, mint identities, launch agents, watch what they do, and tear it all down.",
42318
- "body": "# `cotal` CLI reference\n\n> **Reference**: describes the TypeScript reference implementation (the `cotal` CLI), not the wire contract. \xB7 **For:** operators \xB7 **Wire contract:** [SPEC](../SPEC.md)\n\n`cotal` is the operator command line for the reference implementation: bring a mesh up, mint\nidentities, launch agents, watch what they do, and tear it all down. It is a thin client over the\nwire contract: the normative subjects and schemas live in the [SPEC](../SPEC.md); this page is\nlookup material for the commands, not a walkthrough; if you are new, start with\n[Getting started](getting-started.md).\n\n## Running it\n\n```bash\nnpm install -g cotal-ai # puts `cotal` on your PATH (needs Node 20+)\ncotal --help # every command, grouped\ncotal <command> --help # one command's flags and usage\n```\n\n`npx cotal-ai <command>` runs it without a global install; in a dev clone, `pnpm cotal <command>`\nruns it through `tsx` with no build step. Bare `cotal` prints help. Every command generates its own\n`--help`, usage, and shell completion from its declared flags.\n\nCommands come from the surfaces the binary composes: the base mesh CLI, the manager\n(`supervise`), and the delivery daemon (`deliver`), plus any operator-installed extensions.\n`cotal ext add <npm-package>` installs any registry providers a package contributes: commands,\nruntimes, and local process lifecycle descriptors. The `web` dashboard and optional manager\nruntimes ship this way.\n\n## Commands\n\n| Area | Command | Purpose |\n|---|---|---|\n| Set up & lifecycle | [`setup`](#setup) | Guided, configure-only setup (installs, seeds personas; launches nothing) |\n| Set up & lifecycle | [`up`](#up) | Start a local mesh (nats-server + JetStream), or boot a whole manifest with `-f` |\n| Set up & lifecycle | [`down`](#down) | Stop the whole stack, selected registered components, or a manifest deploy |\n| Set up & lifecycle | [`clean`](#clean) | Configurable cleanup: purge history (live), or wipe the local store / identity (stopped) |\n| Set up & lifecycle | [`meshes`](#meshes-use-status) | List the running meshes on this machine |\n| Set up & lifecycle | [`use`](#meshes-use-status) | Set the default mesh a bare `cotal spawn` joins |\n| Set up & lifecycle | [`status`](#meshes-use-status) | Read-only diagnostics for setup, processes, and the selected mesh |\n| Agents & personas | [`spawn`](#spawn) | Launch an agent from a persona (foreground, or `--detach` via the manager) |\n| Agents & personas | [`models`](#models) | List connector model catalogs and variants from the manager |\n| Agents & personas | [`ps`](#ps-stop-attach) | List managed agents and their mesh status |\n| Agents & personas | [`stop`](#ps-stop-attach) | Ask the manager to stop a managed agent |\n| Agents & personas | [`attach`](#ps-stop-attach) | Stream and drive a managed agent's terminal (pty runtime) |\n| Agents & personas | [`personas`](#personas) | List, show, edit, create, or remove local personas |\n| Agents & personas | [`supervise`](#supervise) | Run a manager daemon (the agent supervisor / control plane) |\n| Messaging & watching | [`endpoints`](#endpoints) | List every endpoint in the live presence roster, including infrastructure |\n| Messaging & watching | [`send`](#send) | Send one message, then exit: DM a peer, post a channel, or ask a role |\n| Messaging & watching | [`channels`](#channels) | Inspect or set the channel registry (replay, description, instructions) |\n| Messaging & watching | [`history`](#history) | Clear retained message history |\n| Messaging & watching | [`console`](#console) | Live protocol view for a space (TUI, or `--plain` line stream) |\n| Messaging & watching | [`web`](#web) | Browser dashboard (installed as the `@cotal-ai/web` extension) |\n| Auth & meshes | [`mint`](#mint) | Mint a creds file for a space (static auth mode) |\n| Auth & meshes | [`login`](#login-logout) | Sign in to a per-user-auth mesh's IdP (once per machine) |\n| Auth & meshes | [`logout`](#login-logout) | Revoke the IdP session and clear the cached login |\n| Auth & meshes | [`actor`](#actor) | Manage a user-auth space's actor ledger (grant / revoke / list) |\n| Auth & meshes | [`doctor`](#doctor) | Credential-health diagnosis and repair (`doctor auth`) |\n| Auth & meshes | [`join`](#join) | Join a space as your own presence (interactive) |\n| Manifest | [`topology`](#manifest-deploys) | Validate and view a mesh manifest's access graph (read-only) |\n| Extensions & misc | [`ext`](#ext) | Install / remove operator CLI extensions |\n| Extensions & misc | [`completion`](#completion) | Print or install shell completion |\n| Extensions & misc | [`feedback`](#feedback) | Send feedback to the Cotal developers |\n| Extensions & misc | [`deliver`](#server-daemons) | Run the server-side Plane-3 delivery daemon |\n| Extensions & misc | [`feedback-intake`](#server-daemons) | Run a self-hosted feedback intake server |\n\nThe manifest modes of `up`, `spawn`, and `down` (`-f <cotal.yaml>`) plus `topology` are covered\ntogether under [Manifest deploys](#manifest-deploys).\n\n## setup\n\n```bash\ncotal setup [--full] [--demo] [--yes]\n```\n\n| Flag | Default | Meaning |\n|---|---|---|\n| `--full` | off | Redo the full guided flow (implies `--demo`) |\n| `--demo` | off | Also seed the guided expert team (`david`, `sven`, `me`) |\n| `--yes`, `-y` | off | Non-interactive accept-all (for agents / CI) |\n\nGuided setup is **configure-only**: it checks prerequisites, installs the Claude Code plugin, and\nseeds persona files, and it launches nothing (no mesh, no web, no manager). First run gets the\nnarrated flow; later runs print a status card. By default it seeds one `default` persona; the\n`david`/`sven`/`me` team is opt-in via `--demo`. See [Getting started](getting-started.md) and, for\nmaintainers, [setup internals](setup-internals.md).\n\n## up\n\n```bash\ncotal up [--detach] [--open] [--space <s>] [--server <url>] [--channels <path>]\ncotal up -f <cotal.yaml> [--dry-run] [--runtime <name>]\n```\n\n| Flag | Default | Meaning |\n|---|---|---|\n| `--server <url>` | auto (free local port) | Listen URL override |\n| `--host <host>` | \u2014 | Bind host override |\n| `--space <s>` | the folder's name | Space name |\n| `--store-dir <dir>` | \u2014 | JetStream store directory |\n| `--channels <path>` | `.cotal/channels.json` if present | Channel-registry seed file (JSON). An explicit path that is missing is an error |\n| `--open` | off (auth) | Unauthenticated dev mesh: no JWT, no ACLs |\n| `--user-auth` | off | Per-user auth: people `cotal login`; connects are authorized against the actor ledger |\n| `--idp <url>` | \u2014 | With `--user-auth`: the IdP auth base URL to pin on first enable |\n| `--detach` | off | Run in the background (stop with `cotal down`) |\n| `--file <cotal.yaml>`, `-f` | \u2014 | Launch a whole mesh from a manifest |\n| `--dry-run` | off | With `-f`: print the plan, mutate nothing |\n| `--runtime <name>` | manifest's | With `-f`: override the manifest's runtime (`pty` built in; others installed extensions) |\n\n`cotal up` boots a local nats-server with JetStream and, in auth mode (the default), JWT auth and\nper-agent ACLs; `--detach` records the mesh so `cotal spawn` from any directory can find it. With no\n`--server`, it auto-selects a free port if the default address is taken; an explicit `--server`\nstays fail-loud on collision. `--detach` also brings up the control plane (delivery daemon in auth\nmode, then the manager). The `-f` form is a [manifest deploy](#manifest-deploys); see\n[Run a mesh](run-a-mesh.md).\n\n`--user-auth --idp <url>` starts the space's auth service alongside the broker (the NATS\nauth callout plus the loopback token exchange); it is torn down with `cotal down`, and a\nre-run of `cotal up` heals a dead service on a running broker. `--user-auth` and `--open`\ncontradict each other and are refused loudly; a running broker cannot change auth mode\nwithout a `cotal down` first. See [identity & auth](identity-and-auth.md).\n\n## down\n\n```bash\ncotal down\ncotal down manager [delivery auth web nats ...]\ncotal down -f <cotal.yaml> | --run <id> [--dry-run]\n```\n\n| Flag | Default | Meaning |\n|---|---|---|\n| `--file <cotal.yaml>`, `-f` | \u2014 | Tear down this manifest's deploy |\n| `--run <id>` | \u2014 | Tear down one `spawn -f` run by id |\n| `--dry-run` | off | Print the manifest teardown or selected components, mutate nothing |\n\nBare `cotal down` stops the whole local stack in dependency order. Positional component names stop\nonly those self-registered local processes; for example, `cotal down manager` leaves delivery and\nthe broker running, and `cotal down web` is available when the web extension is installed. The\n`-f` / `--run` forms tear down a [manifest deploy](#manifest-deploys) without stopping the whole mesh\nand cannot be combined with component names. Stopping `nats` alone is refused while an unselected\nregistered daemon is still live; include those components or use bare `cotal down`.\n\n`down` never deletes on-disk state; that is [`clean`](#clean).\n\n## clean\n\n```bash\ncotal clean <history|store|all> --force\n```\n\n| Flag | Default | Meaning |\n|---|---|---|\n| `--space <s>` / `--server <url>` / `--creds <path>` | resolved mesh | `history`: target mesh |\n| `--dms` | off | `history`: also clear DM history |\n| `--store-dir <dir>` | `.cotal/nats` | `store`/`all`: JetStream store directory |\n| `--force` | \u2014 | Required: destructive, no prompting |\n\nOne configurable cleanup verb; every target requires `--force`.\n\n- `history` purges the retained message backlog on the **running** broker (channels, plus DMs\n with `--dms`). The same operation as [`history clear`](#history), which stays as an alias.\n- `store` deletes the **stopped** mesh's JetStream store (`.cotal/nats`): streams, durable\n consumers, and messages. This is the reset for stale on-disk broker state, e.g. durables\n minted by an older, incompatible Cotal generation surviving a `down`/`up` cycle.\n- `all` is `store` plus the space identity (`.cotal/auth`), the local creds and markers tied to\n it, any crash residue a normal `down` would have swept (stale pidfiles, `run/`), and the mesh's\n registry entry; the next `cotal up` mints a fresh identity.\n\n`history` needs the mesh up; `store` and `all` refuse while any recorded mesh process is still\nalive (run `cotal down` first). Personas (`.cotal/agents`) and logs are never touched. A custom\nstore location is not recorded anywhere, so `--store-dir` must repeat whatever the mesh was\nlaunched with.\n\n## meshes, use, status\n\n```bash\ncotal meshes\ncotal use <space>\ncotal status [--space <s>] [--server <url>]\n```\n\n`meshes` lists the running meshes on this machine; a `*` marks the `current` default a bare\n`cotal spawn` joins. `use <space>` sets that default when several are running. `status` is a\nread-only report across four sections: machine prerequisites, this folder's `.cotal/`, the\nrecorded meshes, and a live snapshot of the selected mesh (roster, channels, membership feed).\n`status` takes only `--space` / `--server` to pick the mesh to inspect; it starts nothing.\n\n## spawn\n\n```bash\ncotal spawn [<persona>] [--detach] [--name <n>] [--agent <a>] [--model <m>] [--variant <v>] [--prompt <text>] [--cwd <dir>]\ncotal spawn -f <cotal.yaml> [--dry-run]\n```\n\n| Flag | Default | Meaning |\n|---|---|---|\n| `--space <s>` | resolved mesh | Target space |\n| `--server <url>` | registry entry | Broker URL override |\n| `--creds <path>` | \u2014 | Control-caller creds for an off-registry manager (`--detach` only) |\n| `--name <n>` | persona's `name:` | Presence-name override (does not choose the persona) |\n| `--config <persona-or-path>` | \u2014 | Persona catalog name or file path; wins over the positional |\n| `--agent <a>` | `COTAL_DEFAULT_AGENT`, else `claude` | Connector type (`claude`, `opencode`, `hermes`, \u2026) |\n| `--role <r>` | persona's `role:` | Role override |\n| `--model <m>` | persona's `model:` | Model override |\n| `--variant <v>` | persona's `variant:` | Model variant override (connector-defined; e.g. OpenCode reasoning tiers) |\n| `--cwd <dir>` | this cwd | Working directory to root the agent at |\n| `--prompt <text>` | \u2014 | Initial prompt auto-submitted at start |\n| `--resume <id>` | \u2014 | Fork an existing session id into the mesh (claude only) |\n| `--transcript` / `--no-transcript` | off | Mirror the session transcript to `tr-<name>` |\n| `--share-tools <sel>` | none | Share named operator MCP servers with the agent |\n| `--subscribe <a,b>` | persona's | Channel read-set override |\n| `--allow-subscribe <a,b>` | = subscribe | Read-ACL override |\n| `--allow-publish <a,b>` | deny | Post-ACL override |\n| `--detach`, `-d` | off | Launch via the manager into a detached PTY (reattach with `cotal attach`) |\n| `--file <cotal.yaml>`, `-f` | \u2014 | Deploy a manifest onto the running mesh |\n| `--dry-run` | off | With `-f`: print the plan, mutate nothing |\n| `--allow-stale <a,b>` | \u2014 | With `-f`: waive named stale agents (apply-only) |\n| `--runtime <name>` | manifest's | With `-f`: override the manifest's runtime |\n\nThe persona (`--config` > positional > `COTAL_DEFAULT_PERSONA` > `default`) is loaded from the\ntarget mesh's `.cotal/agents/`; the launch flags override the file. Foreground runs the agent\nattached to your terminal; `--detach` hands the launch to the running manager. `--detach` is the\nonly mode that registers a durable delivery membership; a foreground spawn reads live only. See\n[Connect Claude Code](connect-claude.md) and [Agent files](agent-files.md); `-f` is a\n[manifest deploy](#manifest-deploys). (`cotal start` was merged into `cotal spawn --detach`.)\n\n## models\n\n```bash\ncotal models [--agent <connector>] [--refresh]\n```\n\n| Flag | Default | Meaning |\n|---|---|---|\n| `--space <s>` / `--server <url>` / `--creds <path>` | resolved mesh | Which manager to reach |\n| `--agent <connector>` | all registered connectors | Connector whose catalog to list |\n| `--refresh` | off | Ask the connector to refresh its provider cache |\n\nAsks the running manager for each connector's model catalog (model ids plus their variants)\nfor connectors that expose one (OpenCode today; a connector without a catalog says so). Pick a\nresult with `cotal spawn --model <provider/model> --variant <v>`.\n\n## endpoints\n\n```bash\ncotal endpoints [--space <s>] [--server <url>] [--creds <path>]\n```\n\nLists the mesh presence roster: agents, the manager, and any other protocol endpoint, with each\nendpoint's role, kind, status, and current activity. Unlike `ps`, this is a read-only presence view;\nit is not limited to child processes owned by the manager.\n\n## ps, stop, attach\n\n```bash\ncotal ps [--space <s>]\ncotal stop --name <n> [--space <s>]\ncotal attach --name <n> [--space <s>]\n```\n\n| Flag | Default | Meaning |\n|---|---|---|\n| `--space <s>` / `--server <url>` / `--creds <path>` | resolved mesh | Which manager to reach |\n| `--name <n>` | \u2014 | Managed agent to stop / attach (required) |\n\nThese are operator clients over the running manager's control plane. `ps` lists managed agents with\ntheir mesh status (`starting\u2026` / `working` / `waiting` / `offline`); on a user-auth mesh it also\nrenders each managed agent's last credential-refresh outcome, fail-closed. `attach` streams and\ndrives an agent's terminal on the `pty` runtime; detach with the escape key (Ctrl-] by default; see\n[`COTAL_DETACH_KEY`](config.md)). `stop` and `attach` need a running manager to talk to. On a\nstatic mesh they are cross-agent admin operations. On a user-auth mesh, your own agents (any agent\nunder your owner) need only the `spawn` scope; another owner's agent needs `admin` on your ledger\nrow ([identity & auth](identity-and-auth.md)). Launch detached agents with\n[`spawn --detach`](#spawn).\n\n## personas\n\n```bash\ncotal personas list [-v] [--running]\ncotal personas show <name>\ncotal personas edit <name>\ncotal personas new <name> (--prompt <t> | --from <f>) [--role <r>] [--model <m>]\ncotal personas rm <name> --force\n```\n\n| Flag | Default | Meaning |\n|---|---|---|\n| `--space <s>` / `--server <url>` / `--creds <path>` | resolved mesh | Which mesh's persona catalog |\n| `--role <r>` | \u2014 | `new`: the persona's role |\n| `--model <m>` | \u2014 | `new`: the persona's model |\n| `--prompt <t>` | \u2014 | `new`: the persona's prompt text |\n| `--from <f>` | \u2014 | `new`: seed the prompt from a file |\n| `--verbose`, `-v` | off | `list`: include role / model / description |\n| `--running` | off | `list`: mark personas live on the mesh |\n| `--force` | \u2014 | `rm`: required, delete without prompting |\n\nPersonas are the local agent files under `.cotal/agents/` that `cotal spawn` launches. See\n[Agent files](agent-files.md) for the file format.\n\n## supervise\n\n```bash\ncotal supervise [--runtime <name>] [--space <s>] [--server <url>] [--spawn <names>]\n```\n\n| Flag | Default | Meaning |\n|---|---|---|\n| `--space <s>` | this folder's auth space | Space to supervise |\n| `--server <url>` | the local mesh | Broker URL |\n| `--runtime <name>` | `pty` | Agent runtime (`pty` built in; extension runtimes are explicit-only) |\n| `--console-port <n>` | \u2014 | Protocol-console port |\n| `--roster <file>` | \u2014 | Declarative roster to boot at startup |\n| `--launch <spec>` | \u2014 | Resolved manifest launch spec (from `up -f` / `spawn -f`) |\n| `--spawn <names>` | \u2014 | Comma-separated personas to pre-spawn at startup |\n\nThe manager is the agent supervisor and control plane: it answers `spawn --detach`, `stop`, `ps`,\n`attach`, and the `cotal_*` manager tools. `cotal up --detach` starts one for you; run `supervise`\ndirectly to recover a dead manager or drive a custom runtime. Default runtime is `pty`; install an\noptional provider first (`cotal ext add @cotal-ai/orca`, `@cotal-ai/tmux`, or `@cotal-ai/cmux`) and\nselect it explicitly. A missing provider or app fails loudly; there is no fallback. See [Deploy](deploy.md).\n\n## send\n\n```bash\ncotal send dm <agent> \"<text>\" [--space <s>] [--server <url>] [--creds <path>]\ncotal send msg <channel> \"<text>\"\ncotal send ask <role> \"<text>\"\n```\n\n| Flag | Default | Meaning |\n|---|---|---|\n| `--space <s>` / `--server <url>` / `--creds <path>` | resolved mesh | Which mesh, and (off-registry) which credential |\n\nOne-shot messaging: connect, send a single direct message (`dm`), channel post (`msg`), or role\nask/anycast (`ask`), then exit. For a running conversation, agents use the mesh tools instead\n([MCP tools](mcp-tools.md)).\n\n## channels\n\n```bash\ncotal channels list\ncotal channels set <name> [--replay | --no-replay] [--window <n>] [--desc <s>] [--instructions <s>]\ncotal channels default --replay | --no-replay\n```\n\n| Flag | Default | Meaning |\n|---|---|---|\n| `--space <s>` / `--server <url>` / `--creds <path>` | resolved mesh | Target mesh |\n| `--replay` / `--no-replay` | \u2014 | `set`/`default`: replay history to new joiners, or not |\n| `--window <n>` | \u2014 | `set`: replay window size |\n| `--desc <s>` | \u2014 | `set`: one-line channel description |\n| `--instructions <s>` | \u2014 | `set`: instructions shown to joiners |\n\nInspects and edits the channel registry: replay policy, description, and joiner instructions. ACL\nsemantics (who may read or post) are set at mint / provision time, not here; see\n[Channels and permissions](channels-and-permissions.md). On a user-auth mesh, `list` rides your\nown login as is; `set` and `default` edit the registry over a short-lived channel-writer view,\nwhich needs ledger scope `admin` ([Identity & auth](identity-and-auth.md)).\n\n## history\n\n```bash\ncotal history clear --force [--dms] [--space <s>]\n```\n\n| Flag | Default | Meaning |\n|---|---|---|\n| `--space <s>` / `--server <url>` / `--creds <path>` | resolved mesh | Target mesh |\n| `--dms` | off | Also clear DM history |\n| `--force` | \u2014 | Required: clear without prompting |\n\nPurges retained channel history; `--dms` extends it to direct-message history. An alias of\n[`clean history`](#clean). On a user-auth mesh the purge rides a short-lived purger view over\nyour login, which needs ledger scope `admin` ([Identity & auth](identity-and-auth.md)).\n\n## console\n\n```bash\ncotal console [--plain] [--space <s>]\n```\n\n| Flag | Default | Meaning |\n|---|---|---|\n| `--space <s>` / `--server <url>` / `--creds <path>` | resolved mesh | Space to watch |\n| `--plain` | off | Line stream instead of the TUI |\n\nA live protocol view for a space: a lazygit-style TUI, or a plain line stream on `--plain`. On a\nuser-auth mesh it rides the read-only admin view over your login, which needs ledger scope\n`admin`. See [Watch a mesh](watch-a-mesh.md).\n\n## web\n\n```bash\ncotal ext add @cotal-ai/web # install once\ncotal web [--port <n>] [--no-open] [--space <s>]\n```\n\n| Flag | Default | Meaning |\n|---|---|---|\n| `--space <s>` / `--server <url>` / `--creds <path>` | resolved mesh | Space to serve |\n| `--port <n>` | `7799` | HTTP port |\n| `--no-open` | off | Don't open the browser |\n\nThe browser observability dashboard: presence, channels, and a live feed. It is **not** part of\n`cotal up`: it ships as the `@cotal-ai/web` extension (`cotal setup` installs it automatically; otherwise\n`cotal ext add @cotal-ai/web`). It self-registers `cotal web` into this surface and serves\n`http://cotal.localhost:7799` (loopback; `*.localhost` resolves in Chrome/Firefox/Edge; Safari may\nneed `http://127.0.0.1:7799`). On a user-auth mesh the dashboard rides the read-only admin view\nover your login, and a channel purge asks for its own channel-purger view per click; both need\nledger scope `admin`. See [Watch a mesh](watch-a-mesh.md).\n\n## mint\n\n```bash\ncotal mint <name> [--profile <agent|observer|admin>] [--out <path>] [--signer]\n```\n\n| Flag | Default | Meaning |\n|---|---|---|\n| `--profile <agent\\|observer\\|admin>` | `agent` | Credential profile |\n| `--out <path>` | `.cotal/auth/creds/<name>.creds` | Output path |\n| `--signer` | off | Emit a stripped account-signing file instead |\n| `--force` | off | With `--signer`: overwrite an existing file |\n| `--allow-subscribe <a,b>` | profile default | Read-ACL override |\n| `--allow-publish <a,b>` | profile default | Post-ACL override |\n\nMints a NATS creds file for a space in **static** auth mode, scoped to a profile and (optionally)\nexplicit read/post ACLs. `--signer` emits an account-signing file for delegating minting to another\nhost. A per-user-auth space refuses `mint`: agents there join under a logged-in user\n([`login`](#login-logout) + [`actor grant`](#actor)), never via a handed-out creds file. See\n[Identity and auth](identity-and-auth.md).\n\n## login, logout\n\n```bash\ncotal login --idp <auth base URL> [--client-id <id>]\ncotal logout --idp <auth base URL>\n```\n\nSigns you in to a per-user-auth mesh's IdP (device code flow) and caches the session; run it\nonce per machine. It prints your IdP subject, the id the operator grants against. After a\nlogin, every command on that mesh works under your identity: each connect takes a fresh IdP\nproof, exchanges it locally for a short-lived bearer, and is authorized against the actor\nledger at connect time. `logout` revokes the IdP session and clears the cache. See\n[identity & auth](identity-and-auth.md).\n\n## actor\n\n```bash\ncotal actor grant <actor> --sub <IdP subject> [--scope a,b] [--allow-subscribe a,b] [--allow-publish a,b] [--role <r>] [--label <l>]\ncotal actor revoke <actor> (--sub <IdP subject> | --owner <u_\u2026>)\ncotal actor list\n```\n\n| Flag | Default | Meaning |\n|---|---|---|\n| `--space <s>` | the folder's | Space whose ledger to manage |\n| `--sub <subject>` | \u2014 | The IdP subject (shown by `cotal login`) the actor belongs to |\n| `--owner <u_\u2026>` | \u2014 | The derived owner token (alternative to `--sub`) |\n| `--scope <a,b>` | `spawn,role:default` | Capability scope (`''` = none; `spawn` = may run agents, `role:<r>` = may delegate role r, `admin` = cross-agent control) |\n| `--allow-subscribe <a,b>` | `>` (all channels) | Channel read ACL; the user's envelope, their agents can never read beyond it |\n| `--allow-publish <a,b>` | `>` (all channels) | Channel post ACL; also the envelope for their agents' posting |\n| `--role <r>` | \u2014 | Role (scopes the task-queue consumer) |\n| `--label <l>` | \u2014 | Display label for `actor list` (never the IdP subject) |\n\nThe actor ledger is the single authorization source of a user-auth space: no row, no access.\nA bare `grant` is the **full** envelope (all channels, may spawn); the flags narrow it. A\nre-grant **replaces** the row, so to add a capability, re-grant with it added to the current\nscope (`cotal actor list` shows what a row holds). `revoke` denies the next exchange and the\nnext connect with no restart, and evicts the principal's live connections. Managed-agent rows\n(written by the spawn path) live in a disjoint row space this command never touches. See\n[identity & auth](identity-and-auth.md).\n\n## doctor\n\n```bash\ncotal doctor auth [--fix]\n```\n\nCredential-health diagnosis and repair for this folder's mesh: renders every managed\ncredential as healthy / near-expiry / expired and ends in `healthy` or the exact next\ncommand; `--fix` applies the repairs it can. The one surface every stale-credential error\npoints at.\n\n## join\n\n```bash\ncotal join --space <s> --name <n> [--role <r>] [--channel <c>]\ncotal join --link <url> | --token <t>\n```\n\n| Flag | Default | Meaning |\n|---|---|---|\n| `--space <s>` / `--server <url>` / `--creds <path>` | resolved mesh | Which mesh, and which credential |\n| `--name <n>` | \u2014 | Your presence name |\n| `--role <r>` | \u2014 | Your role |\n| `--channel <c>` | \u2014 | Channel to join |\n| `--kind <k>` | `agent` | Endpoint kind |\n| `--link <url>` | \u2014 | Join link (`cotal://\u2026`) |\n| `--token <t>` | \u2014 | Join token |\n| `--tls` | off | Connect over TLS |\n\nAn interactive presence: join a space under your own name and role, without launching an agent\nharness. A `--link` or `--token` supplies the where and the auth in one value. See\n[Spaces](spaces.md) and [Identity and auth](identity-and-auth.md).\n\n## Manifest deploys\n\nA `cotal.yaml` manifest declares a whole mesh (channels, personas, roles, and ACLs) in one file.\nThree commands consume it, plus a read-only validator:\n\n```bash\ncotal up -f cotal.yaml # boot a fresh mesh from the manifest\ncotal spawn -f cotal.yaml # deploy the manifest additively onto a running mesh\ncotal down -f cotal.yaml # tear that deploy down (or --run <id> for one run)\ncotal topology view -f cotal.yaml # validate + view the access graph, change nothing\n```\n\n`up -f` and `spawn -f` differ in target: `up -f` brings up a new broker and applies the manifest;\n`spawn -f` requires an already-reachable mesh and applies additively (ownership-scoped). On a\nuser-auth mesh, `spawn -f` deploys over your own login (the deployer view, gated on ledger scope\n`spawn`): the manifest's agents land under your owner, a manifest claiming another owner is\nrefused, and seeding new channels additionally needs scope `admin`. Both take\n`--dry-run` to print the plan without mutating anything. `topology` validates the manifest and\nrenders its channel / role / ACL graph. See [Define a team](define-a-team.md) and the\n[manifest reference](manifest.md).\n\n## ext\n\n```bash\ncotal ext add <npm-package>\ncotal ext remove <name>\ncotal ext list\n```\n\nOperator-installed extensions: `add` installs an npm package into a cotal-owned prefix and records\nevery registry provider it contributes. Commands appear in help, completion, and dispatch; runtime\nproviders are lazy-loaded by commands such as `supervise`; local process providers participate in\n`status` and selective `down`. `remove` and `list` manage them. The `@cotal-ai/web` dashboard is the\ncanonical command/process example. Installed packages and their location are described in\n[config](config.md).\n\nRemoving an extension that owns a running local process is refused with the mesh root and its\n`cotal down <component>` command; stop it first so uninstalling the package never strands a process\nwhose lifecycle provider is gone.\n\n## completion\n\n```bash\ncotal completion <bash|zsh|fish|powershell> # print a stub to eval / source\ncotal completion install [shell] # install it persistently\n```\n\nPrints or installs shell completion. Completion candidates come from each command's declared flags\nand, where useful, live mesh state (spaces, personas, managed agents) resolved offline.\n\n## feedback\n\n```bash\ncotal feedback \"<summary>\" [--type <t>] [--email <e>] [--details <text>]\n```\n\n| Flag | Default | Meaning |\n|---|---|---|\n| `--type <t>` | \u2014 | `bug` \\| `idea` \\| `friction` \\| `praise` \\| `other` |\n| `--details <text>` | \u2014 | Longer free-form details |\n| `--severity <s>` | \u2014 | `low` \\| `medium` \\| `high` |\n| `--area <a>` | \u2014 | The part of Cotal this concerns |\n| `--email <e>` | git email | Contact email (required on the keyless public path) |\n| `--name <n>` | \u2014 | Your name (optional) |\n| `--url <url>` | keyed / public intake | Intake URL override |\n| `--key <k>` | `COTAL_FEEDBACK_KEY` | Feedback key |\n\nSends feedback to the Cotal developers. With a key (`--key` / `COTAL_FEEDBACK_KEY`) it routes to the\nkeyed beta intake; without one it goes to the public `cotal.ai` intake and requires a contact email\n(`--email` / `COTAL_FEEDBACK_EMAIL`, else your git email). Run a self-hosted intake with\n[`feedback-intake`](#server-daemons).\n\n## Server daemons\n\nTwo long-lived infra roles ship with the CLI. They are not part of everyday operation; the delivery\ndaemon comes up automatically with `cotal up --detach` in auth mode.\n\n```bash\ncotal deliver --space <s> [--server <url>] [--creds <file>]\ncotal auth-service --space <s> --server <url> [--port <n>]\ncotal feedback-intake --keys <keys.json> [--port <n>] [--creds <file>]\n```\n\n`auth-service` runs a user-auth space's identity plane (the NATS auth callout plus the\nloopback token exchange and JWKS); `cotal up --user-auth` starts and supervises it for you,\nso you run it directly only to recover one by hand.\n\n`deliver` runs the server-side Plane-3 delivery daemon: the durable backstop and membership/ACL\nauthority. It is auth-mode-only and single-instance (`--shard`/`--shards` accept only `N=1`);\n`--dev-mint` mints a scoped cred from the local signer for standalone dev. See the\n[delivery daemon](delivery-daemon.md). `feedback-intake` runs a self-hosted feedback server\n(requires `--keys` and a scoped `--creds`), announcing submissions into a space channel; flags\ninclude `--host`/`--port`, `--store`, `--space`/`--channel`, `--max-bytes`, and `--rate-limit`.\n\n## Plumbing\n\n`cotal __complete <words\u2026>` is the internal entry the shell-completion stubs call to emit candidates\nfor the current command line; you never run it directly. `cotal agent-bearer` is machine-facing\nplumbing on user-auth meshes: spawned agents exec it to print a fresh short-lived bearer from their\nspawn-time secret; you never run it directly either. (`cotal start` is a removed tombstone: it\nerrors and points you to `cotal spawn --detach`.)\n"
42325
+ "body": "# `cotal` CLI reference\n\n> **Reference**: describes the TypeScript reference implementation (the `cotal` CLI), not the wire contract. \xB7 **For:** operators \xB7 **Wire contract:** [SPEC](../SPEC.md)\n\n`cotal` is the operator command line for the reference implementation: bring a mesh up, mint\nidentities, launch agents, watch what they do, and tear it all down. It is a thin client over the\nwire contract: the normative subjects and schemas live in the [SPEC](../SPEC.md); this page is\nlookup material for the commands, not a walkthrough; if you are new, start with\n[Getting started](getting-started.md).\n\n## Running it\n\n```bash\nnpm install -g cotal-ai # puts `cotal` on your PATH (needs Node 20+)\ncotal --help # every command, grouped\ncotal <command> --help # one command's flags and usage\n```\n\n`npx cotal-ai <command>` runs it without a global install; in a dev clone, `pnpm cotal <command>`\nruns it through `tsx` with no build step. Bare `cotal` prints help. Every command generates its own\n`--help`, usage, and shell completion from its declared flags.\n\nCommands come from the surfaces the binary composes: the base mesh CLI, the manager\n(`supervise`), and the delivery daemon (`deliver`), plus any operator-installed extensions.\n`cotal ext add <npm-package>` installs any registry providers a package contributes: commands,\nruntimes, and local process lifecycle descriptors. The `web` dashboard and optional manager\nruntimes ship this way.\n\n## Commands\n\n| Area | Command | Purpose |\n|---|---|---|\n| Set up & lifecycle | [`setup`](#setup) | Guided, configure-only setup (installs, seeds personas; launches nothing) |\n| Set up & lifecycle | [`up`](#up) | Start a local mesh (nats-server + JetStream), or boot a whole manifest with `-f` |\n| Set up & lifecycle | [`down`](#down) | Stop the whole stack, selected registered components, or a manifest deploy |\n| Set up & lifecycle | [`clean`](#clean) | Configurable cleanup: purge history (live), or wipe the local store / identity (stopped) |\n| Set up & lifecycle | [`meshes`](#meshes-use-status) | List the running meshes on this machine |\n| Set up & lifecycle | [`use`](#meshes-use-status) | Set the default mesh a bare `cotal spawn` joins |\n| Set up & lifecycle | [`status`](#meshes-use-status) | Read-only diagnostics for setup, processes, and the selected mesh |\n| Agents & personas | [`spawn`](#spawn) | Launch an agent from a persona (foreground, or `--detach` via the manager) |\n| Agents & personas | [`models`](#models) | List connector model catalogs and variants from the manager |\n| Agents & personas | [`ps`](#ps-stop-attach) | List managed agents and their mesh status |\n| Agents & personas | [`stop`](#ps-stop-attach) | Ask the manager to stop a managed agent |\n| Agents & personas | [`attach`](#ps-stop-attach) | Stream and drive a managed agent's terminal (pty runtime) |\n| Agents & personas | [`personas`](#personas) | List, show, edit, create, or remove local personas |\n| Agents & personas | [`supervise`](#supervise) | Run a manager daemon (the agent supervisor / control plane) |\n| Agents & personas | [`runtimes`](#runtimes) | List the agent runtimes the manager can spawn through and whether each is reachable |\n| Messaging & watching | [`endpoints`](#endpoints) | List every endpoint in the live presence roster, including infrastructure |\n| Messaging & watching | [`send`](#send) | Send one message, then exit: DM a peer, post a channel, or ask a role |\n| Messaging & watching | [`channels`](#channels) | Inspect or set the channel registry (replay, description, instructions) |\n| Messaging & watching | [`history`](#history) | Clear retained message history |\n| Messaging & watching | [`console`](#console) | Live protocol view for a space (TUI, or `--plain` line stream) |\n| Messaging & watching | [`web`](#web) | Browser dashboard (installed as the `@cotal-ai/web` extension) |\n| Auth & meshes | [`mint`](#mint) | Mint a creds file for a space (static auth mode) |\n| Auth & meshes | [`login`](#login-logout) | Sign in to a per-user-auth mesh's IdP (once per machine) |\n| Auth & meshes | [`logout`](#login-logout) | Revoke the IdP session and clear the cached login |\n| Auth & meshes | [`actor`](#actor) | Manage a user-auth space's actor ledger (grant / revoke / list) |\n| Auth & meshes | [`doctor`](#doctor) | Credential-health diagnosis and repair (`doctor auth`) |\n| Auth & meshes | [`join`](#join) | Join a space as your own presence (interactive) |\n| Manifest | [`topology`](#manifest-deploys) | Validate and view a mesh manifest's access graph (read-only) |\n| Extensions & misc | [`ext`](#ext) | Install / remove operator CLI extensions |\n| Extensions & misc | [`completion`](#completion) | Print or install shell completion |\n| Extensions & misc | [`feedback`](#feedback) | Send feedback to the Cotal developers |\n| Extensions & misc | [`deliver`](#server-daemons) | Run the server-side Plane-3 delivery daemon |\n| Extensions & misc | [`feedback-intake`](#server-daemons) | Run a self-hosted feedback intake server |\n\nThe manifest modes of `up`, `spawn`, and `down` (`-f <cotal.yaml>`) plus `topology` are covered\ntogether under [Manifest deploys](#manifest-deploys).\n\n## setup\n\n```bash\ncotal setup [--full] [--demo] [--yes]\n```\n\n| Flag | Default | Meaning |\n|---|---|---|\n| `--full` | off | Redo the full guided flow (implies `--demo`) |\n| `--demo` | off | Also seed the guided expert team (`david`, `sven`, `me`) |\n| `--yes`, `-y` | off | Non-interactive accept-all (for agents / CI) |\n\nGuided setup is **configure-only**: it checks prerequisites, installs the Claude Code plugin, and\nseeds persona files, and it launches nothing (no mesh, no web, no manager). First run gets the\nnarrated flow; later runs print a status card. By default it seeds one `default` persona; the\n`david`/`sven`/`me` team is opt-in via `--demo`. See [Getting started](getting-started.md) and, for\nmaintainers, [setup internals](setup-internals.md).\n\n## up\n\n```bash\ncotal up [--detach] [--open] [--space <s>] [--server <url>] [--channels <path>] [--runtime <name>]\ncotal up -f <cotal.yaml> [--dry-run] [--runtime <name>]\n```\n\n| Flag | Default | Meaning |\n|---|---|---|\n| `--server <url>` | auto (free local port) | Listen URL override |\n| `--host <host>` | \u2014 | Bind host override |\n| `--space <s>` | the folder's name | Space name |\n| `--store-dir <dir>` | \u2014 | JetStream store directory |\n| `--channels <path>` | `.cotal/channels.json` if present | Channel-registry seed file (JSON). An explicit path that is missing is an error |\n| `--open` | off (auth) | Unauthenticated dev mesh: no JWT, no ACLs |\n| `--user-auth` | off | Per-user auth: people `cotal login`; connects are authorized against the actor ledger |\n| `--idp <url>` | \u2014 | With `--user-auth`: the IdP auth base URL to pin on first enable |\n| `--detach` | off | Run in the background (stop with `cotal down`) |\n| `--file <cotal.yaml>`, `-f` | \u2014 | Launch a whole mesh from a manifest |\n| `--dry-run` | off | With `-f`: print the plan, mutate nothing |\n| `--runtime <name>` | `pty` (or the manifest's, with `-f`) | Agent runtime for the mesh manager (`pty` built in; others are installed extensions, explicit-only). Resolved + probed before the broker starts; an uninstalled/unreachable runtime fails loud. With `-f`, overrides the manifest's runtime |\n\n`cotal up` boots a local nats-server with JetStream and, in auth mode (the default), JWT auth and\nper-agent ACLs; `--detach` records the mesh so `cotal spawn` from any directory can find it. With no\n`--server`, it auto-selects a free port if the default address is taken; an explicit `--server`\nstays fail-loud on collision. `--detach` also brings up the control plane (delivery daemon in auth\nmode, then the manager). The `-f` form is a [manifest deploy](#manifest-deploys); see\n[Run a mesh](run-a-mesh.md).\n\n`--user-auth --idp <url>` starts the space's auth service alongside the broker (the NATS\nauth callout plus the loopback token exchange); it is torn down with `cotal down`, and a\nre-run of `cotal up` heals a dead service on a running broker. `--user-auth` and `--open`\ncontradict each other and are refused loudly; a running broker cannot change auth mode\nwithout a `cotal down` first. See [identity & auth](identity-and-auth.md).\n\n## down\n\n```bash\ncotal down\ncotal down manager [delivery auth web nats ...]\ncotal down -f <cotal.yaml> | --run <id> [--dry-run]\n```\n\n| Flag | Default | Meaning |\n|---|---|---|\n| `--file <cotal.yaml>`, `-f` | \u2014 | Tear down this manifest's deploy |\n| `--run <id>` | \u2014 | Tear down one `spawn -f` run by id |\n| `--dry-run` | off | Print the manifest teardown or selected components, mutate nothing |\n\nBare `cotal down` stops the whole local stack in dependency order. Positional component names stop\nonly those self-registered local processes; for example, `cotal down manager` leaves delivery and\nthe broker running, and `cotal down web` is available when the web extension is installed. The\n`-f` / `--run` forms tear down a [manifest deploy](#manifest-deploys) without stopping the whole mesh\nand cannot be combined with component names. Stopping `nats` alone is refused while an unselected\nregistered daemon is still live; include those components or use bare `cotal down`.\n\n`down` never deletes on-disk state; that is [`clean`](#clean).\n\n## clean\n\n```bash\ncotal clean <history|store|all> --force\n```\n\n| Flag | Default | Meaning |\n|---|---|---|\n| `--space <s>` / `--server <url>` / `--creds <path>` | resolved mesh | `history`: target mesh |\n| `--dms` | off | `history`: also clear DM history |\n| `--store-dir <dir>` | `.cotal/nats` | `store`/`all`: JetStream store directory |\n| `--force` | \u2014 | Required: destructive, no prompting |\n\nOne configurable cleanup verb; every target requires `--force`.\n\n- `history` purges the retained message backlog on the **running** broker (channels, plus DMs\n with `--dms`). The same operation as [`history clear`](#history), which stays as an alias.\n- `store` deletes the **stopped** mesh's JetStream store (`.cotal/nats`): streams, durable\n consumers, and messages. This is the reset for stale on-disk broker state, e.g. durables\n minted by an older, incompatible Cotal generation surviving a `down`/`up` cycle.\n- `all` is `store` plus the space identity (`.cotal/auth`), the local creds and markers tied to\n it, any crash residue a normal `down` would have swept (stale pidfiles, `run/`), and the mesh's\n registry entry; the next `cotal up` mints a fresh identity.\n\n`history` needs the mesh up; `store` and `all` refuse while any recorded mesh process is still\nalive (run `cotal down` first). Personas (`.cotal/agents`) and logs are never touched. A custom\nstore location is not recorded anywhere, so `--store-dir` must repeat whatever the mesh was\nlaunched with.\n\n## meshes, use, status\n\n```bash\ncotal meshes\ncotal use <space>\ncotal status [--space <s>] [--server <url>]\n```\n\n`meshes` lists the running meshes on this machine; a `*` marks the `current` default a bare\n`cotal spawn` joins. `use <space>` sets that default when several are running. `status` is a\nread-only report across four sections: machine prerequisites, this folder's `.cotal/`, the\nrecorded meshes, and a live snapshot of the selected mesh (roster, channels, membership feed).\n`status` takes only `--space` / `--server` to pick the mesh to inspect; it starts nothing.\n\n## spawn\n\n```bash\ncotal spawn [<persona>] [--detach] [--name <n>] [--agent <a>] [--model <m>] [--variant <v>] [--prompt <text>] [--cwd <dir>]\ncotal spawn -f <cotal.yaml> [--dry-run]\n```\n\n| Flag | Default | Meaning |\n|---|---|---|\n| `--space <s>` | resolved mesh | Target space |\n| `--server <url>` | registry entry | Broker URL override |\n| `--creds <path>` | \u2014 | Control-caller creds for an off-registry manager (`--detach` only) |\n| `--name <n>` | persona's `name:` | Presence-name override (does not choose the persona) |\n| `--config <persona-or-path>` | \u2014 | Persona catalog name or file path; wins over the positional |\n| `--agent <a>` | `COTAL_DEFAULT_AGENT`, else `claude` | Connector type (`claude`, `opencode`, `hermes`, \u2026) |\n| `--role <r>` | persona's `role:` | Role override |\n| `--model <m>` | persona's `model:` | Model override |\n| `--variant <v>` | persona's `variant:` | Model variant override (connector-defined; e.g. OpenCode reasoning tiers) |\n| `--cwd <dir>` | this cwd | Working directory to root the agent at |\n| `--prompt <text>` | \u2014 | Initial prompt auto-submitted at start |\n| `--resume <id>` | \u2014 | Fork an existing session id into the mesh (claude only) |\n| `--transcript` / `--no-transcript` | off | Mirror the session transcript to `tr-<name>` |\n| `--share-tools <sel>` | none | Share named operator MCP servers with the agent |\n| `--subscribe <a,b>` | persona's | Channel read-set override |\n| `--allow-subscribe <a,b>` | = subscribe | Read-ACL override |\n| `--allow-publish <a,b>` | deny | Post-ACL override |\n| `--detach`, `-d` | off | Launch via the manager into a detached PTY (reattach with `cotal attach`) |\n| `--file <cotal.yaml>`, `-f` | \u2014 | Deploy a manifest onto the running mesh |\n| `--dry-run` | off | With `-f`: print the plan, mutate nothing |\n| `--allow-stale <a,b>` | \u2014 | With `-f`: waive named stale agents (apply-only) |\n| `--runtime <name>` | manifest's | With `-f`: override the manifest's runtime |\n\nThe persona (`--config` > positional > `COTAL_DEFAULT_PERSONA` > `default`) is loaded from the\ntarget mesh's `.cotal/agents/`; the launch flags override the file. Foreground runs the agent\nattached to your terminal; `--detach` hands the launch to the running manager. `--detach` is the\nonly mode that registers a durable delivery membership; a foreground spawn reads live only. See\n[Connect Claude Code](connect-claude.md) and [Agent files](agent-files.md); `-f` is a\n[manifest deploy](#manifest-deploys). (`cotal start` was merged into `cotal spawn --detach`.)\n\n## models\n\n```bash\ncotal models [--agent <connector>] [--refresh]\n```\n\n| Flag | Default | Meaning |\n|---|---|---|\n| `--space <s>` / `--server <url>` / `--creds <path>` | resolved mesh | Which manager to reach |\n| `--agent <connector>` | all registered connectors | Connector whose catalog to list |\n| `--refresh` | off | Ask the connector to refresh its provider cache |\n\nAsks the running manager for each connector's model catalog (model ids plus their variants)\nfor connectors that expose one (OpenCode today; a connector without a catalog says so). Pick a\nresult with `cotal spawn --model <provider/model> --variant <v>`.\n\n## endpoints\n\n```bash\ncotal endpoints [--space <s>] [--server <url>] [--creds <path>]\n```\n\nLists the mesh presence roster: agents, the manager, and any other protocol endpoint, with each\nendpoint's role, kind, status, and current activity. Unlike `ps`, this is a read-only presence view;\nit is not limited to child processes owned by the manager.\n\n## ps, stop, attach\n\n```bash\ncotal ps [--space <s>]\ncotal stop --name <n> [--space <s>]\ncotal attach --name <n> [--space <s>]\n```\n\n| Flag | Default | Meaning |\n|---|---|---|\n| `--space <s>` / `--server <url>` / `--creds <path>` | resolved mesh | Which manager to reach |\n| `--name <n>` | \u2014 | Managed agent to stop / attach (required) |\n\nThese are operator clients over the running manager's control plane. `ps` lists managed agents with\ntheir mesh status (`starting\u2026` / `working` / `waiting` / `offline`); on a user-auth mesh it also\nrenders each managed agent's last credential-refresh outcome, fail-closed. `attach` streams and\ndrives an agent's terminal on the `pty` runtime; detach with the escape key (Ctrl-] by default; see\n[`COTAL_DETACH_KEY`](config.md)). `stop` and `attach` need a running manager to talk to. On a\nstatic mesh they are cross-agent admin operations. On a user-auth mesh, your own agents (any agent\nunder your owner) need only the `spawn` scope; another owner's agent needs `admin` on your ledger\nrow ([identity & auth](identity-and-auth.md)). Launch detached agents with\n[`spawn --detach`](#spawn).\n\n## personas\n\n```bash\ncotal personas list [-v] [--running]\ncotal personas show <name>\ncotal personas edit <name>\ncotal personas new <name> (--prompt <t> | --from <f>) [--role <r>] [--model <m>]\ncotal personas rm <name> --force\n```\n\n| Flag | Default | Meaning |\n|---|---|---|\n| `--space <s>` / `--server <url>` / `--creds <path>` | resolved mesh | Which mesh's persona catalog |\n| `--role <r>` | \u2014 | `new`: the persona's role |\n| `--model <m>` | \u2014 | `new`: the persona's model |\n| `--prompt <t>` | \u2014 | `new`: the persona's prompt text |\n| `--from <f>` | \u2014 | `new`: seed the prompt from a file |\n| `--verbose`, `-v` | off | `list`: include role / model / description |\n| `--running` | off | `list`: mark personas live on the mesh |\n| `--force` | \u2014 | `rm`: required, delete without prompting |\n\nPersonas are the local agent files under `.cotal/agents/` that `cotal spawn` launches. See\n[Agent files](agent-files.md) for the file format.\n\n## supervise\n\n```bash\ncotal supervise [--runtime <name>] [--space <s>] [--server <url>] [--spawn <names>]\n```\n\n| Flag | Default | Meaning |\n|---|---|---|\n| `--space <s>` | this folder's auth space | Space to supervise |\n| `--server <url>` | the local mesh | Broker URL |\n| `--runtime <name>` | `pty` | Agent runtime (`pty` built in; extension runtimes are explicit-only) |\n| `--console-port <n>` | \u2014 | Protocol-console port |\n| `--roster <file>` | \u2014 | Declarative roster to boot at startup |\n| `--launch <spec>` | \u2014 | Resolved manifest launch spec (from `up -f` / `spawn -f`) |\n| `--spawn <names>` | \u2014 | Comma-separated personas to pre-spawn at startup |\n\nThe manager is the agent supervisor and control plane: it answers `spawn --detach`, `stop`, `ps`,\n`attach`, and the `cotal_*` manager tools. `cotal up --detach` starts one for you; run `supervise`\ndirectly to recover a dead manager or drive a custom runtime. Default runtime is `pty`; install an\noptional provider first (`cotal ext add @cotal-ai/orca`, `@cotal-ai/tmux`, or `@cotal-ai/cmux`) and\nselect it explicitly. A missing provider or app fails loudly; there is no fallback. See [Deploy](deploy.md).\n\n## runtimes\n\n```bash\ncotal runtimes\n```\n\nLists every agent runtime the manager can spawn through: the built-in `pty`, the official providers\n(`orca`, `tmux`, `cmux`), and any custom provider installed via `cotal ext add`. Each installed\nprovider is probed so you can see what is actually reachable on this machine before selecting it:\n\n```\npty built in\norca installed \xB7 reachable @cotal-ai/orca\ntmux available \xB7 cotal ext add @cotal-ai/tmux\ncmux available \xB7 cotal ext add @cotal-ai/cmux\n```\n\n`installed \xB7 reachable` / `unreachable` is the provider's own `available()` probe; `available` means\nit is a known runtime you can add with the shown command. Selecting an unknown or uninstalled runtime\nvia `up`/`spawn --runtime <name>` fails loud and, for a known one, points at the exact `cotal ext add`\npackage \u2014 there is no silent fallback to `pty`.\n\n## send\n\n```bash\ncotal send dm <agent> \"<text>\" [--space <s>] [--server <url>] [--creds <path>]\ncotal send msg <channel> \"<text>\"\ncotal send ask <role> \"<text>\"\n```\n\n| Flag | Default | Meaning |\n|---|---|---|\n| `--space <s>` / `--server <url>` / `--creds <path>` | resolved mesh | Which mesh, and (off-registry) which credential |\n\nOne-shot messaging: connect, send a single direct message (`dm`), channel post (`msg`), or role\nask/anycast (`ask`), then exit. For a running conversation, agents use the mesh tools instead\n([MCP tools](mcp-tools.md)).\n\n## channels\n\n```bash\ncotal channels list\ncotal channels set <name> [--replay | --no-replay] [--window <n>] [--desc <s>] [--instructions <s>]\ncotal channels default --replay | --no-replay\n```\n\n| Flag | Default | Meaning |\n|---|---|---|\n| `--space <s>` / `--server <url>` / `--creds <path>` | resolved mesh | Target mesh |\n| `--replay` / `--no-replay` | \u2014 | `set`/`default`: replay history to new joiners, or not |\n| `--window <n>` | \u2014 | `set`: replay window size |\n| `--desc <s>` | \u2014 | `set`: one-line channel description |\n| `--instructions <s>` | \u2014 | `set`: instructions shown to joiners |\n\nInspects and edits the channel registry: replay policy, description, and joiner instructions. ACL\nsemantics (who may read or post) are set at mint / provision time, not here; see\n[Channels and permissions](channels-and-permissions.md). On a user-auth mesh, `list` rides your\nown login as is; `set` and `default` edit the registry over a short-lived channel-writer view,\nwhich needs ledger scope `admin` ([Identity & auth](identity-and-auth.md)).\n\n## history\n\n```bash\ncotal history clear --force [--dms] [--space <s>]\n```\n\n| Flag | Default | Meaning |\n|---|---|---|\n| `--space <s>` / `--server <url>` / `--creds <path>` | resolved mesh | Target mesh |\n| `--dms` | off | Also clear DM history |\n| `--force` | \u2014 | Required: clear without prompting |\n\nPurges retained channel history; `--dms` extends it to direct-message history. An alias of\n[`clean history`](#clean). On a user-auth mesh the purge rides a short-lived purger view over\nyour login, which needs ledger scope `admin` ([Identity & auth](identity-and-auth.md)).\n\n## console\n\n```bash\ncotal console [--plain] [--space <s>]\n```\n\n| Flag | Default | Meaning |\n|---|---|---|\n| `--space <s>` / `--server <url>` / `--creds <path>` | resolved mesh | Space to watch |\n| `--plain` | off | Line stream instead of the TUI |\n\nA live protocol view for a space: a lazygit-style TUI, or a plain line stream on `--plain`. On a\nuser-auth mesh it rides the read-only admin view over your login, which needs ledger scope\n`admin`. See [Watch a mesh](watch-a-mesh.md).\n\n## web\n\n```bash\ncotal ext add @cotal-ai/web # install once\ncotal web [--port <n>] [--no-open] [--space <s>]\n```\n\n| Flag | Default | Meaning |\n|---|---|---|\n| `--space <s>` / `--server <url>` / `--creds <path>` | resolved mesh | Space to serve |\n| `--port <n>` | `7799` | HTTP port |\n| `--no-open` | off | Don't open the browser |\n\nThe browser observability dashboard: presence, channels, and a live feed. It is **not** part of\n`cotal up`: it ships as the `@cotal-ai/web` extension (`cotal setup` installs it automatically; otherwise\n`cotal ext add @cotal-ai/web`). It self-registers `cotal web` into this surface and serves\n`http://cotal.localhost:7799` (loopback; `*.localhost` resolves in Chrome/Firefox/Edge; Safari may\nneed `http://127.0.0.1:7799`). On a user-auth mesh the dashboard rides the read-only admin view\nover your login, and a channel purge asks for its own channel-purger view per click; both need\nledger scope `admin`. See [Watch a mesh](watch-a-mesh.md).\n\n## mint\n\n```bash\ncotal mint <name> [--profile <agent|observer|admin>] [--out <path>] [--signer]\n```\n\n| Flag | Default | Meaning |\n|---|---|---|\n| `--profile <agent\\|observer\\|admin>` | `agent` | Credential profile |\n| `--out <path>` | `.cotal/auth/creds/<name>.creds` | Output path |\n| `--signer` | off | Emit a stripped account-signing file instead |\n| `--force` | off | With `--signer`: overwrite an existing file |\n| `--allow-subscribe <a,b>` | profile default | Read-ACL override |\n| `--allow-publish <a,b>` | profile default | Post-ACL override |\n\nMints a NATS creds file for a space in **static** auth mode, scoped to a profile and (optionally)\nexplicit read/post ACLs. `--signer` emits an account-signing file for delegating minting to another\nhost. A per-user-auth space refuses `mint`: agents there join under a logged-in user\n([`login`](#login-logout) + [`actor grant`](#actor)), never via a handed-out creds file. See\n[Identity and auth](identity-and-auth.md).\n\n## login, logout\n\n```bash\ncotal login --idp <auth base URL> [--client-id <id>]\ncotal logout --idp <auth base URL>\n```\n\nSigns you in to a per-user-auth mesh's IdP (device code flow) and caches the session; run it\nonce per machine. It prints your IdP subject, the id the operator grants against. After a\nlogin, every command on that mesh works under your identity: each connect takes a fresh IdP\nproof, exchanges it locally for a short-lived bearer, and is authorized against the actor\nledger at connect time. `logout` revokes the IdP session and clears the cache. See\n[identity & auth](identity-and-auth.md).\n\n## actor\n\n```bash\ncotal actor grant <actor> --sub <IdP subject> [--scope a,b] [--allow-subscribe a,b] [--allow-publish a,b] [--role <r>] [--label <l>]\ncotal actor revoke <actor> (--sub <IdP subject> | --owner <u_\u2026>)\ncotal actor list\n```\n\n| Flag | Default | Meaning |\n|---|---|---|\n| `--space <s>` | the folder's | Space whose ledger to manage |\n| `--sub <subject>` | \u2014 | The IdP subject (shown by `cotal login`) the actor belongs to |\n| `--owner <u_\u2026>` | \u2014 | The derived owner token (alternative to `--sub`) |\n| `--scope <a,b>` | `spawn,role:default` | Capability scope (`''` = none; `spawn` = may run agents, `role:<r>` = may delegate role r, `admin` = cross-agent control) |\n| `--allow-subscribe <a,b>` | `>` (all channels) | Channel read ACL; the user's envelope, their agents can never read beyond it |\n| `--allow-publish <a,b>` | `>` (all channels) | Channel post ACL; also the envelope for their agents' posting |\n| `--role <r>` | \u2014 | Role (scopes the task-queue consumer) |\n| `--label <l>` | \u2014 | Display label for `actor list` (never the IdP subject) |\n\nThe actor ledger is the single authorization source of a user-auth space: no row, no access.\nA bare `grant` is the **full** envelope (all channels, may spawn); the flags narrow it. A\nre-grant **replaces** the row, so to add a capability, re-grant with it added to the current\nscope (`cotal actor list` shows what a row holds). `revoke` denies the next exchange and the\nnext connect with no restart, and evicts the principal's live connections. Managed-agent rows\n(written by the spawn path) live in a disjoint row space this command never touches. See\n[identity & auth](identity-and-auth.md).\n\n## doctor\n\n```bash\ncotal doctor auth [--fix]\n```\n\nCredential-health diagnosis and repair for this folder's mesh: renders every managed\ncredential as healthy / near-expiry / expired and ends in `healthy` or the exact next\ncommand; `--fix` applies the repairs it can. The one surface every stale-credential error\npoints at.\n\n## join\n\n```bash\ncotal join --space <s> --name <n> [--role <r>] [--channel <c>]\ncotal join --link <url> | --token <t>\n```\n\n| Flag | Default | Meaning |\n|---|---|---|\n| `--space <s>` / `--server <url>` / `--creds <path>` | resolved mesh | Which mesh, and which credential |\n| `--name <n>` | \u2014 | Your presence name |\n| `--role <r>` | \u2014 | Your role |\n| `--channel <c>` | \u2014 | Channel to join |\n| `--kind <k>` | `agent` | Endpoint kind |\n| `--link <url>` | \u2014 | Join link (`cotal://\u2026`) |\n| `--token <t>` | \u2014 | Join token |\n| `--tls` | off | Connect over TLS |\n\nAn interactive presence: join a space under your own name and role, without launching an agent\nharness. A `--link` or `--token` supplies the where and the auth in one value. See\n[Spaces](spaces.md) and [Identity and auth](identity-and-auth.md).\n\n## Manifest deploys\n\nA `cotal.yaml` manifest declares a whole mesh (channels, personas, roles, and ACLs) in one file.\nThree commands consume it, plus a read-only validator:\n\n```bash\ncotal up -f cotal.yaml # boot a fresh mesh from the manifest\ncotal spawn -f cotal.yaml # deploy the manifest additively onto a running mesh\ncotal down -f cotal.yaml # tear that deploy down (or --run <id> for one run)\ncotal topology view -f cotal.yaml # validate + view the access graph, change nothing\n```\n\n`up -f` and `spawn -f` differ in target: `up -f` brings up a new broker and applies the manifest;\n`spawn -f` requires an already-reachable mesh and applies additively (ownership-scoped). On a\nuser-auth mesh, `spawn -f` deploys over your own login (the deployer view, gated on ledger scope\n`spawn`): the manifest's agents land under your owner, a manifest claiming another owner is\nrefused, and seeding new channels additionally needs scope `admin`. Both take\n`--dry-run` to print the plan without mutating anything. `topology` validates the manifest and\nrenders its channel / role / ACL graph. See [Define a team](define-a-team.md) and the\n[manifest reference](manifest.md).\n\n## ext\n\n```bash\ncotal ext add <npm-package>\ncotal ext remove <name>\ncotal ext list\n```\n\nOperator-installed extensions: `add` installs an npm package into a cotal-owned prefix and records\nevery registry provider it contributes. Commands appear in help, completion, and dispatch; runtime\nproviders are lazy-loaded by commands such as `supervise`; local process providers participate in\n`status` and selective `down`. `remove` and `list` manage them. The `@cotal-ai/web` dashboard is the\ncanonical command/process example. Installed packages and their location are described in\n[config](config.md).\n\nRemoving an extension that owns a running local process is refused with the mesh root and its\n`cotal down <component>` command; stop it first so uninstalling the package never strands a process\nwhose lifecycle provider is gone.\n\n## completion\n\n```bash\ncotal completion <bash|zsh|fish|powershell> # print a stub to eval / source\ncotal completion install [shell] # install it persistently\n```\n\nPrints or installs shell completion. Completion candidates come from each command's declared flags\nand, where useful, live mesh state (spaces, personas, managed agents) resolved offline.\n\n## feedback\n\n```bash\ncotal feedback \"<summary>\" [--type <t>] [--email <e>] [--details <text>]\n```\n\n| Flag | Default | Meaning |\n|---|---|---|\n| `--type <t>` | \u2014 | `bug` \\| `idea` \\| `friction` \\| `praise` \\| `other` |\n| `--details <text>` | \u2014 | Longer free-form details |\n| `--severity <s>` | \u2014 | `low` \\| `medium` \\| `high` |\n| `--area <a>` | \u2014 | The part of Cotal this concerns |\n| `--email <e>` | git email | Contact email (required on the keyless public path) |\n| `--name <n>` | \u2014 | Your name (optional) |\n| `--url <url>` | keyed / public intake | Intake URL override |\n| `--key <k>` | `COTAL_FEEDBACK_KEY` | Feedback key |\n\nSends feedback to the Cotal developers. With a key (`--key` / `COTAL_FEEDBACK_KEY`) it routes to the\nkeyed beta intake; without one it goes to the public `cotal.ai` intake and requires a contact email\n(`--email` / `COTAL_FEEDBACK_EMAIL`, else your git email). Run a self-hosted intake with\n[`feedback-intake`](#server-daemons).\n\n## Server daemons\n\nTwo long-lived infra roles ship with the CLI. They are not part of everyday operation; the delivery\ndaemon comes up automatically with `cotal up --detach` in auth mode.\n\n```bash\ncotal deliver --space <s> [--server <url>] [--creds <file>]\ncotal auth-service --space <s> --server <url> [--port <n>]\ncotal feedback-intake --keys <keys.json> [--port <n>] [--creds <file>]\n```\n\n`auth-service` runs a user-auth space's identity plane (the NATS auth callout plus the\nloopback token exchange and JWKS); `cotal up --user-auth` starts and supervises it for you,\nso you run it directly only to recover one by hand.\n\n`deliver` runs the server-side Plane-3 delivery daemon: the durable backstop and membership/ACL\nauthority. It is auth-mode-only and single-instance (`--shard`/`--shards` accept only `N=1`);\n`--dev-mint` mints a scoped cred from the local signer for standalone dev. See the\n[delivery daemon](delivery-daemon.md). `feedback-intake` runs a self-hosted feedback server\n(requires `--keys` and a scoped `--creds`), announcing submissions into a space channel; flags\ninclude `--host`/`--port`, `--store`, `--space`/`--channel`, `--max-bytes`, and `--rate-limit`.\n\n## Plumbing\n\n`cotal __complete <words\u2026>` is the internal entry the shell-completion stubs call to emit candidates\nfor the current command line; you never run it directly. `cotal agent-bearer` is machine-facing\nplumbing on user-auth meshes: spawned agents exec it to print a fresh short-lived bearer from their\nspawn-time secret; you never run it directly either. (`cotal start` is a removed tombstone: it\nerrors and points you to `cotal spawn --detach`.)\n"
42319
42326
  },
42320
42327
  {
42321
42328
  "slug": "config",
@@ -42406,7 +42413,7 @@ var DOCS_BUNDLE = {
42406
42413
  "title": "Release and publish",
42407
42414
  "kind": "Project (non-normative maintainer notes)",
42408
42415
  "summary": "Cotal uses Changesets to version and publish the workspace packages under packages/, extensions/, and implementations/ to npm.",
42409
- "body": "# Release and publish\n\n> **Project** (non-normative maintainer notes) \xB7 **For:** maintainers shipping Cotal\n\nCotal uses [Changesets](https://github.com/changesets/changesets) to version and publish the\nworkspace packages under `packages/*`, `extensions/*`, and `implementations/*` to npm.\n`examples/**` is ignored, since it is not published.\n\n## 0.11 runtime migration\n\nThe published binary no longer bundles the optional tmux and cmux runtimes. Existing operators\nmust run `cotal ext add @cotal-ai/tmux` or `cotal ext add @cotal-ai/cmux` once after upgrading,\nbefore using `runtime: tmux|cmux` in a manifest or passing `--runtime tmux|cmux`. Missing runtimes\nfail loudly with the matching install command; they never fall back to pty.\n\n## One-time npm setup: trusted publishing (OIDC)\n\nTrusted publishing replaces the long-lived `NPM_TOKEN` secret with short-lived OIDC tokens\nissued by GitHub Actions. Each published package must be configured once on npmjs.com.\n\nFor **every** published package (`@cotal-ai/core`, `@cotal-ai/cli`, `@cotal-ai/manager`,\n`@cotal-ai/delivery`, `@cotal-ai/connector-core`, `@cotal-ai/connector-claude-code`,\n`@cotal-ai/connector-opencode`, `@cotal-ai/connector-hermes`, `@cotal-ai/cmux`, `@cotal-ai/orca`, and the\n`cotal-ai` binary):\n\n1. Go to `https://www.npmjs.com/package/<name>/access` (e.g.\n `https://www.npmjs.com/package/@cotal-ai/core/access`).\n2. Scroll to **Trusted publishing** \u2192 **Add a trusted publisher**.\n3. Pick **GitHub Actions**.\n4. Fill in:\n - **Organization or user:** the GitHub owner (your org or user).\n - **Repository:** `SWARL` (or whatever this repo is called).\n - **Workflow filename:** `changesets.yml`.\n - **Environment name:** leave blank.\n5. Save. Repeat for every package.\n\n> The first time, you may need to publish a version manually (with a classic token) so the\n> package exists on npm. After that, OIDC takes over.\n\n## Day-to-day flow\n\n1. Open a PR that changes code in a publishable package.\n2. Add a changeset describing the change:\n\n ```bash\n pnpm changeset\n ```\n\n Pick the affected packages plus the semver bump (patch / minor / major), and write a\n one-line summary. Commit the generated `.changeset/<name>.md` file alongside your code\n change.\n3. Merge to `main`.\n4. The `Changesets` workflow runs:\n - If there are pending changesets, it opens (or updates) a PR titled `chore(release):\n version packages` that bumps versions and updates `CHANGELOG.md` files.\n - When **that** PR is merged, the same workflow detects the bumped versions, runs `pnpm\n build`, and `pnpm publish`es each changed package to npm with provenance.\n\n## Manual publish (escape hatch)\n\nIf the workflow is broken, you can run the same steps locally with a classic npm token:\n\n```bash\npnpm ci:version\npnpm ci:publish\n```\n\nSet `NPM_TOKEN` in your environment first. **Do not** commit the token.\n\n## How `ci:publish` is wired\n\n`ci:publish` in the root `package.json` is:\n\n```bash\npnpm publish -r --provenance --access=public --no-git-checks\n```\n\n- `-r`: recursively publish all workspace packages.\n- `--provenance`: emit SLSA provenance attestations (a no-op without OIDC, automatic with it).\n- `--access=public`: required for scoped packages on first publish.\n- `--no-git-checks`: skip pnpm's branch / clean-tree guard, since CI does not need it.\n"
42416
+ "body": "# Release and publish\n\n> **Project** (non-normative maintainer notes) \xB7 **For:** maintainers shipping Cotal\n\nCotal uses [Changesets](https://github.com/changesets/changesets) to version and publish the\nworkspace packages under `packages/*`, `extensions/*`, and `implementations/*` to npm.\n`examples/**` is ignored, since it is not published.\n\n## 0.11 runtime migration\n\nThe published binary no longer bundles the optional tmux and cmux runtimes. Existing operators\nmust run `cotal ext add @cotal-ai/tmux` or `cotal ext add @cotal-ai/cmux` once after upgrading,\nbefore using `runtime: tmux|cmux` in a manifest or passing `--runtime tmux|cmux`. Missing runtimes\nfail loudly with the matching install command; they never fall back to pty.\n\n## One-time npm setup: trusted publishing (OIDC)\n\nTrusted publishing replaces the long-lived `NPM_TOKEN` secret with short-lived OIDC tokens\nissued by GitHub Actions. Each published package must be configured once on npmjs.com.\n\nFor **every** published package (`@cotal-ai/core`, `@cotal-ai/cli`, `@cotal-ai/manager`,\n`@cotal-ai/delivery`, `@cotal-ai/connector-core`, `@cotal-ai/connector-claude-code`,\n`@cotal-ai/connector-opencode`, `@cotal-ai/connector-hermes`, `@cotal-ai/pi`, `@cotal-ai/cmux`, `@cotal-ai/orca`, and the\n`cotal-ai` binary):\n\n1. Go to `https://www.npmjs.com/package/<name>/access` (e.g.\n `https://www.npmjs.com/package/@cotal-ai/core/access`).\n2. Scroll to **Trusted publishing** \u2192 **Add a trusted publisher**.\n3. Pick **GitHub Actions**.\n4. Fill in:\n - **Organization or user:** the GitHub owner (your org or user).\n - **Repository:** `SWARL` (or whatever this repo is called).\n - **Workflow filename:** `changesets.yml`.\n - **Environment name:** leave blank.\n5. Save. Repeat for every package.\n\n> The first time, you may need to publish a version manually (with a classic token) so the\n> package exists on npm. After that, OIDC takes over.\n\n## Day-to-day flow\n\n1. Open a PR that changes code in a publishable package.\n2. Add a changeset describing the change:\n\n ```bash\n pnpm changeset\n ```\n\n Pick the affected packages plus the semver bump (patch / minor / major), and write a\n one-line summary. Commit the generated `.changeset/<name>.md` file alongside your code\n change.\n3. Merge to `main`.\n4. The `Changesets` workflow runs:\n - If there are pending changesets, it opens (or updates) a PR titled `chore(release):\n version packages` that bumps versions and updates `CHANGELOG.md` files.\n - When **that** PR is merged, the same workflow detects the bumped versions, runs `pnpm\n build`, and `pnpm publish`es each changed package to npm with provenance.\n\n## Manual publish (escape hatch)\n\nIf the workflow is broken, you can run the same steps locally with a classic npm token:\n\n```bash\npnpm ci:version\npnpm ci:publish\n```\n\nSet `NPM_TOKEN` in your environment first. **Do not** commit the token.\n\n## How `ci:publish` is wired\n\n`ci:publish` in the root `package.json` is:\n\n```bash\npnpm publish -r --provenance --access=public --no-git-checks\n```\n\n- `-r`: recursively publish all workspace packages.\n- `--provenance`: emit SLSA provenance attestations (a no-op without OIDC, automatic with it).\n- `--access=public`: required for scoped packages on first publish.\n- `--no-git-checks`: skip pnpm's branch / clean-tree guard, since CI does not need it.\n"
42410
42417
  },
42411
42418
  {
42412
42419
  "slug": "roadmap",
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@cotal-ai/connector-opencode",
3
3
  "description": "Cotal connector for OpenCode: a native in-process plugin that joins a session to the mesh.",
4
- "version": "0.11.2",
4
+ "version": "0.11.3",
5
5
  "license": "Apache-2.0",
6
6
  "repository": {
7
7
  "type": "git",
@@ -18,7 +18,7 @@
18
18
  }
19
19
  },
20
20
  "dependencies": {
21
- "@cotal-ai/connector-core": "0.11.2"
21
+ "@cotal-ai/connector-core": "0.11.3"
22
22
  },
23
23
  "peerDependencies": {
24
24
  "@cotal-ai/core": ">=0.1.0",
@@ -30,7 +30,7 @@
30
30
  "@opencode-ai/sdk": "^1.16.2",
31
31
  "esbuild": "^0.28.0",
32
32
  "tsx": "^4.22.4",
33
- "@cotal-ai/core": "0.11.2"
33
+ "@cotal-ai/core": "0.11.3"
34
34
  },
35
35
  "files": [
36
36
  "dist"