Turn a code repository into a conversational, executable, and observable agent runtime.
Downcity is an agent platform for local projects and team workflows. It combines your repository, models, sessions, tools, services, plugins, and control plane into one system so a project can run long-lived agents with traceable execution and extensible interfaces.
- Repo-native agent runtime: the repository is the working context, memory boundary, and execution surface.
- Platform plus runtime separation:
@downcity/citymanages the platform;@downcity/agentfocuses on single-agent execution. - Long-running operations: run agents as managed daemons, inspect status, review history, and interact through CLI or Console.
- Observable by default: sessions, logs, runtime state, and operational surfaces are designed to be inspectable.
- Extensible architecture: services, plugins, SDK APIs, and UI components are all designed as explicit integration surfaces.
| Package | Purpose |
|---|---|
@downcity/city |
Platform layer and CLI for city runtime, Console gateway, multi-agent registration, model pool, global config, and daemon management. |
@downcity/agent |
Single-agent runtime and SDK for sessions, tool loops, services, plugins, HTTP/RPC, sandboxing, and host integration. |
@downcity/ui |
React + Tailwind UI SDK for reusable Console and host-application components. |
products/chrome-extension |
Chrome extension for Console connectivity, page context, and inline composition workflows. |
homepage |
Official website and end-user documentation site. |
- Repo is the Agent: initialize a project with
PROFILE.md,SOUL.md,downcity.json, and.downcity/. - City control plane: run
city startorcity consoleto manage agents and access the control surface. - Agent daemon lifecycle: create, start, stop, restart, inspect, chat with, and diagnose project agents.
- Global model pool: manage providers and models through
city model, then bind projects to model IDs. - Built-in services:
chat,task,memory,shell, andcontact. - Built-in plugins:
skill,auth,web,asr,tts, andworkboard. - SDK access: embed a local agent or call a remote agent over HTTP.
npm install -g @downcity/city
# or
npm install -g downcity
# or
pnpm add -g @downcity/city
# or
pnpm add -g downcityBoth commands below are equivalent:
city --version
downcity --version@downcity/city and downcity publish the same CLI contents. city update upgrades whichever package you originally installed globally.
city initThis sets up the global Downcity storage and configuration, by default under ~/.downcity/.
city model create
city model list
city model use <modelId>
city model test model <modelId>city resolves downcity.json.execution.modelId into a runtime LanguageModel and injects it into agent sessions.
Run this inside the target repository:
city agent create .This creates or updates:
your-project/
├── PROFILE.md
├── SOUL.md
├── downcity.json
├── .agents/
│ └── skills/
└── .downcity/
├── cache/
├── config/
├── data/
├── debug/
├── logs/
├── profile/
├── public/
├── schema/
├── session/
└── tasks/
city agent start .
city agent status .
city agent chat -m "Summarize this repository"To run in the foreground:
city agent start . --foregroundcity start --console
# or
city consoleUseful status commands:
city status
city agent list
city console statusimport { Agent } from "@downcity/agent";
import { createOpenAI } from "@ai-sdk/openai";
const openai = createOpenAI({
apiKey: process.env.OPENAI_API_KEY!,
});
const agent = new Agent({
id: "repo-helper",
path: "/path/to/project",
tools: {},
});
const session = await agent.session();
await session.set({
model: openai.responses("gpt-5"),
});
const turn = await session.prompt({
query: "Summarize the repository structure",
});
const result = await turn.finished;
console.log(result.text);@downcity/agent does not resolve provider or model IDs for you. In SDK mode, the host application creates the model and injects it into the session.
import { RemoteAgent } from "@downcity/agent";
const agent = new RemoteAgent({
baseUrl: "http://127.0.0.1:15314",
});
const session = await agent.session();
const turn = await session.prompt({
query: "Check the latest task execution status",
});
const result = await turn.finished;
console.log(result.text);downcity/
├── packages/
│ ├── agent/
│ ├── city/
│ └── ui/
├── products/
│ └── chrome-extension/
├── homepage/
├── scripts/
├── package.json
└── pnpm-workspace.yaml
- Product docs: downcity.ai/docs
- Agent SDK docs: downcity.ai/agent-sdk-docs
- UI SDK docs: downcity.ai/ui-sdk-docs
- Developer docs: downcity.ai/devdocs
- Chinese overview: README.zh-CN.md
- Package docs: packages/agent/README.md, packages/city/README.md, packages/ui/README.md
Install dependencies:
pnpm installBuild:
pnpm build
pnpm build:agent
pnpm build:city
pnpm build:homepage
pnpm build:extensionTypecheck:
pnpm typecheck
pnpm -C packages/ui typecheck
pnpm -C homepage typecheckRun in development mode:
pnpm dev:city
pnpm dev:agent
pnpm dev:ui-sdk
pnpm dev:console
pnpm dev:homepage- Downcity can execute shell commands, read and write project files, start local daemons, and receive external messages through chat channels.
- Use a clean Git branch and audit changes with
git statusandgit diff. - Keep secrets out of the repository; prefer local environment variables or
city env. - Use tokens and auth boundaries for Console, HTTP access, and chat channel integrations.
- Tighten command execution boundaries through sandbox configuration where appropriate.