PackagesCity CLI

CLI Quickstart

First-time Downcity CLI usage starts by separating fed/downfed from city/downcity.

The downcity package installs two command families:

  • fed / downfed: manages and deploys Federations.
  • city / downcity: manages local Agents, local plugins, chat/gateway, and the local user's selected Federation login.

Install

npm i -g downcity

Check versions:

fed -v
city -v

Manage Federations With fed

Use fed when you are creating, deploying, or operating the shared backend.

fed
fed create .
fed create ./edge-fed --template cloudflare-workers
fed create ./custom-fed --template git://example.com/custom-fed.git
fed deploy
fed deploy --dry-run
fed deploy --verify

fed create generates a Local Node.js + SQLite project by default. --template can select cloudflare-workers or a Git template. Project identity and deployment intent live in federation.json.

fed deploy deploys the current project whether the destination is local or remote. Local deploys allocate a port starting at 12314 and start a managed process; the first deploy interactively sets an administrator ID and password, while ordinary redeploys preserve the existing administrator. Redeploying the same fed_id replaces the old process without changing administrator credentials. Cloudflare Workers deploys prepare D1, Queue, and R2, publish the Worker, then create a time-limited administrator Session Token for the local registry.

Manage deployed Federations:

fed server add
fed server
fed query GET /health
fed query GET /v1/ai/models
fed query POST /v1/ai/image/result --data '{"job_id":"..."}'

Federation URLs, active state, administrator IDs, administrator Session Tokens, local PIDs, ports, logs, and deployment status are stored in the system-level Federation registry and do not depend on the current directory. downfed has no default Federation. fed deploy only registers or updates an instance and never changes active_server_url; a Federation becomes active only when the user explicitly opens it in downfed. fed query adds Authorization: Bearer when a valid administrator Session exists and asks you to log in again when it expires.

federation.json

{
  "schema": 1,
  "type": "federation",
  "id": "fed_example",
  "name": "example",
  "entry": "src/index.ts",
  "deployment": {
    "target": "local",
    "scripts": {
      "build": "pnpm typecheck",
      "deploy": "pnpm start"
    }
  }
}

deployment.scripts is optional. Missing scripts use the target's built-in deployer; a configured build or deploy script replaces only that stage.

Manage Local Agents And Login State With city

Use city when the local machine needs to join a Federation, sign in as a user, run Agents, or open chat.

city
city federation status
city federation join https://your-federation.example.com
city federation login
city agent create .
city agent list
city agent start
city agent chat

city agent chat keeps one live subscription to the active Session and merges Message, Part, text, reasoning, Tool, Interaction, and configuration updates as they arrive. The header shows the active Session model. Use /model to choose from the current user's available model catalog, or /model <model-id> to switch directly. A model change affects only the active Session and reaches the UI through a Session Mutation; it does not change the Agent default model. When /session switches conversations, the TUI subscribes to the new Session before loading its full snapshot and then merges any buffered events. Visible reasoning text is rendered in Assistant Part order with subdued styling; reasoning metadata alone does not produce invented reasoning content.

city federation ... only manages local Federation membership and user login state. It does not deploy Federations.

Each background Agent start has a unique instance ID. city agent stop verifies the PID, project path, and instance ID together. If pid/meta files are stale or the PID has been reused by another process, the CLI only removes stale state files and does not signal that unrelated process.

After selecting an OAuth provider such as GitHub or Google, the CLI always prints the authorization_url. In a local graphical session it also attempts to open the default browser. When connected to a VPS over SSH or running headlessly, open that URL in your own browser while the CLI waits for the login result.

Default Storage In federation.json

Cloudflare Workers Federation projects can declare default storage in federation.json. R2 is currently supported:

{
  "deployment": {
    "target": "cloudflare-workers",
    "resources": {
      "storage": {
        "type": "r2",
        "binding": "DOWNCITY_STORAGE",
        "name": "downcity-storage",
        "public_url_prefix": "https://images.example.com"
      }
    }
  }
}

During deploy, fed deploy first checks whether a same-name R2 bucket exists. If it is missing and the deploy is not a dry run, the CLI creates it automatically. The CLI then writes the binding to the temporary wrangler.toml as [[r2_buckets]] and emits public_url_prefix as a Worker var.

Common Misunderstandings

city deploy is not the deploy entry

Use fed deploy to deploy Federations.

city create is not the Federation project entry

Use fed create to scaffold a Federation project. Use city agent create to create a local Agent project.

fed and city have different roles

  • fed: manages shared backend and admin-side capabilities.
  • city: manages local Agents and user-side connection state.