agents-city
v0.5.12
Published
Run autonomous agent cities: one chair seat, role-aware repo agents, repo-owned skills, and explicit roads.
Downloads
2,285
Maintainers
Readme
Agents City
Run several autonomous agent cities on one machine, and connect only the cities that should talk.
npm install -g agents-city
agents-cityThat is the whole installation. The second command opens the town hall in your browser and walks you through creating your first city.
Agents City is a local-first, multi-model orchestrator for repository work. Each city has its own identity, domain, chair seat, goal, repo support agents, editable knowledge, live-recognised skills, and explicit roads to other cities. It does not turn every agent into a group chat: the seat chairs the process, selects specialists, and controls the floor.
This is the complete guide. If you only want to try it, go to Quick start.
Contents
- Mental model
- Quick start
- Requirements and installation
- First run, step by step
- Working inside tmux
- Runtimes and transports
- Domains, roles, and knowledge
- Complete command reference
- Committee: complete workflow
- Claude
/city:commands - Use-case cookbook
- Files and environment variables
- Security and trust boundaries
- Troubleshooting
- Development and testing
Mental model
A city is not an account, a remote person, or a free-form collection of bots. It is one autonomous work domain owned by a local person:
local user
├── home city
│ ├── stable identity: owner/home
│ ├── domain + seat role + goal
│ ├── seat: chair and only public boundary
│ ├── agent A: workspace + mounts → a git repo (kind: code)
│ ├── agent B: workspace + mounts → a folder of documents (kind: knowledge)
│ ├── agent C: workspace + mounts → several repos and a worktree
│ ├── editable domain/role knowledge
│ ├── skills that already live inside the mounted work
│ └── explicit roads to other seats
├── product city
└── client-a cityAgents come first. An agent is the unit, and a repo is just one thing it can
mount. Each agent has a workspace folder with a mounts/ dir of symlinks to
wherever the real work lives — a git repo, a linked worktree, or a plain folder
of documents — so a person whose work is knowledge in documents, with no git at
all, is a first-class agent. "One repo is one agent" is simply the special case
of an agent whose single mount is that repo, so existing repo-only cities keep
working unchanged. Full model: docs/agents-first.md.
The important boundaries are:
- User: may own several local cities.
- City: has its own identity, domain, goal, configuration, and state.
- Seat: chairs the committee and is the only actor that may cross roads.
- Agent: the member unit. It owns a workspace folder and works over its
mounts, contributes evidence, and always has member authority — whether its
speciality is
dev,seoorcfo, and whether its kind iscode,knowledgeorcoordinator. - Mount: a symlink inside an agent's workspace to real work on disk (a repo, a worktree, a document folder). An agent may have several, or none.
- Role: professional perspective and responsibility; it does not grant bus permissions.
- Skill: capability installed by the user or repo. Recognition is live and read-only; the one deliberate write is the Hall installing a skill zip the owner explicitly uploads, into that agent's own home — never on its own, never anywhere else. Skills are the Claude runtime's format; other engines ignore them.
- Road: allowlist between two seats. It grants reachability, not authority.
- Committee: bounded process for isolated positions, synthesis, floor, decision, and verification. It is not lateral conversation between all agents.
Quick start
Install from npm
npm install -g agents-city
agents-city --versionThis is 0.x on purpose: the commands are usable today, and the file formats
and APIs can still change between minor versions. Nothing here pretends to be
frozen yet.
You need Node.js 22.13+, Python 3 and tmux; the
requirements table has the details, and agents-city seat
offers to install tmux when it is missing. Nothing is installed system-wide
beyond the npm global folder of your active Node installation.
Try it without installing anything
npx agents-citynpx downloads the package into its cache, runs it, and leaves your global npm
folder untouched — the fastest way to see whether this is for you.
Then: the Hall, or the terminal
agents-city # the town hall in your browser (same as: agents-city hall)
agents-city seat # the terminal wizard, if you prefer not to leave the shellThe Hall listens on 127.0.0.1, chooses a free port, and opens the browser. You
can create or select a city, edit its configuration, tune each agent's engine
and watch the live map there. The Hall and the CLI use the same underlying
modules, so neither is the "lesser" path.
Update, or remove
npm install -g agents-city # update to the newest release
npm uninstall -g agents-city # remove the programUninstalling leaves ~/.agents-city, your cities and your repositories exactly
where they are: the program is not your data.
Install from a source checkout instead
For contributors, and for anyone who wants to read the code before running it. Packing first is the honest test: it exercises the exact file list a person receives from npm, not your whole working copy.
git clone https://github.com/jlcases/agents-city.git
cd agents-city
npm pack
npm install -g ./agents-city-*.tgz
agents-city --versionRequirements and installation
Base requirements
| Requirement | Used for |
|---|---|
| Node.js 22.13 or later | npm package, WebSocket bus, local reception, and frontends |
| npm | installation and packaging |
| Python 3 | Hall, onboarding, cities, maps, and utilities |
| a window server | one window per seat/agent: tmux on macOS and Linux, herdr on Windows; seat tries to install it when missing |
| macOS, Linux or Windows | all three natively. Four commands still need a shell — city, demo, benchmark, test — and say so by name on Windows |
| bash | only for those four |
| bubblewrap | optional, Linux only: it IS the cage there. Without it agents run uncaged — see the cage |
Each runtime also needs its own installed and authenticated CLI. Agents City does not bundle or replace Claude, Codex, OpenCode, or Kimi accounts.
command -v claude
command -v codex
command -v opencode
command -v kimiYou do not need all of them. An all-Claude, all-Codex, or mixed city is valid.
GitHub is optional
Selecting local repos requires no account. If you choose GitHub during
onboarding, Agents City uses the separate gh CLI:
- detects it;
- tries the system package manager if it is absent;
- runs
gh auth login --webwhen unauthenticated; - shows the device code if a browser cannot open;
- offers to clone selected repos that are not on disk.
gh is not bundled inside the Agents City npm package.
Update an installation
npm install -g agents-city # from the registry
agents-city --versionFrom a source checkout, pack and install the tarball instead:
cd /path/to/agents-city && npm pack && npm install -g ./agents-city-*.tgzAlready-running sessions retain the code loaded in memory. To apply the new version to one city:
agents-city exit home --dry-run
agents-city exit home
agents-city seat --city homeSave active work first: exit closes every window in that city.
Uninstall
npm uninstall -g agents-cityThis removes the installed program. It does not remove ~/.agents-city, your
cities, backups, or repositories. Use agents-city reset only when you intend to
restart one specific city.
First run, step by step
agents-city seat creates home when no city exists and asks seven questions.
1. Work domain
The domain determines vocabulary, evidence criteria, and suggested roles. The built-in options are:
| ID | Domain |
|---|---|
| software | Software development |
| healthcare | Healthcare and medicine |
| legal | Legal services |
| finance | Finance and operations |
| marketing | Marketing and growth |
| sales | Sales and customer success |
| research | Research and education |
| operations | Operations and delivery |
| custom | Another domain without assuming an industry |
2. Seat role
This is the responsibility of the city lead. It is not the city name or runtime.
The seat remains chair even when you choose blank.
3. The agents, one at a time
This is the city itself, and it is a loop rather than a list of folders to tick. Each agent is asked for in full, and then you are asked for another, until you say the city is complete:
- Its name — what you call it in its window, on the map, and on the bus.
- The kind of work it does —
code,knowledgeorcoordinator. This is not a permission: it decides how its house grows on the map, so a person whose work is documents is not measured in pull requests. - Its role — its specialty, from this city's domain or another one. A
software city can give
poto a product agent,seoto a portfolio one anddata-engineerto a pipeline. None becomes chair. - Everything it works on — any number of repositories (read from disk, your GitHub account, or an organisation) plus any number of document folders. One agent may answer for three services and a handbook at once, and an agent with no git anywhere is a first-class agent. They are mounted inside its workspace, not turned into separate agents.
- What runs it — Claude with a model and effort of its own, or Codex, OpenCode, Kimi, or an explicit terminal fallback.
- The skills it starts with — a skill folder or
.zipinstalled into that agent's own home. Only offered for engines that read skills; an agent on Codex is told its engine ignores them instead of being sold something that does nothing.
Each agent then receives a tmux window, a private bus actor, its workspace as working directory, and the skills its runtime can already discover in what it mounts.
Saying the city has no agents is also valid: it opens with only its seat, and roads connect it to other cities.
Change the roster any time with agents-city seat --agents.
4. Goal
A goal may be quantitative or qualitative. It stores:
- title;
- observed signal;
- a command that returns the measure, when one exists;
- person and review frequency for a qualitative judgement;
- baseline;
- target;
- target date.
You may skip it and configure it later with agents-city seat --goal.
5. Runtime for your own chair
Every agent's engine was decided on the agent itself, in question 3. What is
left is your own window — the one that holds the chair role, the /city:
commands and the plugin. Pressing Enter keeps it on your Claude; you may instead
choose Claude with a model and effort, Codex, OpenCode, Kimi, or an unknown
command through the explicit terminal fallback.
Persistent choices live in the owner card. seat --model and --effort are
one-launch overrides only.
6. Whether your chair asks permission
Per city, in city.yml as seat_yolo. Locally the seat is your own hands on
your own machine, so asking you for permission in your own chair is a choice,
not a law. Agent windows keep their own cage either way, and launching with
--no-yolo still brakes the whole session, seat included.
7. The city on your desktop
Offered once, when the city is new: a real desktop shortcut carrying the city's
name and an icon coloured from its own identity — a macOS .app bundle or a
Linux .desktop entry. Double-click it and the city opens.
It runs the same line you would type, so it is a labelled button on the front door rather than a second way in. Add or remove one any time:
agents-city shortcut # this city, on your desktop
agents-city shortcut home --hall # a door that opens the map instead
agents-city shortcut --remove # take it off again
agents-city shortcut --to ~/bin # somewhere other than the desktopOn Windows it is a real .lnk, built through Windows' own PowerShell so it
can carry an .ico, running the same front-door command as every other desktop.
The desktop is asked of Windows itself rather than guessed from a username — one
redirected to OneDrive or a domain profile is not under C:\Users\<name>\Desktop.
Where PowerShell is unavailable a double-clickable .cmd is written instead:
same door, plain icon.
Inside WSL the shortcut still crosses back: a ~/Desktop there is the Linux
home's desktop, which nobody looks at, so the Windows desktop gets a .lnk that
launches wsl.exe running the same command in a login shell.
What gets created
~/.agents-city/
├── .runtime/ # bus endpoints, queues, and ephemeral state
├── state/ # local map state, separated per city
├── .backups/ # old migrations
└── <owner>/
├── .current # selected city
├── .backups/ # recoverable owner resets
└── <city>/
├── city.yml # id, name, slug, owner, domain
├── roads.json # allowed roads
├── <owner>.md # role, repos, roles, goal, runtimes
├── AGENTS.md # how to read this city
├── domains/ # editable domain knowledge
├── roles/ # editable role knowledge
├── deliberations/ # committee state, events, and acts
├── units.yml # map districts, when used
└── parcels.yml # map houses/parcels, when usedThe ~/.agents-city root is a container, never a city. home is simply the
first city and is isolated exactly like product or client-a.
Working inside tmux
A session is named <owner>-<city> and contains:
- a
seatwindow, located in the city folder; - one window per locally found repo;
- the configured runtime already started in each window.
Shortcuts are added only to the currently running tmux server:
| Action | Shortcut |
|---|---|
| Switch to windows 1–9 | Alt+1 … Alt+9 |
| Previous/next window | Alt+← / Alt+→ |
| Select with mouse | click the bottom status bar |
| Scroll | mouse wheel |
| Detach without closing | Ctrl-b, then d |
| Return to the city | agents-city seat --city <name> |
If the session already exists, seat reattaches to it; it does not create a
duplicate set of agents. A bell or activity-coloured tab means that window may
need attention.
Claude starts in a stagger because multiple instances share its OAuth token.
Codex, OpenCode, and Kimi do not wait for that stagger. Use
CITY_SETTLE=0 CITY_STAGGER=0 only when you deliberately want to disable it.
Do not close a city by killing generic processes. Use:
agents-city exit <city> --dry-run
agents-city exit <city>Runtimes and transports
All runtimes receive typed envelopes from the same local WebSocket bus, but each provider has a native last mile:
| Runtime | Bus task delivery | Visible interface | Requirement |
|---|---|---|---|
| Claude | persistent stream-json over stdin/stdout | interactive city> gateway plus visible Claude transcript | authenticated claude CLI; no Team account or admin policy |
| Codex | app-server WebSocket | official TUI connected with codex --remote | authenticated codex CLI |
| OpenCode | HTTP/SSE API | interactive gateway city> console | configured opencode CLI |
| Kimi | REST + WebSocket | interactive gateway city> console | configured kimi or kimi-code CLI |
| Unknown CLI | compatibility adapter | its own TUI/command inside tmux | explicit terminal:<command> setting |
Claude, Codex, OpenCode, and Kimi tasks are not pasted into tmux and do not use the clipboard. Terminal fallback exists only for an explicitly selected unknown command.
Agents City does not use custom Claude Channels in its normal launch path.
The same official Claude Code process stays open in print/streaming mode and
receives JSONL turns directly from the city gateway. A personal Pro/Max account
therefore needs no sudo, managed-settings.json, Team console, Channel
allowlist, development bypass, or per-window confirmation. The installed plugin
still supplies its MCP tools, skills and hooks normally. Custom Channels remain
an optional upstream preview mechanism, not a prerequisite for Agents City.
Conceptual multi-model card settings:
runs.seat: codex
runs.api: codex --model gpt-5
runs.analytics: opencode -m lmstudio/qwen3-coder
runs.research: kimi
runs.legacy: terminal:gemini
model.docs: sonnet
effort.docs: highWhen the seat does not use Claude, it has no /city: commands. Everything
fundamental remains available through agents-city committee, road, bus,
skills, seat, reset, and exit.
Domains, roles, and knowledge
Built-in roles by domain
| Domain | Available role IDs |
|---|---|
| software | cpto, dev, data-engineer, devops, data, product-design, po, llm-engineer, ai-manager, blank |
| healthcare | clinical-director, clinician, patient-safety, clinical-ops, health-data, health-compliance, blank |
| legal | managing-partner, associate, compliance, knowledge, ops, blank |
| finance | cfo, controller, fin-analytics, ops, compliance, blank |
| marketing | brand-lead, content, performance, seo, lifecycle, data, product-design, blank |
| sales | revenue-lead, account-executive, revops, customer-success, enablement, blank |
| research | research-director, researcher, methods, research-ops, ethics, knowledge, blank |
| operations | operations-lead, program-manager, process-owner, quality, knowledge, blank |
| custom | city-lead, specialist, quality, knowledge, blank |
blank is a complete choice: it creates no role file, applies no hidden
profile, and infers no responsibility. You may assign it to the seat or any repo
and change it later.
When you select a domain/role, Agents City copies initial packs into the city:
domains/<domain>.md
roles/<role>.mdThey are ordinary Markdown. You can edit, remove, or extend their contents. A later role change does not overwrite an existing file, so your adaptations are preserved. This knowledge is not a skill.
Complete command reference
Overview
agents-city [hall]
agents-city setup
agents-city seat
agents-city cities
agents-city road
agents-city connect
agents-city bus
agents-city committee
agents-city agents
agents-city skills
agents-city city
agents-city shortcut
agents-city demo
agents-city report
agents-city tokens
agents-city logs
agents-city benchmark
agents-city reset
agents-city exit
agents-city doctor
agents-city update
agents-city testGlobal commands:
agents-city --help
agents-city --versionagents-city and agents-city hall
Open the local Hall for the selected city.
agents-city
agents-city hall
agents-city hall --city product
agents-city hall --no-browser| Option | Effect |
|---|---|
| --city NAME|ID|PATH | select a known city and open it |
| --no-browser | do not open the browser; print the local URL and temporary token |
The server binds only to 127.0.0.1 and requires a per-run token for writes.
The City live column on the right connects as a spectator to the same local
WebSocket bus used by the agents. It shows ordinary visible user/agent messages,
runtime failures, and the complete moderated committee flow as a conversation:
one avatar per repo, the seat marked as chair, and one visible turn per revealed
position or granted reply. Routine commands and lifecycle noise are collapsed
behind show work; the selected conversation opens by default.
The Hall opens directly on The map. The city owns the whole centre canvas: state, controls, and
history stay in the side rails, never above or below the map. Every semantic
turn arriving on that same WebSocket also creates a short game-style bubble,
anchored to the speaking character and prefixed with its recipient (Para
seat:, Para committee:, and so on). The bubble is only the transient summary;
the complete message and evidence remain in City live. No decorative
dialogue, commands, private reasoning, or raw envelopes become speech.
Codex uses completed visible app-server items; Claude uses its documented prompt
and stop hooks. Provider reasoning items, chain-of-thought, credentials, and raw
transport frames are neither shown nor written to the activity log. The
spectator token rotates with the hub, accepts only an origin on this computer,
and is read-only: the browser cannot direct the committee. Ctrl-c stops the
Hall.
Demos in the rail plays a whole committee without setting anything up: one
story per work domain — a studio, a clinic, a law firm — with play, pause,
replay and speed. What it plays are recordings: demo/graba.py runs each story
over the real local bus, through the real committee state machine, and keeps the
exact event stream a spectator saw; the Hall replays those events through the
same renderer the live rail uses. It says so on screen, because a demo that
pretends to be live is the one kind this product must not ship. To run one live
in a terminal instead: agents-city demo --domain software.
Regenerate the recordings after editing demo/stories.py:
demo/graba.py # every story
demo/graba.py medicina # just oneThe demo suite fails when a recording no longer matches the story it claims to be, so a stale one is a red build rather than a browser quietly playing last month's committee.
Two buttons sit under the brand: day/night, and ES/EN. The Hall speaks Spanish and English, starting in the browser's own language and remembering an explicit choice. Translations are keyed by the English sentence, so anything not yet translated falls back to readable English rather than to an identifier — new strings are never blocked on a translation pass.
Coverage is a test, not a habit. bin/test-i18n.py reads the render paths, pulls
out every English sentence a person will see, and fails when one has no Spanish —
so a new view cannot quietly ship untranslated, which is how coverage had drifted
to about 40% before anybody noticed.
The obvious mechanism, sweeping the rendered DOM and translating what matches a
key, is deliberately not what this does. At DOM time there is no way to tell
a sentence this product wrote from a city or agent name somebody typed, so a
person whose city is called Overview would watch it rename itself. The
distinction only exists in the source, between a literal and an interpolation,
and that is where the check is made: anything holding a ${} is skipped.
agents-city setup
Creates or selects a city and opens the Hall; --tui hands the flow to seat.
agents-city setup
agents-city setup --city product
agents-city setup --city product --tui
agents-city setup --out /path/to/a/city
agents-city setup --demo
agents-city setup --no-browser| Option | Effect |
|---|---|
| --city NAME | create the managed city when missing or select the existing one |
| --out PATH | register/import an explicit compatible folder; advanced use |
| --demo | open the complete guided Aurora Games demo |
| --tui | use terminal onboarding and open the session |
| --no-browser | keep the Hall in the terminal and print its URL |
agents-city hall
The town hall runs detached, like the city bus and every other long-lived
piece of this product. Closing the window that started it is not a way to break
the page somebody is looking at, and agents-city hall run twice hands back the
address that is already serving rather than starting a second one. Stop it with
agents-city exit; --foreground serves in the window and stops with it.
Its address survives a restart. The token used to be minted per process, which
made every tab disposable — close the hall, open it again, and the page somebody
had is permanently refused, with no way back except reading a new URL out of a
terminal. It is stored at ~/.agents-city/.runtime/hall.pase, mode 0600, in the
same class as the bus token this product already keeps.
Whether the city is running is said on every screen, not on the front page somebody may never return to: open or not, how many agents are actually connected, and — only when it is missing — that this city is running with none of its rules. That last light is the one that had to be earned: it used to be a guess at whether a directory existed, and that directory is the marketplace's cache, which appears the moment somebody adds the marketplace. So a machine with no city plugin showed a green "installed", which is why its owner could spend an afternoon unable to see that nothing was being enforced. It asks Claude now.
And when the hall is not answering, the page says so in its own words: what happened, that nothing was lost, the command that opens it again, and a button that retries — plus a quiet retry every few seconds, so a page left open recovers by itself when the hall comes back.
agents-city seat
Configures requested settings, ensures tmux/plugin, and opens or resumes the city session.
agents-city seat
agents-city seat --city product
agents-city seat --repos
agents-city seat --agent-roles
agents-city seat --goal
agents-city seat --engines
agents-city seat --domain marketing
agents-city seat --domain marketing --role brand-lead
agents-city seat --role blank
agents-city seat --only api,web
agents-city seat --model sonnet --effort high
agents-city seat --seat-yolo on
agents-city seat --no-yolo --no-sync| Option | Persistence and effect |
|---|---|
| --city NAME|PATH | select this city and open its session |
| --repos | choose repos again, then their agent roles; persists |
| --agent-roles, --agents | choose only each repo role again; persists |
| --goal | redefine the goal; persists |
| --engines | choose runtime/model per window; persists |
| --domain DOMAIN | change domain; persists and asks for a compatible role unless --role is supplied |
| --role ROLE | change the seat role without a picker; persists |
| --only a,b | open only those repos this run; does not alter the card |
| --model ALIAS | model override for all windows in this launch |
| --effort LEVEL | low, medium, high, xhigh, or max override for this launch |
| --seat-yolo on\|off | whether the chair itself runs without permission prompts; persists per city (city.yml seat_yolo, also question six of the wizard). Locally the seat is the owner's own hands; repo windows keep their own yolo/cage story either way |
| --seat-reach open\|closed | whether the chair may work inside its agents' mounts; persists per city (city.yml seat_reach). Closed by default: the seat asks the agent who owns that ground instead of reading it, and a refusal names them and the command |
| --no-yolo | disable auto-approval for this launch — seat included, whatever seat_yolo says |
| --no-sync | skip initial git fetch/pull in repos for this launch |
seat accepts a positional user for compatibility, but only when it matches the
resolved local owner. Use --city for another city belonging to the same user.
agents-city cities
Manages the local catalogue. Creating or selecting does not start tmux.
agents-city cities list
agents-city cities current
agents-city cities create product
agents-city cities use product
agents-city cities use /path/to/city| Subcommand | Output/effect |
|---|---|
| list | known cities; * marks the selected one |
| current | absolute path of the selected city |
| create NAME | create ~/.agents-city/<owner>/<slug>/ and select it |
| use NAME|PATH | select an existing city without starting it |
agents-city road
Opens and closes the allowlist of connections between seats.
agents-city road list product
agents-city road connect product client-a
agents-city road invite product
agents-city road invite product > product.invitation.json
agents-city road connect product research.invitation.json
agents-city road disconnect product client-a
agents-city road disconnect product <remote-city-id>| Subcommand | Effect |
|---|---|
| list CITY | show destination, address, and local/remote status |
| connect A B | when B is local, write both ends symmetrically |
| connect A invitation.json | add only the local end of a remote road |
| invite CITY | print public JSON without a token |
| disconnect A B|ID | remove both local ends or the specified remote ID |
A city cannot connect to itself. Each machine must independently accept the other remote invitation.
agents-city connect
Pairs this computer with a managed Road service. It does not create a connection unilaterally: both people approve it in the service, and the recipient sees the sender in their private human reception without exposing a city catalogue. The public client implements protocol v4; the hosted service is outside this repository and is not production-enabled or independently audited.
agents-city connect --service https://connect.example.com --trust-file roots.json
agents-city connect --city product
agents-city connect --all
agents-city connect status
agents-city connect roadsThe command generates Ed25519/X25519, Olm and signed ML-KEM-768 material on this
computer, prints a one-use PASCO and opens the browser for approval. Only public
material is uploaded. Private keys, ratchet state, ML-KEM seeds and retry data
are encrypted in ~/.agents-city/.runtime/connect/vault/; the wrapping key
stays in macOS Keychain, Windows Credential Manager or Linux Secret Service.
The client fails closed if that keyring is unavailable. The vault is sealed from
repo-agent windows on macOS and Linux.
The signed root chain supplied through --trust-file is mandatory for first
pairing with a non-development service. The client persists its last accepted
version. A later root must continue from that exact local root and carry enough
signatures from both the old and new offline authorities; skipped versions,
rollback, expiry and silent operator/witness replacement are rejected. Protocol
v4 then verifies the peer through key transparency, protects the first Olm
message with hybrid X25519 + ML-KEM-768, and uses the Olm Double Ratchet. Normal
sealed submissions omit sender, device, city and Road identity from the outer
request. This does not hide IP address, timing or padded size from Cloudflare,
and later ratchet steps are classical.
The package includes a public root only for the exact managed sandbox origin;
self-hosted services still require their reviewed --trust-file. A root
returned by the service is never accepted as a first pin.
--city chooses a local hub that can keep the computer's reception bridge
alive; it is not a recipient selector and is never disclosed to the other
person. Exactly one hub per computer holds the lease and one outbound encrypted
session; no public port is opened. Use --service URL or
AGENTS_CITY_CONNECT_URL for a pilot endpoint. The hosted server is not part of
this Apache repository; the auditable client and wire protocol are.
agents-city connect roads prints a connected person's name for a person Road,
not the opaque rx-* transport endpoints. In the Hall, every incoming message
waits for manual review by default. The owner may route it to one or more local
cities, reject it with a reason, or explicitly enable the deterministic Auto
router. Auto routes only one unique low-risk rule match; ambiguous, unmatched,
prompt-like, secret-seeking, or command-like text remains in the human queue.
See docs/managed-connect.md for the exact key, envelope, encryption, ACK, revocation and threat-model contract.
agents-city bus
Operates messages between seats over declared roads.
agents-city bus roster
agents-city bus inbox
agents-city bus send alice/research "Please confirm the event X contract"
agents-city bus send '*' "Notice for every connected city"| Subcommand | Effect |
|---|---|
| roster | return roads and known online presence |
| inbox | return and consume the next approved batch of up to 20; managed text is unavailable until the owner routes it in the Hall |
| send owner/city TEXT | send to one allowed destination |
| send '*' TEXT | send to all roads; requires at least one |
Only seat may run these operations. A repo actor is rejected by the ACL even
if it knows the destination address.
agents-city committee
Manages structured deliberations inside one city. Every command accepts fields
as flags or as a JSON object through --input.
agents-city committee list
agents-city committee history
agents-city committee show <deliberation-id>
agents-city committee status <deliberation-id> # alias for show
agents-city committee schema open
agents-city committee open --input proposal.json
agents-city committee open --input - < proposal.json| Subcommand | Allowed actor | Purpose |
|---|---|---|
| list | any involved city actor | open deliberations visible to that actor |
| history | seat | finished decision history and contributor counts |
| show ID, status ID | involved city actor | complete actor-visible state and events |
| schema VERB | anyone | JSON contract for a mutation verb |
| open | seat | state question, outcome, members, and boundaries |
| respond | invited member | record one independent initial position |
| synthesize | seat | publish agreements, conflicts, and unknowns |
| floor-request | member | request a turn for evidence, contradiction, risk, or dependency |
| floor-grant | seat | grant one floor request |
| floor-deny | seat | deny one floor request with a reason |
| reply | member holding the floor | submit one bounded, evidence-based reply |
| decide | seat | record outcome, owners, verifier, and reopen conditions |
| verify | assigned verifier | return pass or fail with checks |
| replan | seat | reopen a failed verification with a new plan |
| close | seat | close an already verified outcome |
| cancel | seat | cancel a deliberation with a reason |
Opening with flags:
agents-city committee open \
--question "Should we ship today?" \
--outcome-wanted "A reversible decision with an owner and verification" \
--context "The release candidate passed the local suite" \
--constraint "Do not lose data" \
--constraint "Rollback within ten minutes" \
--done "The decision names an executor and verifier" \
--authority execute \
--member api \
--member web \
--member qa \
--max-rebuttals 1The result prints a deliberationId. Keep it for later transitions. JSON is
usually clearer for large payloads:
{
"question": "Should we ship today?",
"desiredOutcome": "A reversible decision with an owner and verification",
"context": "The release candidate passed the local suite",
"constraints": ["Do not lose data", "Rollback within ten minutes"],
"definitionOfDone": ["Executor and verifier assigned"],
"authority": "execute",
"participants": ["api", "web", "qa"],
"maxRebuttals": 1
}agents-city committee open --input proposal.json--input - reads stdin. When JSON and flags are mixed, explicit flags override
the equivalent field. Repeatable flags are --member, --constraint, --done,
--evidence, --risk, --unknown, --agreement, --conflict, --check,
--residual-risk, --selected-evidence, --rejected-option, --dissent,
--reopen-if, --learning, and --followup.
Always inspect the exact contract shipped by the installed version:
agents-city committee schema respond
agents-city committee schema decide
agents-city committee schema verifyMember commands (respond, floor-request, and reply) are normally executed
by the authenticated repo agent after receiving an envelope. Running one from
the seat correctly fails its ACL: accepting an actor name as text would not let
the bus pretend to be that actor.
agents-city skills
Lists skills already present in a city's repos. This is read-only: it does not install, copy, enable, or remove anything.
agents-city skills
agents-city skills productRecognised layouts per repository:
SKILL.md
.claude/skills/*/SKILL.md
.codex/skills/*/SKILL.md
.agents/skills/*/SKILL.md
skills/*/SKILL.mdActual invocation depends on the runtime. Agents City advertises the capability for the member and lets the provider enforce its own discovery and use rules.
agents-city agents
Lists this city's agents and manages what each one works on. An agent's mounts are symlinks inside its workspace, so this is the terminal equivalent of the Hall's works on row and of question 3 of the wizard.
agents-city agents list --card ~/.agents-city/alice/home/alice.md --data ~/.agents-city/alice/home
agents-city agents mounts --agent urgencias --data ~/.agents-city/alice/home
agents-city agents mount --agent urgencias --src ~/documents/handbook --data …
agents-city agents unmount --agent urgencias --name handbook --data …| Command | Effect |
|---|---|
| list | every agent: name, slug, role, runtime, kind, working directory |
| mounts | one agent's mounts, as label and real target |
| mount --src PATH | mount a repo, a worktree or a folder of documents |
| unmount --name LABEL | remove that mount; the folder itself is untouched |
| sync / sync-all | rebuild the workspaces from the card, as the launcher does |
Unmounting removes a symlink and a card key. It never deletes what the link pointed at.
agents-city city
Opens one city's local map without starting an agent session.
agents-city city
agents-city city ~/.agents-city/alice/productIt uses port 8787 or the next free port, binds to loopback, and opens the
browser. Ctrl-c stops the server. units.yml, parcels.yml, the card, and bus
state feed the visualisation.
The map is live, not a postcard. Three layers stage what is happening right
now, all derived from data the product already emits: presence (a mid-turn
house glows and breathes, a stopped one cools), the town hall (committee
sessions play on stage — sealed positions fly in face down, the floor is a
raised hand, verification stamps the door, closing files the act — with the
camera flying to the session and members walking over), and one gate per road,
which letters to other cities leave through. Agents get deterministic
identicon faces, knowledge/coordinator parcels wear a different building
family than code, the town hall and the gates are clickable, P (or the ⛶
control) toggles fullscreen, and the Hall's live rail is resizable by dragging
its edge. The full contract is in
docs/map-live-layers.md.
agents-city shortcut
Puts a city on your desktop: its name, an icon coloured from its own identity, and a double-click that opens it.
agents-city shortcut # the selected city
agents-city shortcut product # a specific one
agents-city shortcut --hall # a door that opens the map instead of the seat
agents-city shortcut --remove # take it off the desktop
agents-city shortcut --to ~/bin # write it somewhere else| Option | Effect |
|---|---|
| --hall | the shortcut opens the browser map instead of the tmux city |
| --remove | remove this city's shortcut |
| --to DIR | write it into another folder than the desktop |
What gets written depends on the desktop, and each is a real one rather than a script pretending:
| Platform | Shortcut | Icon |
|---|---|---|
| macOS | .app bundle running the city in Terminal | .icns, built with the system's iconutil |
| Linux | .desktop entry, marked trusted where gio exists | .png under XDG_DATA_HOME |
| Windows | .lnk on the desktop, running the front-door command | .ico, built by hand; a .cmd without PowerShell |
| Windows (inside WSL) | .lnk on the Windows desktop, launching wsl.exe | .ico, when PowerShell interop is reachable |
All of them run the same line you would type, so the shortcut is a labelled
button on the front door rather than a second way in. The icon is generated
without any image library: a PNG written by hand, wrapped as .ico for Windows
and converted by iconutil for macOS.
On Windows the city lives inside WSL, and a ~/Desktop there is the Linux
home's desktop that nobody looks at — so the Windows desktop is asked of Windows
itself, never assembled from a username, because a desktop redirected to OneDrive
or a domain profile is not under C:\Users\<name>\Desktop. Without interop a
double-clickable .cmd is written instead: same door, plain icon.
agents-city demo
Opens one fictional, disposable demo city in the complete Hall. The map owns
the centre; the right rail plays a guided deliberation and those same turns
appear as Para …: speech bubbles over their agents. There is one demo per
domain — real chaos told in plain words, not programmer phrases:
agents-city demo # software · Aurora Games — the night the saves vanished
agents-city demo --domain medicina # Clínica Alba — the morning the appointments doubled
agents-city demo --domain legal # Costa & Ley — the deadline at nine tomorrow
agents-city demo --no-browserIt starts no models and needs no Claude, Codex, OpenCode or Kimi account. The stories are declared presentation content, but their engineering is not an animation: all 22 events cross the real authenticated WebSocket, committee state machine, durable ledger and spectator feed. Every story walks the WHOLE machine, including the part demos usually hide: three isolated positions, two chair-granted floor requests, a decision, a verification that FAILS, a replan, and only then a verified close. The clinic and the firm are agents-first cities — knowledge and coordinator agents, no repositories — so they also exercise the roster and the map's building families.
The Hall's live rail shows a framed guided committee control for demo
cities only: ⟳ replay plays the domain's story again, and ⏸ pause /
▶ resume stop and continue the storyteller process itself (SIGSTOP, a real
pause). /api/demo refuses any city that is not a packaged demo: a real
city's committee is real, and a replay there would publish fiction onto a real
bus.
The demo copies its city and runtime into a temporary directory. Ctrl-c stops
its Hall, map and hub and removes that copy; it never selects, rewrites or starts
your cities. If another map already owns 8787, the demo uses another port and
the Hall checks city identity instead of accidentally framing the wrong map.
agents-city report
Computes growth that can be represented on the map and optionally pushes it to the configured city service.
agents-city report
agents-city report --data ~/.agents-city/alice/product
agents-city report --url https://city.example.com --token "$CITY_TOKEN"
agents-city report --push --quiet| Option | Effect |
|---|---|
| --data PATH | use another city data folder |
| --url URL | override the service URL |
| --token TOKEN | override the authentication token |
| --push | send the report; without it, only compute/show |
| --quiet | reduce human-readable output |
agents-city tokens
Aggregates local Claude transcript usage and can send totals only. It does not send prompts, responses, or file paths.
agents-city tokens
agents-city tokens --days 7
agents-city tokens --all
agents-city tokens --push --quiet
agents-city tokens --url https://city.example.com --token "$CITY_TOKEN"| Option | Effect |
|---|---|
| --days N | time window; default 30 days |
| --all | re-read transcripts inside --days, ignoring the incremental cache |
| --url URL | override the service URL |
| --token TOKEN | override the authentication token |
| --push | send aggregates; without it, only show them |
| --quiet | reduce human-readable output |
tokens does not automatically estimate Codex, OpenCode, or Kimi usage.
agents-city logs
Reads the selected city's two durable local streams: visible semantic activity and secret-scrubbed operational diagnostics. It does not read provider reasoning.
agents-city logs
agents-city logs --activity --lines 50
agents-city logs --diagnostics --lines 200
agents-city logs --follow
agents-city logs --json --follow| Option | Effect |
|---|---|
| --activity | only visible prompts, answers, work, and committee events |
| --diagnostics | only hub, socket, gateway, hook, and launcher diagnostics |
| -n, --lines N | initial number of records; default 100 |
| -f, --follow | continue streaming appended records until Ctrl-c |
| --json | emit the stored JSONL records unchanged |
The files live under the selected city's private runtime directory as
activity.jsonl and diagnostics.jsonl. They survive a Hall reload and a bus
restart, are mode 0600, and can be inspected directly. Activity source IDs
make repeated provider notifications and hooks idempotent.
agents-city benchmark
Measures transport, real runtimes, or the structure of the committee protocol.
Local stress without model quota
agents-city benchmark stress
agents-city benchmark stress --agents 40 --rounds 2 --timeout 20
agents-city benchmark stress --agents 80 --rounds 5 --json
agents-city benchmark stress --keep| Option | Effect |
|---|---|
| --agents N | simulated actors; must be even, default 40 |
| --rounds N | rounds per actor; default 2 |
| --timeout SEC | benchmark limit; default 20 |
| --json | machine-readable output |
| --keep | preserve the temporary workspace for inspection |
Real runtimes, consuming quota
agents-city benchmark live --runtime claude --runtime codex
agents-city benchmark live \
--runtime codex \
--runtime kimi \
--timeout 180 \
--json
agents-city benchmark live \
--command codex="codex --model gpt-5" \
--command opencode="opencode -m lmstudio/qwen3-coder" \
--keep| Option | Effect |
|---|---|
| --runtime RUNTIME | runtime to measure; repeatable: claude, codex, kimi, opencode |
| --command RUNTIME=COMMAND | concrete command for that runtime; repeatable |
| --timeout SEC | limit per case; default 180 |
| --json | machine-readable output |
| --no-save | do not append the result to local history |
| --keep | preserve temporary workspaces |
live makes real calls to installed providers and can consume quota or money.
Check authentication and limits before running it.
Committee protocol
agents-city benchmark committee
agents-city benchmark committee --jsonThis compares the structured flow with an unbounded chat: response barrier, floor control, decision, and verification. It is a deterministic structural benchmark; by itself it proves neither higher answer quality nor a SOTA claim.
agents-city reset
Resets managed cities while preserving their stable identity and repositories.
agents-city reset product --dry-run # show every effect, change nothing
agents-city reset product
agents-city reset product client-a # several, space separated
agents-city reset all # every city this owner hasOne unknown name aborts the whole run before anything is touched: resetting three cities and then stopping on a typo is the worst outcome a destructive command can have. The Hall has the same thing as a button, in Cities — it first shows what disappears, what survives and where the copy lands, and asks you to type the city's name.
The reset plan:
- verifies the target is a managed city, not an arbitrary path;
- shows and stops only that city's session/runtime;
- creates a recoverable backup under its owner;
- preserves
id, owner, name, and slug; - removes that city's configuration, deliberations, and generated state;
- does not touch source repositories;
- symmetrically removes incident local roads;
- leaves the city ready for onboarding again.
There is no automatic restore command yet. The exact backup path is printed
for manual recovery. Always run --dry-run first.
agents-city exit
Stops Agents City sessions and processes without deleting configuration.
agents-city exit product --dry-run
agents-city exit product
agents-city exit --dry-run
agents-city exitWith a city, it closes only that city's tmux, gateway, and helper processes; the Hall may stay up. Without a city, it shows or closes everything managed by Agents City. A tmux session may contain unsaved work, so dry-run is the safe way to confirm scope.
agents-city doctor
Checks this machine and says which part is missing, in one screen.
agents-city doctorIt reports the tools it needs (python3, tmux, bash, git, node, and gh as
optional), which agent runtimes are installed, which cage this kernel gives
you — seatbelt, bubblewrap, or none and why — the selected city and its card,
whether the Hall bundle is built, and whether a newer version is published. It
exits non-zero when something is broken, so it works in a script too.
Passed a config file instead, it keeps its older job: detect an old config
shape, explain it, and migrate it with --fix (leaving a backup).
agents-city update
agents-city update # install the newest published version
agents-city update --check # only ask: installed vs published
agents-city update --tag beta # follow a dist-tagThe check is one GET to the public npm registry, cached for a day under
~/.agents-city/.runtime/. Nothing about your machine is sent — no identifier,
no counter, no telemetry — and CITY_UPDATE_CHECK=0 switches it off entirely.
It runs only where you deliberately opened something: doctor, update, and
the Hall (which shows one line when a release is out). A plain
agents-city cities never touches the network.
Installed from a git checkout, update refuses and tells you the command that
fits your install instead of running npm install -g over your working copy.
agents-city test
Runs checkout tests. With no arguments it runs every suite; with names it runs only those suites.
agents-city test
agents-city test seat runtime-ui
agents-city test committee stress benchmarkAvailable suites:
widgets card parcels domains serve seat cities channel committee live-feed
runtime runtime-ui runtime-failures stress adapter benchmark contracts exit
cage broker launchThis command is intended for contributors or local tarball validation. Normal use does not require running tests at every startup.
Committee: complete workflow
The committee behaves like a management committee: the seat frames and chairs the decision; specialists contribute evidence from their repos; nobody opens a lateral conversation; the seat integrates and another identity verifies.
open
└─ collecting: independent, hidden positions
├─ missing replies + proceedWithout ─┐
└─ all reply -> review │
v
synthesize
│
v
deliberating
┌─ bounded floor ─┐
└─ request/reply ┘
│
decide
│
v
verifying
┌─ fail ─└─ pass
v v
verification_failed verified
│ │
replan close
│ │
└─> review closed1. Prepare the brief
A good question names a decision, not merely a topic. The desired outcome says
what the committee must produce; definitionOfDone lists observable conditions.
Select only repositories capable of producing relevant evidence.
| open field | Required | Values/meaning |
|---|---|---|
| question | yes | exact decision |
| desiredOutcome | yes | concrete expected result |
| context | no | minimum necessary facts |
| constraints | no | time, cost, security, or policy boundaries |
| definitionOfDone | yes, list | observable acceptance conditions |
| authority | no | recommend, decide, or execute; default recommend |
| participants | yes, list | repo actor names in this city |
| maxRebuttals | no | integer 0–5; default 2 per member |
authority records the mandate; it does not change technical ACLs.
2. Collect isolated positions
Each participant receives the same brief and responds once:
agents-city committee respond "$DELIBERATION_ID" \
--stance conditional \
--recommendation "Ship to 10% first" \
--evidence "npm test: 844 checks passed" \
--expected-impact "Detect regressions before full rollout" \
--visible-when "After 30 minutes of telemetry" \
--withdraw-if "The migration is not reversible" \
--risk "Insufficient canary capacity" \
--unknown "First-hour production load"stance is support, oppose, conditional, or abstain. evidence is
required and repeatable. The runtime executes the response inside the repo
window under its real identity. Until the barrier opens, the seat sees progress,
not initial-position contents; this reduces anchoring.
3. Synthesise without voting
Once all positions are ready, the seat integrates evidence:
agents-city committee synthesize "$DELIBERATION_ID" \
--summary "There is agreement on a reversible canary" \
--agreement "The migration needs a tested rollback" \
--conflict "10% versus 25% initial traffic" \
--unknown "Capacity at expected peak"If a member is missing, it cannot simply be ignored:
agents-city committee synthesize "$DELIBERATION_ID" \
--summary "Provisional synthesis" \
--proceed-without "QA is offline; the deadline is today and rollback remains available"The decision integrates evidence, impact, and withdrawal conditions rather than counting votes.
4. Request and grant the floor
After synthesis, a member may reply only with an admitted basis:
agents-city committee floor-request "$DELIBERATION_ID" \
--basis new_evidence \
--reason "The canary failed its rollback test" \
--evidence "artifacts/rollback.log: exit 1"basis accepts new_evidence, contradiction, risk, or dependency. The
seat resolves the returned requestId:
agents-city committee floor-grant "$DELIBERATION_ID" --request-id "$REQUEST_ID"
# or:
agents-city committee floor-deny "$DELIBERATION_ID" \
--request-id "$REQUEST_ID" \
--reason "The evidence is already in the synthesis"Once granted, that member has exactly one reply and releases the floor by using it:
agents-city committee reply "$DELIBERATION_ID" \
--claim "Shipping with the current script is unsafe" \
--evidence "artifacts/rollback.log: exit 1" \
--consequence "Block until fixed and rerun rollback"The reply reaches the seat and is heard by the whole committee. Other members
do not answer the speaker directly: if one finds new evidence, a contradiction,
a material risk, or a dependency, it asks the seat for another turn. The seat
grants or denies it, and only then may that agent speak. This is real specialist
conversation mediated like an executive committee, not an all-to-all chat. Two
active turns cannot coexist; every grant permits one intervention;
maxRebuttals bounds the cascade per member; and the seat must resolve every
pending request before deciding.
5. Decide and attribute
agents-city committee decide "$DELIBERATION_ID" \
--outcome "Fix rollback and ship a 10% canary" \
--rationale "This limits impact and satisfies reversibility" \
--owner "Release owner" \
--executor api \
--verifier qa \
--verification-question "Do rollback and canary pass end to end?" \
--selected-evidence "full suite is green" \
--selected-evidence "reproducible rollback failure" \
--decisive-contributors qa \
--rejected-option "Immediate full rollout" \
--dissent "web prefers a 25% canary" \
--reopen-if "5xx errors exceed 1% for five minutes"selectedEvidence, decisiveContributors, and reopenIf are required. If
another identity is available, verifier cannot equal executor. Dissent stays
in the act even when it does not change the decision. Use JSON input when more
than one decisive contributor must be recorded.
6. Verify, replan, or close
Only the assigned verifier may run:
agents-city committee verify "$DELIBERATION_ID" \
--result pass \
--evidence "artifacts/e2e-rollback.txt" \
--check "canary returns 200" \
--check "rollback restores the previous version" \
--residual-risk "The first hour at full load remains unobserved"After fail, the seat must replan and then synthesise/decide again:
agents-city committee replan "$DELIBERATION_ID" \
--reason "Rollback still leaves an incompatible schema"After pass, the seat may close:
agents-city committee close "$DELIBERATION_ID" \
--summary "Canary verified; rollout authorised" \
--learning "Test rollback before fixing a release window" \
--followup "Watch 5xx rates for the first hour"A deliberation cannot close without reproducible passing verification. If it is no longer relevant, the seat may cancel it:
agents-city committee cancel "$DELIBERATION_ID" \
--reason "The release was replaced by another candidate"State, events, and a readable act remain in deliberations/. history
summarises recent decisions and decisive contributions to expose repeated
influence. That count is a review signal, not automatic evidence of capture.
Claude /city: commands
These commands come from the Claude plugin. They do not exist inside Codex,
OpenCode, or Kimi TUIs; use the equivalent agents-city terminal commands there.
| Command | Use case |
|---|---|
| /city:setup [--city N] [--tui] [--demo] | create/open a city through the shared flow |
| /city:join [--domain D\|--role R\|--repos\|--agent-roles\|--goal\|--engines] | compatibility name for configuring the seat; does not add a person |
| /city:session [--no-yolo] [--only a,b] | open or resume this city's tmux |
| /city:settings [domain\|role\|repos\|agent-roles\|goal\|engines\|roads\|skills] | read or change one configuration area |
| /city:goals | show or edit the current goal |
| /city:committee QUESTION | prepare and open a chaired deliberation |
| /city:committee status ID | inspect the next legal transition |
| /city:round [--to owner/city] [--since DATE] | compare goal and local evidence; consult relevant roads |
| /city:notice [--pr N\|--since REF] [--dry] | notify only affected cities about a verified change |
| /city:propose owner/city [SUBJECT] | send an evidence-backed proposal |
| /city:team | historical alias: list cities, active city, repos, and roads; not people |
| /city:exit [CITY] [--dry-run] | show or close managed processes |
/city:notice --dry sends nothing. /city:round and /city:propose can only use
destinations present in road list. A reply from another city informs the seat;
it never gains authority to command a local repo directly.
Use-case cookbook
Case 1: start from zero with one city and Claude
cd /path/to/agents-city
npm pack
npm install -g ./agents-city-*.tgz
agents-city seat- Choose the domain.
- Choose the seat role.
- Select repositories or continue with none.
- Define or skip the goal.
- Press Enter in the runtime picker to keep Claude.
Result: a home city, an <owner>-home session, one seat window, and one
window per selected local repo. Agents City keeps one official Claude Code
process per window and feeds it through persistent stream-json; it does not
request a custom Channel or require admin/per-window approval.
Case 2: use Codex as the main seat
agents-city seat --enginesChoose Codex on the seat row, confirm the other rows, and open the city. Agents
City starts codex app-server on loopback and opens the official TUI with
codex --remote. The TUI creates its persisted thread; the gateway detects only
the new thread for that working directory and joins it through thread/resume.
You should type directly into Codex. A city> prompt in a Codex seat means an
old version or a failed launch; it is not the intended Codex interface.
Case 3: mix runtimes per repository
agents-city seat --city product --enginesExample selection:
seat Codex
api Claude / opus model / high effort
web Codex
analytics OpenCode
research KimiEach choice persists in the card. The next seat run reuses it. To test another
combination without retaining old processes:
agents-city exit product --dry-run
agents-city exit product
agents-city seat --city product --enginesCase 4: use a local model through OpenCode
Agents City does not choose OpenCode's provider. In the runtime picker, select OpenCode and enter the command/model accepted by your installation, for example:
opencode -m lmstudio/qwen3-coderValidate it independently first:
opencode -m lmstudio/qwen3-coderThen run agents-city seat --engines. Bus delivery reaches OpenCode through
HTTP/SSE; the model may be local while Agents City keeps the same typed envelope.
Case 5: use a CLI that is not natively integrated yet
Choose “another command (terminal fallback)” under --engines and enter, for
example, gemini. Agents City stores:
runs.api: terminal:geminiThe prefix makes it explicit that this window may need visible tmux injection.
An unknown command without terminal: is rejected when reading a hand-edited
card; known runtimes never silently degrade to terminal transport.
Case 6: create several cities for the same user
agents-city cities create product
agents-city seat --city product
agents-city cities create client-a
agents-city seat --city client-a
agents-city cities listExpected result:
~/.agents-city/<owner>/product/
~/.agents-city/<owner>/client-a/Each city has its own domain, role, goal, repos, recognised skills,
deliberations, roads, runtime, and tmux session. home has no special privilege.
Case 7: give every repo a different speciality
agents-city seat --city product --agent-rolesAssign po to the main repo, seo to the portfolio, and data-engineer to the
pipeline even when the seat domain is software. The picker can search roles
from other domains. Speciality changes perspective and editable context; all
repo agents retain technical member authority.
Case 8: work without a preloaded profile
agents-city seat --city lab --role blank
agents-city seat --city lab --agent-rolesAlso select blank for repos that should receive no profile. No role knowledge
file is created and no hidden role is inferred. Repo instructions and skills
continue to work normally.
Case 9: connect two local cities
agents-city road connect product client-a
agents-city road list product
agents-city road list client-aThe road is written at both ends. Start both cities and, from one seat:
CITY_OWNER=alice
AGENTS_CITY_DATA="$HOME/.agents-city/$CITY_OWNER/product" \
agents-city bus send "$CITY_OWNER/client-a" "Does this change affect your contract?"Inside a normal session, you do not need to set AGENTS_CITY_DATA; it is already
injected into each window. The example makes it explicit for an outside terminal.
Case 10: connect two people on different machines
With a managed Road operator, each person pairs a computer. --city chooses the
local hub that will start the owner-level reception bridge; it does not reveal
that city or give the other person direct access to it:
agents-city connect --city product --service https://connect.example.com --trust-file roots.json
agents-city connect --city research --service https://connect.e