Cotal
DocsAPI Reference
Operate a mesh

Register a mesh

Use the mesh registry to choose a space from any directory. Register a remote mesh before launching agents against it. For a new local space, start with Configure a space.

Choose a mesh

List the meshes this machine knows, then select one:

cotal meshes
cotal use <name>

The selected mesh becomes the default even inside another mesh's project folder. Pass --space <name> to target a different mesh for one command. A bare cotal spawn <persona> can then find the selected mesh's credentials and personas from any directory.

A selected mesh stays selected when its broker is offline. Commands report that failure instead of connecting elsewhere. If the selected entry no longer exists, the command refuses with TARGET_NOT_FOUND.

With no selection, Cotal first uses the current project's .cotal/. Outside a project, it uses the only running mesh or refuses an ambiguous choice when several are running. The (default) marker in cotal meshes marks the selected entry.

cotal up records a local mesh's broker URL, project root, and authentication mode in ~/.cotal/meshes/space.<key>.json. The key is a case-safe hex encoding of the space name. The registry stores paths and connection settings. Credentials stay under the project's .cotal/auth.

To name a space before starting it, use cotal space create <name> [--root <dir>]. This prepares <root>/.cotal/ separately from the running-mesh registry. Commands targeting that space refuse until it starts and name the root to use.

A folder's own space captures commands there only while it runs. A prepared or stopped folder leaves them to the selected space; the Mesh: report names the folder's space and its startup command. An interrupted up or down whose member still runs keeps that folder's scope until the member stops.

Register a remote mesh

Before registering, choose a permitted broker address and obtain the required trust material from the operator. --root names the local folder containing that mesh's .cotal/auth and .cotal/agents. Cotal infers the authentication mode from that folder.

A copied signer gives authority over the whole space

An authenticated space's .cotal/auth can contain its account signing seed. Anyone who reads that seed can mint identities, read retained channels and DMs, change ACLs, and keep issuing credentials. It makes the destination machine an authority for the mesh.

Copy it only to a machine you trust with the entire space. There is no per-machine revocation. Removing that authority requires signing-key rotation and new credentials for the space. A credential minted by cotal auth mint does not replace the signing material required to register a static-auth mesh. A machine that must not hold the signer does not register that space. Use an owner-minted credential with --creds <file> --server <url> instead.

For a broker reached through your private overlay, run:

cotal space add optiplex --server nats://100.90.12.34:4222 --root ~/meshes/optiplex \
  --allow-unencrypted-overlay

Replace the example address and folder with your broker's address and local trust folder. The flag records that you accept the connection's dependence on the overlay tunnel. Keep that tunnel active whenever you use the entry.

Cotal checks the broker and its trust before writing the entry. On a terminal, it shows what it will trust and asks for confirmation. If the broker is offline, --force can save an unverified entry. It never bypasses the address restrictions.

For guided registration, run:

cotal meshes add

The guided form probes the broker, reports whether it requires credentials, offers spaces already represented by the folder's credentials, and shows the record before saving it. Scripts use the explicit flags. Nothing prompts without a terminal.

Keep copied instance records separate

Each root keeps its manager and user-auth service identities in .cotal/space.<hex>/. They are not part of the trust folder to share. Starting cotal manager start or cotal up --user-auth in another root creates that root's own instance.

Older roots may still keep manager-instance.<hex>.json, manager-siblings.<hex>.json, and space.<hex>/.cotal/auth/auth-instance.<hex>.json under .cotal/auth. Remove those instance records from a copied folder before its first start. On the original root, the next start moves them to .cotal/space.<hex>/. The move refuses and keeps both entries if either path is a symlink, is not a regular file, or holds a conflicting record.

Choose a permitted address

Registration determines where this machine may send agent credentials. NATS sends its first announcement before authentication, so an unprotected peer can impersonate the broker and collect those credentials. Choose one of these connection policies:

  • Required TLS. Set --tls or use a tls:// URL. Hostnames and public addresses are accepted when the certificate chain and hostname identify the peer. The TLS requirement is recorded and enforced on later connections.
  • Loopback without TLS. Use a loopback literal such as 127.0.0.0/8 or ::1. A hostname is not accepted as a substitute.
  • Private overlay without TLS. Use a literal in 100.64.0.0/10 or fd7a:115c:a1e0::/48 and pass --allow-unencrypted-overlay. The tunnel provides protection; Cotal cannot check that it is active.

If the overlay tunnel is down, its address can be ordinary carrier-grade NAT and whoever answers may receive your credentials. The guided form asks you to accept that dependency too. Required TLS removes the need for that consent flag. For example, cotal meshes add <space> --server nats://100.64.0.1 --tls records required TLS without an overlay-consent prompt.

Ordinary private ranges such as 10.x and 192.168.x are refused in both modes. Alternate spellings do not change the result: [::ffff:192.168.1.10], 3232235786, 0300.0250.01.012, and 192.168.257 are still private addresses. --force can skip a liveness check, but cannot authorize an unsafe credential destination.

This policy applies to registration. An explicit cotal join --creds --server <url> does not consult the registry. Use it only with an address you would have registered.

Register a hosted user-auth mesh

Obtain the mesh's IdP pins from its operator. Use --user-auth-file bundle.json to load a supplied bundle, or --from https://auth.example to fetch the mesh's discovery document. The latter asks before contacting the origin, fetches /.well-known/cotal-mesh, displays the pins, and asks again before adopting them. A URL already ending in /.well-known/cotal-mesh is fetched as given.

The fetch refuses redirects. The pinned exchange must use HTTPS, except for a loopback literal on this machine. Plain HTTP may use 127.0.0.1, ::1, or another spelling of a loopback literal, but not localhost. A name lookup must not decide where a plaintext exchange sends its proof.

Registration checks /health and /jwks against the pinned issuer. It also checks that the broker refuses a bare connection. That refusal is the expected result. The bundle's deny-all sentinel credential goes into a private 0600 file under the entry's root, not the registry.

Maintain mesh entries

For a broker shared by several spaces, cotal up --space <name> refreshes only the named space. A refresh updates the server, root, mode, user-auth endpoints, and any explicit --host or --max-sessions setting. It preserves other current fields, including TLS policy and concurrent changes. If the entry was removed during the refresh, Cotal refuses instead of recreating it.

A failed probe does not remove an entry. cotal meshes reports an unreachable broker as offline; name it with --space when you intend to restart it. The probe retries using the registry's longer preflight budget. A broker that accepts a connection without finishing reports that it is not answering. A refused port reports that the broker is not running.

To forget a registered mesh, run:

cotal space forget optiplex

cotal meshes rm also forgets an entry. Neither command stops the broker. Use cotal down to stop a mesh running here.

A hand-registered entry survives cotal down and cotal clean all, even if its root is the project being stopped. Those commands remove entries created by a local up. If up finds an already-running broker at the registered endpoint, it refreshes the entry without changing that provenance. If it starts the broker for that same space, endpoint, and root, the entry becomes locally owned. down normally removes its registration. A space named after its folder keeps its registration while stopped. Controller spaces remain prepared at their root, and an existing selection keeps naming that space.

An up targeting a hand-registered mesh refuses to start a different endpoint around it. For a remote broker, follow its remedy to run cotal manager start --space <s> with delivery on the broker host. For a local entry, remove it with cotal meshes rm if it needs replacement. Re-registering with --force can replace an entry, but still applies its address restrictions.

On this page