This document is an audit‑ready reference for BTCA v2 covering:
- Local server HTTP API (btca-server)
- Local CLI commands (btca)
- Remote CLI commands (btca remote)
- Remote cloud APIs used by the CLI
- Authentication and installation
- Configuration files, validation, and limits
All details reflect the current repo state.
bun add -g btcabun add btca-server- Bun is required.
BTCA reads credentials from OpenCode’s auth storage:
- Linux/macOS:
~/.local/share/opencode/auth.json - Windows:
%APPDATA%/opencode/auth.json
Supported providers:
opencode— API keyopenrouter— API keyopenai— OAuth (no API keys)anthropic— API keygoogle— API key or OAuth
Environment variable overrides:
OPENCODE_API_KEY(for provideropencode)OPENROUTER_API_KEY(for provideropenrouter)
btca connect:
- If provider is
openai, runs local OAuth flow (PKCE) and writes tokens into OpenCode auth. - If provider is
opencode,openrouter,anthropic, orgoogle, prompts for API key and writes into OpenCode auth. - If provider is not handled directly, falls back to
opencode auth --provider <provider>.
btca disconnect:
- Removes provider entry from OpenCode auth file (env vars remain).
Remote commands require an API key stored at:
~/.config/btca/remote-auth.jsonStructure:
{
"apiKey": "btca_xxxxxxxxxxxx",
"linkedAt": 1706000000000
}All remote requests include:
Authorization: Bearer <apiKey>- Project config:
./btca.config.jsonc - Global config:
~/.config/btca/btca.config.jsonc - JSONC supported (comments + trailing commas)
- Precedence: global loaded first, project merged on top (project overrides conflicts)
- If project config exists, data directory resolves relative to project.
Example:
Defaults (auto‑created global config if missing):
provider:opencodemodel:claude-haiku-4-5providerTimeoutMs:300000- Default resources:
svelte,tailwindcss,nextjs
Data storage:
- Resources are stored in
${dataDirectory}/resources. - If
dataDirectoryis missing and a legacy.btca/directory exists, the project config is migrated to use.btca.
- File:
./btca.remote.config.jsonc - Remote supports git resources only.
Example:
{
"$schema": "https://btca.dev/btca.remote.schema.json",
"project": "my-project",
"model": "claude-sonnet",
"resources": [
{
"type": "git",
"name": "svelte",
"url": "https://github.com/sveltejs/svelte.dev",
"branch": "main",
"searchPath": "apps/svelte.dev",
"specialNotes": "Focus on docs",
},
],
}Remote model list (fixed):
claude-sonnetclaude-haikugpt-4ogpt-4o-mini
All commands support:
--server <url>— Use existing server (health checked)--port <port>— Port for auto-started server--no-tui— Use REPL instead of TUI--no-thinking— Hide reasoning output (REPL/ask)--no-tools— Hide tool traces (REPL/ask)--sub-agent— Clean output (no reasoning/tool traces)
Launches the TUI by default. With --no-tui, launches REPL.
REPL commands:
/help— show help/resources— list resources/clear— clear session resources/quitor/exit— exit
REPL supports @resource mentions.
Add a git repo or local directory resource.
Options:
-g, --global— (flag exists; config target is still resolved by presence of project config)-n, --name <name>-b, --branch <branch>(defaultmain)-s, --search-path <path...>--notes <notes>-t, --type <git|local>
Behavior:
- If no argument, interactive wizard.
- If
--typeomitted, auto‑detects URL vs path. - Git URLs are normalized to base repo when GitHub.
- Local paths are resolved to absolute paths.
Remove a resource by name. If omitted, interactive picker.
Options:
-g, --global— (flag exists; not implemented as a strict global override)
List all configured resources.
Ask a one‑shot question with streaming output.
Options:
-q, --question <text>required-r, --resource <name...>(repeatable)--no-thinking,--no-tools,--sub-agent
Behavior:
@resourcementions are resolved and merged with-rflags.- Valid mentions are stripped from the query text before sending.
- If no resources specified, uses all configured resources.
- Uses
/question/streamSSE endpoint.
Configure provider + model.
Options:
-g, --global-p, --provider <id>-m, --model <id>
Behavior:
- If provider/model specified, updates config.
- Otherwise, interactive provider selection (connected providers listed first), then model selection.
- Prompts for auth if required.
Disconnect provider credentials.
Options:
-p, --provider <id>
Behavior:
- If omitted, interactive picker.
Project setup wizard.
Options:
-f, --force— overwrite config
Behavior:
- Prompts for setup type: MCP (remote) or CLI (local)
- MCP path:
- Prompts for API key (if missing), validates it
- Creates
btca.remote.config.jsonc - Writes
.claude/skills/btca-remote/SKILL.md
- CLI path:
- Creates
btca.config.jsonc - Handles
.btca/and.gitignore - Writes
.claude/skills/btca-local/SKILL.md
- Creates
Clears all locally cloned resources.
Starts local server.
Options:
-p, --port <port>(default8080)
All remote commands require authentication via btca remote link.
Authenticate with BTCA cloud API.
Options:
--key <apiKey>
Behavior:
- Prompts for API key if not provided.
- Validates key by calling MCP listResources.
Removes stored API key.
Shows sandbox state, plan, version, and current project info.
Pre‑warms sandbox and returns when ready.
Adds a git resource to local remote config and syncs to cloud.
Options:
-n, --name <name>-b, --branch <branch>-s, --search-path <path...>--notes <notes>
Behavior:
- Creates local config if missing (prompts for project name).
- Normalizes GitHub URLs.
- Syncs resource to cloud; warns if sync fails.
Syncs local remote config with cloud.
Options:
--force— overwrite cloud on conflicts
Behavior:
- Detects conflicts (same resource name but different config).
Ask a question via cloud sandbox.
Options:
-q, --question <text>required-r, --resource <name...>
Behavior:
- Validates resources by calling
listResourcesfirst. - If none specified, uses all available resources.
Fetch full thread transcript.
Options:
--json--markdown(default)
Creates btca.remote.config.jsonc.
Options:
-p, --project <name>
Outputs MCP configuration snippet:
opencode: JSON config blockclaude: CLI command for Claude Code
Base URL:
- Local:
http://localhost:<port>
No authentication required.
Error format:
{ "error": "Message", "tag": "ConfigError", "hint": "Actionable hint" }Health check.
Response:
{ "ok": true, "service": "btca-server", "version": "0.0.1" }Returns current config.
Response:
{
"provider": "opencode",
"model": "claude-haiku-4-5",
"providerTimeoutMs": 300000,
"resourcesDirectory": "/abs/path/resources",
"resourceCount": 3
}Lists configured resources.
Response:
{
"resources": [
{
"name": "svelte",
"type": "git",
"url": "https://github.com/sveltejs/svelte.dev",
"branch": "main",
"searchPath": "apps/svelte.dev",
"searchPaths": null,
"specialNotes": "..."
},
{
"name": "internal-docs",
"type": "local",
"path": "/abs/path/docs",
"specialNotes": null
}
]
}Lists supported providers and connected providers.
Response:
{
"all": [
{ "id": "opencode", "models": {} },
{ "id": "openrouter", "models": {} }
],
"connected": ["opencode"]
}Reloads config from disk.
Response:
{ "ok": true, "resources": ["svelte", "tailwindcss"] }Ask a question (non‑streaming).
Request:
{
"question": "How do I create a store?",
"resources": ["svelte"],
"quiet": true
}Response:
{
"answer": "...",
"model": { "provider": "opencode", "model": "claude-haiku-4-5" },
"resources": ["svelte"],
"collection": { "key": "svelte", "path": "/abs/path/collection" }
}Ask a question with streaming SSE output.
Request: same as /question.
Response: SSE event stream (see §7).
Updates provider/model.
Request:
{ "provider": "opencode", "model": "claude-haiku-4-5" }Response:
{ "provider": "opencode", "model": "claude-haiku-4-5" }Adds a new resource.
Request (git):
{
"type": "git",
"name": "hono",
"url": "https://github.com/honojs/website",
"branch": "main",
"searchPath": "docs",
"specialNotes": "Focus on docs"
}Request (local):
{ "type": "local", "name": "docs", "path": "/abs/path/docs" }Response: the created resource (GitHub URLs normalized to base repo).
Remove resource by name.
Request:
{ "name": "hono" }Response:
{ "success": true, "name": "hono" }Clears all cached resource clones.
Response:
{ "cleared": 5 }SSE format:
event: <type>
data: <json>Event types:
metareasoning.deltatext.deltatool.updateddoneerror
meta example:
{
"type": "meta",
"model": { "provider": "opencode", "model": "claude-haiku-4-5" },
"resources": ["svelte"],
"collection": { "key": "svelte", "path": "/abs/path/collection" }
}tool.updated example:
{
"type": "tool.updated",
"callID": "tool-1",
"tool": "read",
"state": { "status": "running", "input": { "path": "README.md" } }
}done example:
{
"type": "done",
"text": "final answer",
"reasoning": "full reasoning",
"tools": [
{
"callID": "tool-1",
"tool": "read",
"state": {
"status": "completed",
"input": { "path": "README.md" },
"output": "..."
}
}
]
}error example:
{ "type": "error", "tag": "ConfigError", "message": "..." }Resource name:
- Max 64 chars
- Regex:
^@?[a-zA-Z0-9][a-zA-Z0-9._-]*(/[a-zA-Z0-9][a-zA-Z0-9._-]*)*$ - No
.., no//, no trailing/
Branch name:
- Max 128 chars
- Regex:
^[a-zA-Z0-9/_.-]+$ - Must not start with
-
Search path:
- Max 256 chars
- No
.. - No absolute paths
- No newline characters
Special notes:
- Max 500 chars
- No control characters
Question length:
- Max 100,000 chars
Resources per request:
- Max 20
Git URL validation:
- HTTPS only
- No embedded credentials
- No localhost or private IPs
- GitHub URLs normalized to base repo
All remote API calls require:
Authorization: Bearer <apiKey>
Content-Type: application/jsonPOST /api/mcp (JSON‑RPC 2.0)
Method: tools/call
Supported tools:
listResourcesaskaddResourcesync
Example payload:
{
"jsonrpc": "2.0",
"id": 1700000000000,
"method": "tools/call",
"params": {
"name": "ask",
"arguments": {
"question": "...",
"resources": ["svelte"],
"project": "default"
}
}
}Response shape:
{
"result": {
"content": [{ "type": "text", "text": "..." }],
"isError": false
}
}GET /api/cli/status?project=<name>- Returns
{ instance, project? }
- Returns
POST /api/cli/wake- Returns
{ serverUrl }
- Returns
GET /api/cli/threads/:threadId- Returns
{ thread, messages }
- Returns
GET /api/cli/threads?project=<name>- Returns
{ threads }
- Returns
GET /api/cli/questions?project=<name>- Returns
{ questions }
- Returns
GET /api/cli/projects- Returns
{ projects }
- Returns
--globalflags exist on several commands, but the effective target is determined by whether a project config exists; there is no strict global override path.btca remote adddefaults differ between paths:- Interactive path uses model
claude-haiku. - Non‑interactive path uses model
claude-sonnet.
- Interactive path uses model
{ "$schema": "https://btca.dev/btca.schema.json", "provider": "opencode", "model": "claude-haiku-4-5", "dataDirectory": ".btca", "resources": [ { "type": "git", "name": "svelte", "url": "https://github.com/sveltejs/svelte.dev", "branch": "main", "searchPath": "apps/svelte.dev", "specialNotes": "Focus on docs content", }, { "type": "local", "name": "internal-docs", "path": "/abs/path/docs", }, ], }