在本地跑一个 amp(ampcode.com)服务端 —— 让官方 amp CLI 完全在本机工作:LLM 调用走你自己的 端点(CLIProxyAPI / ollama / vllm / one-api / opencode Zen Go / OpenAI / Anthropic …),线程、 项目、附件全部落在本地磁盘,不依赖云端。
定位:CLI 是 executor(在本地执行工具),服务端是 agent 大脑(跑 LLM、编排回合)。amp-local 替代后者。协议细节来自对 amp bundle 与真实 ampcode.com 流量的逆向,见 notes/protocol.md。
# 1. 准备配置(默认读取 ~/.amp-local/config.json,可用 AMP_LOCAL_CONFIG 指定)
cp config.example.json ~/.amp-local/config.json
$EDITOR ~/.amp-local/config.json
# 2. 启动(可选端口参数:./start.sh 9999)
./start.sh
# 3. 让 amp CLI 连到本地(API key 任意,服务端不校验)
AMP_URL=http://127.0.0.1:9876 AMP_API_KEY=local amp -x "你好"依赖:Bun(启动脚本用 bun src/main.ts)。bun install 安装依赖后即可运行。
amp CLI (executor) ──REST + WebSocket──▶ amp-local (agent 大脑)
本地执行工具 · LLM 适配器(多 provider / 多协议方言)
文件/Shell/工具注册 · 回合编排、工具调度(tool_lease)
· 线程/项目/附件/标签/技能存储
两条通道:
- REST(
/api/internal、/api/thread-actors、/actors/*、附件、线程搜索、远程线程等) - WebSocket
threadActor:文本帧 JSON-RPC 2.0(心跳ping→pong);CLI 的 executor 连接、工具结果回传、 回合消息流(delta / message_added / agent_state / tool_lease…)都走这里userActor/ runner:二进制 rivet bare 帧(client-protocol v4);侧边栏摘要、pin、runner 注册、 远程线程意图等
支持 runner(Agents Anywhere) 闭环:CLI 注册为 runner 后,/api/remote-thread 创建的远程线程
通过 runnerIntentsUpdated 事件推给对应 runner 自动执行。
所有配置在 ~/.amp-local/config.json(可用 AMP_LOCAL_CONFIG 指定),无需环境变量。结构:
| 字段 | 说明 |
|---|---|
port / dataDir / user |
监听端口、数据目录、本机用户标识(userId 同时用作项目 namespace 前缀) |
provider baseUrl |
LLM 端点,不带尾斜杠(如 http://127.0.0.1:8317/v1) |
provider apiKey / apiKeyEnv / apiKeyFile |
明文 / 环境变量名 / 文件路径(文件内容 trim 后使用);三选一,优先级 apiKey > apiKeyEnv > apiKeyFile。路径不做 ~ 展开,请写绝对路径 |
provider provider |
引用另一个 provider,继承其 baseUrl/apiKey/protocol 后再覆盖 |
llm.default |
全局默认 provider;model 为默认模型 |
llm.modes.<mode> |
每个 mode 独立绑定;缺 provider/baseUrl 时走全局默认;model 支持 models 数组 |
mode models |
fallback 模型链:数组按序尝试,上游模型间歇不可用时自动降级(如 ["gpt-4o", "gpt-4o-mini"]) |
protocol |
协议方言,见下 |
| 值 | 端点 | 适用 |
|---|---|---|
responses(默认) |
/responses(OpenAI Responses API) |
CLIProxyAPI 默认;直连 OpenAI 原生 |
chat |
/chat/completions |
ollama / vllm / one-api / opencode Zen Go 等 OpenAI 兼容网关 |
anthropic |
/messages |
直连 Anthropic(适配器可用,部分特性尚待完善) |
| 变量 | 作用 |
|---|---|
AMP_LOCAL_CONFIG |
配置文件路径(默认 ~/.amp-local/config.json) |
AMP_LOCAL_PORT |
端口 |
AMP_LOCAL_DATA_DIR |
数据目录 |
AMP_LOCAL_LLM_BASE_URL / AMP_LOCAL_LLM_API_KEY / AMP_LOCAL_LLM_MODEL |
全局默认 provider 的旧式覆盖 |
AMP_LOCAL_MODELS |
JSON 对象 {mode: model} 兼容旧写法(配置文件 modes 优先) |
- 多 provider + 多模式绑定:
low / medium / high / ultra各自映射到 provider + 模型; CLI 切换 mode 即换模型 - 协议方言适配:同一套 amp 消息块(text/thinking/tool_use/tool_result)自动转换为
responses/chat/anthropic格式,各上游怪癖(chat 要求 tool 消息紧跟 assistant、 responses 的 item_id 关联、reasoning 回传等)隔离在适配器内部 - 模型 fallback 链:
models数组按序降级 - 线程全生命周期:创建/恢复/导入(
/request/import)、归档、pin、重命名、标签、全文搜索、 编辑消息、重试、truncate、turn 串行队列、草稿 - 项目注册表:
projects.json持久化;listAccessibleProjects / getProject / createProject / updateProject / deleteProject / resolveProjectByRepositoryURLs等,支持 git remote 匹配 - 服务器实现工具(直接进 LLM 工具集,不走本地 executor):
read_threadcreate_threadthread_interactwait_for_threadsget_scheduleset_scheduleupdate_scheduleclear_scheduleTaskfinderview_medialibrarianlist_agent_modeslist_runnersget_current_user_identity - Skills:
loadSkills从~/.agents/skills、~/.config/agents/skills、~/.claude/skills及 工作区.agents/skills、.claude/skills读取 SKILL.md,CLI 落盘后 skill 工具直接可用 - 附件:上传(
/api/attachments)→ 哈希存盘 → 多级重定向下载(/attachments→/user-content/attachments→/raw-attachments,不同 origin 以适配 CLI 外部存储跟随逻辑) - Runner / 远程线程(Agents Anywhere):
registerRunner/runnerHeartbeat//api/remote-thread/createRemoteExecutorThread完整闭环 - 插件生命周期:回合发
session.start / agent.start / agent.end插件消息 - 标题自动生成:无标题线程取首条用户消息截取 48 字
| 路径 | 内容 |
|---|---|
threads/<TID>.json |
线程 + 全部消息(消息粒度持久化,中断/被杀不丢) |
projects.json |
项目注册表 |
attachments/ |
附件(sha256 文件名 + .meta.json 元数据) |
REST 端点(详见 notes/protocol.md):
| 端点 | 说明 |
|---|---|
POST /api/internal?<method> |
核心方法网关:getUserInfo loadPlugins listAgentModes loadSkills archiveThread、项目/线程/标签/账单等(方法在 query 或 body.method) |
POST /api/thread-actors |
创建/复用线程,返回 {threadId, wsToken, ...} |
POST /api/thread-actors/<id> |
标记线程已导入 |
POST /api/user-actor-credentials |
userActor 凭据 |
POST /api/remote-thread |
模拟 web 端远程创建线程(Agents Anywhere) |
POST /api/attachments |
附件上传 |
GET /api/threads/find?q= |
线程全文搜索 |
GET /actors/metadata、GET /actors/actors |
rivet actor 解析/元数据 |
POST /gateway/…/request/import |
线程数据导入 |
POST /gateway/…/action/<name> |
userActor HTTP action(rivet HTTP 通道) |
WebSocket:
threadActor:JSON-RPC 2.0 文本帧;CLI→服务器executor_connectexecutor_tools_registerclient_append_user_msgexecutor_tool_result等;服务器→CLI 初始化序列 +delta/message_added/agent_state/tool_lease等回合事件流userActor:bare/cbor 二进制帧(Init/ActionRequest/Event);getRecentThreads、setThreadPinned、registerRunner、runnerHeartbeat、订阅事件
认证:接受任意 key,不校验(Authorization: Bearer <key>;WS 用 Sec-WebSocket-Protocol
子协议携带 wsToken)。CLI 侧用 AMP_API_KEY=local 即可。
bun install # 安装依赖(@rivetkit/bare-ts、cbor-x、vbare)
bun run typecheck # tsc --noEmit
./start.sh # 或 bun src/main.ts目录结构:
src/
main.ts # 入口:Bun HTTP + WebSocket
config.ts # 声明式配置 + 环境变量覆盖
rest-api.ts # HTTP 端点(fetch handler)
ws-handler.ts # threadActor 的 JSON-RPC 消息分发
agent-loop.ts # agent 回合循环 + turn 队列 + 标题生成
llm.ts # LLM 适配器层(blocks ↔ 各协议方言 + SSE 解析)
server-tools.ts # 服务器实现工具
server-state.ts # 共享状态 + rivet bare 帧编解码
store.ts # 线程本地存储
projects.ts # 项目注册表
thread-format.ts # CLI 线程格式转换
types.ts # 协议类型定义
notes/
protocol.md # 协议规格(逆向自真实流量)
server-tools.md # 服务器工具实测格式
- 不校验 API key / 无鉴权,仅适合本机或可信网络
anthropic适配器可用但部分特性未完善;模型注册表(src/models.ts)为逆向数据,部分条目不完整- 单进程内存态会话(session),重启后线程从磁盘恢复
{ "port": 9876, // 监听端口(默认 9876;AMP_LOCAL_PORT 覆盖) "dataDir": "/home/you/.amp-local", // 数据目录(默认 ~/.amp-local;AMP_LOCAL_DATA_DIR 覆盖) "user": { "userId": "user_local", "username": "local" }, "llm": { // 命名 provider,可多个;可互相引用(provider: "cliproxy" 之类) "providers": { "cliproxy": { "baseUrl": "http://127.0.0.1:8317/v1", "apiKey": "amp-local-dev" // 明文密钥 }, "xai": { "baseUrl": "http://127.0.0.1:8000/v1", "apiKeyEnv": "XAI_API_KEY" // 从环境变量读(推荐,密钥不落盘) }, "opencode-go": { "baseUrl": "https://api.example-llm.com/v1", "apiKeyFile": "/home/you/.secrets/opencode.key", // 从文件读 "protocol": "chat" // 协议方言覆盖(见下) } }, // 全局默认 provider(model 为默认模型) "default": { "provider": "cliproxy", "model": "gpt-4o-mini" }, // mode → provider + model 绑定(low/medium/high/ultra,任意 key 均可) "modes": { "low": { "provider": "cliproxy", "model": "gpt-4o-mini" }, "medium": { "provider": "cliproxy", "model": "gpt-4o", "models": ["gpt-4o", "gpt-4o-mini"] // fallback 链(见下) }, "high": { "provider": "cliproxy", "model": "claude-3-5-sonnet" }, "ultra": { "provider": "cliproxy", "model": "claude-3-5-sonnet" } }, // 全局协议方言(可被 provider/mode 级覆盖) "protocol": "responses" } }