Downcity
Commands

Command Environment Requirements

Explain required command environment, files, and env-variable priority for all city command groups

Command Environment Requirements

This page answers one question: what environment each city command group needs to run correctly.

0) Top-level command boundary

Top-level command groups are:

  • city console
  • city agent
  • city service
  • city plugin

Commands like city chat, city task, city memory, city skill, city asr, and city tts are action commands under service/plugin systems, not top-level commands.

1) Environment by command group

Command GroupRequired EnvironmentOptional EnvironmentNotes
city initWritable ~/.downcity/NoneWrites ~/.downcity/downcity.db (sensitive fields encrypted)
city start/stop/restart/statusWritable ~/.downcity/console/NoneManages global console process and registry
city consoleConsole is running; browser can reach UI port--host, --portSingle UI instance can switch across multiple running agents
city agent createWritable target directoryNoneGenerates downcity.json, PROFILE.md, .downcity/
city agent startConsole is running; project has downcity.json + PROFILE.md--hostAgent port is always allocated by console and then registered into console registry
city agent restart/status/doctorTarget agent is registered in console registryNoneOperates through registry resolution, not arbitrary path only
city config ...Valid downcity.json exists under target path--pathReads/writes project config; does not call agent API
city config aliasWritable ~/.zshrc or ~/.bashrc`--shell zshbash`
city service list/statusNone--jsonStatic console-level service catalog; does not resolve any agent
city service start/stop/restart/commandTarget agent is running; project is registered; project has downcity.json + PROFILE.md--agent, --path, --host, --portAdvanced targeting form; prefer city <service> ... for daily usage
city plugin list/statusNone--jsonStatic console-level plugin catalog; does not resolve any agent
city plugin action ...Project has downcity.json--pathAdvanced local execution form; prefer city <plugin> ... for daily usage
city <service> <action> (e.g. city chat ...)Target agent is running--path, --host, --portForwarded through local IPC by default; explicit remote mode uses /api/services/command
city <plugin> <action> (e.g. city asr ...)Project has downcity.json--pathExecutes locally against the selected project

Additional notes:

  • city service list/status and city plugin list/status are static console catalog reads.
  • Local city service start/stop/restart/command, city task, city chat, and similar runtime commands use local IPC by default instead of HTTP.
  • Local city plugin action and city <plugin> <action> commands read the selected project and execute directly in the CLI process.
  • A call only enters remote HTTP mode when you explicitly pass --host or --port.
  • In remote HTTP mode, token resolution order is: --token > DC_AUTH_TOKEN.
  • sessionId and chatKey are execution context, not authentication tokens.

1.1) DC_AUTH_TOKEN

The most important rule first:

  • For most users, you do not need to care about auth env vars for normal local city ... usage.

That is because local calls now use IPC by default. These variables only matter when a call is explicitly made through remote HTTP.

VariablePrimary PurposeWho Sets ItTypical Use
DC_AUTH_TOKENexplicit user override for a CLI/API calluser, script, CIyou want this specific city ... invocation to authenticate as a specific token

Recommended rule:

  • When you explicitly make a remote HTTP call from your terminal, CI, or a script, prefer --token or DC_AUTH_TOKEN
  • Do not treat sessionId or chatKey as auth tokens; they only define execution context

Unified priority order

When a city ... invocation is explicitly using remote HTTP, the final auth resolution order is:

  1. explicit --token
  2. DC_AUTH_TOKEN

That means:

  • --token always overrides everything else
  • DC_AUTH_TOKEN is the only env-level auth source used for remote HTTP
  • without either one, explicit remote HTTP calls fail with Missing bearer token

Common mistakes

  • Mistake 1: using sessionId as a token Not valid. sessionId only decides where execution belongs.
  • Mistake 2: assuming local city task or city chat always needs a token first Not true anymore. Normal local calls now use IPC and do not need a Bearer token.
  • Mistake 3: assuming agent shell/script subprocesses automatically inherit a usable token Not anymore. Generic subprocesses do not inherit Bearer tokens by default; if you intentionally call remote HTTP, pass a token explicitly.
  • Mistake 4: treating local IPC commands and remote HTTP commands as the same auth model They are different. Local defaults to IPC; only explicit remote HTTP uses DC_AUTH_TOKEN.

How to read Missing bearer token

If an explicit remote HTTP call such as:

  • city service list --host 127.0.0.1 --port 5314
  • city task create --host 127.0.0.1 --port 5314 ...

returns:

  • Missing bearer token

check in this order:

  1. did you pass --token
  2. is DC_AUTH_TOKEN set in the current shell
  3. does this invocation actually need remote HTTP, or should it be using local IPC instead

2) Context env requirements for common commands

city chat ...

  • If --chat-key is omitted, it tries DC_CTX_CHAT_KEY
  • If --session-id is omitted, it first tries DC_SESSION_ID
  • In agent shell, these DC_CTX_* variables are usually injected automatically

city task ...

  • Task creation/run needs sessionId
  • You can pass --session-id explicitly
  • Or first fallback to DC_SESSION_ID
  • Local calls use IPC by default and do not need a Bearer token
  • Only explicit remote HTTP calls resolve auth through --token / DC_AUTH_TOKEN

Chat channel credentials

  • The only path is binding services.chat.channels.<channel>.channelAccountId in downcity.json.
  • Real credentials (botToken / appId / appSecret) are stored in global ~/.downcity/downcity.db (channel_accounts).
  • downcity.json and agent .env no longer carry these credentials.

3) city service target agent resolution order

For city service start/stop/restart/command:

  1. explicit --agent <name> (highest priority)
  2. if --agent omitted and --path is default ., try DC_AGENT_NAME first
  3. fallback to --path or default .
  4. if default . and DC_AGENT_PATH exists, resolve . to it first

Still must satisfy:

  • resolved path is registered in console registry
  • resolved path contains downcity.json and PROFILE.md

4) Runtime transport and endpoint resolution (host/port)

Default rule:

  1. no --host / --port: use local IPC
  2. --host or --port provided: use remote HTTP

Only after a command enters remote HTTP mode does the endpoint resolution below apply.

For agent API calls (service/plugin/action commands):

  1. explicit CLI args: --host / --port
  2. env vars: DC_SERVER_HOST/PORT
  3. env vars: DC_CTX_SERVER_HOST/PORT
  4. daemon meta args (.downcity/.debug/downcity.daemon.json)
  5. default: 127.0.0.1:5314

Normalization rule:

  • 0.0.0.0 and :: are normalized to 127.0.0.1

5) Variable injection sources

Injected after agent startup

  • DC_AGENT_PATH
  • DC_AGENT_NAME
  • DC_SERVER_HOST
  • DC_SERVER_PORT

Injected into agent shell subprocess

  • DC_SESSION_ID
  • DC_CTX_REQUEST_ID
  • DC_CTX_SERVER_HOST
  • DC_CTX_SERVER_PORT

For multi-agent workflows, prefer explicit target on advanced commands:

city service restart task --agent my-agent
# or
city service restart task --path /abs/path/to/agent

For catalog inspection, no target is required:

city service list
city plugin list

Example Output (Based on Current Implementation)

The examples below are aligned with current command implementations in packages/downcity/src (including default output mode and field structure). Placeholder values are used for environment-specific fields.

$ city service list --json
{
  "success": true,
  "count": 4,
  "services": []
}
$ city chat send --text "hi"
{
  "success": false,
  "error": "Failed to parse command input: <error>"
}