📖 English documentation: README.en.md
一个 bash 命令,把任意目录变成隔离的 AI Agent 运行环境。
基于 Docker 的 AI Agent CLI 运行沙箱。一行命令拉起容器,内置 Claude Code、Antigravity(agy)、Codex、Pi、OpenCode、DeepSeek Harness(dsh)六大 Agent,支持逐目录只读挂载、多镜像 profile 切换、tmux 断线重连与多机接力同步,并用 🟢🟡🔴 三色让你一眼看清每次给了 Agent 多大权限。
1. 逐目录读写控制,一行命令搞定
# 原始项目只读参考,副本目录可读写
dkagent -m ./original -r -m ./workspace/my-copy claude只读目录靠 Docker bind mount 钉在内核层——"参考 A 项目、改 B 项目"一行成立。
2. 多 Agent 统一入口:Claude / Antigravity(agy)/ Codex / Pi / OpenCode / DeepSeek Harness(dsh)全装进同一个镜像,持久化 Home 卷保留登录凭证与配置,切换无感。
3. Kali 工具链开箱即用:默认镜像基于 Kali Linux(nmap、ripgrep、Playwright 等全套);要轻量就切 slim profile(Debian slim,小三分之二)。
4. 纵深防御(Defense in Depth):Agent 自带的容器与安全措施也时有漏洞。dkagent 在外部再加一层 Docker 隔离——即使 Agent 内部防线被绕过,也碰不到宿主机文件。
| 依赖 | 用途 | 安装 |
|---|---|---|
| Docker | 必需 | Linux: apt install docker.io / macOS、Windows: Docker Desktop |
| git | 拉取本仓库 | apt install git / brew install git |
| bash 4+ | 脚本运行 | macOS 自带 bash 是 3.2,需 brew install bash |
| ssh 客户端 | dkagent sync 与远程连接 |
Linux: apt install openssh-client / macOS 自带 |
| rsync | 仅 dkagent sync 目录同步需要(卷同步走容器) |
apt install rsync / brew install rsync |
| tmux | 可选,装了自动获得断线保护 | apt install tmux / brew install tmux |
dkagent sync 的卷同步还需先构建辅助镜像 dkagent-sync(约 14MB):docker build -t dkagent-sync -f dockerfiles/Dockerfile.sync .
推荐先用 slim 镜像(构建约 2-3 分钟)跑通,再按需切换 Kali。
# 1. 安装 CLI(自动创建 ~/.config/dkagent/ 并拷贝 .env 模板)
chmod +x install.sh && ./install.sh
# 2. 填入 API Keys(切勿提交 git)
vi ~/.config/dkagent/.env
# 3. 构建 slim 镜像
docker build -t dkagent-slim -f dockerfiles/Dockerfile.slim .
# 4. 在任意项目目录下一行命令拉起
cd ~/my-project
dkagent -p slim claude --dangerously-skip-permissions关于
--dangerously-skip-permissions:真正的安全边界是容器,不是 Agent 的权限确认——容器已隔离,可以放心把"全自动"标志交给 Agent。
想用 Kali 镜像?(约 10GB,首次构建 15-30 分钟):docker compose build 后直接 dkagent claude(默认 profile 就是 kali)。
平台支持:Linux / WSL2 ✅ 原生支持;macOS brew install bash;Windows 原生 ❌ 不支持,请用 WSL2。
dkagent 会自动查找 .env 文件,把其中每行 KEY=value 注入容器(Agent 与脚本都能读到)。查找顺序:$DKAGENT_ENV 指定的路径 → ~/.config/dkagent/.env。
# 每次进入前,把物理机上的 env 文件复制为 .env,dkagent 自动注入
cp ~/projects/secrets.env ~/.config/dkagent/.env
dkagent claude # 容器内可直接读到 .env 里的所有 KEY宿主机已导出的 ANTHROPIC_API_KEY / GEMINI_API_KEY / OPENAI_API_KEY / OPENROUTER_API_KEY / DEEPSEEK_API_KEY 会覆盖 .env 同名项直接透传;空行与 # 注释自动跳过。
安全传递:环境变量经临时 --env-file(0600、运行结束即删)传给 docker——不出现在宿主进程列表(ps)与命令行回显中;--dry-run 输出里环境变量默认打码为 KEY=***,设 DKAGENT_DRY_RUN_SHOW_SECRETS=1 才显示明文。旧版回退读取“脚本所在目录 .env”的行为已移除(防止 repo 目录被种入 .env 劫持后续运行)。注意:Agent 命令以 zsh -f 启动,zsh 启动文件(.zshenv 等)里的变量不会传给 Agent——需要注入请用 .env。
所有 profile 共享同一个持久化 Home 卷——切换镜像时 zsh 配置、命令历史、Agent 登录凭证全部保留。
| Profile | 基础镜像 | 适合场景 |
|---|---|---|
kali (默认) |
Kali Linux | 安全研究、渗透测试、完整工具链 |
slim |
Debian slim | 日常编码、追求启动速度 |
dkagent claude # 默认 kali
dkagent -p slim claude # 切换精简镜像(先 docker build -t dkagent-slim ...)
dkagent --image my-custom-agent claude # 直接指定任意镜像(escape hatch)自定义 profile:在 ~/.config/dkagent/profiles 追加一行 node=my-node-agent,即可 dkagent -p node claude。
⚠️ 自定义镜像约束:要让持久化 Home 卷跨镜像复用,镜像必须创建kali用户并使用/home/kali作为 home 路径(参考dockerfiles/Dockerfile.slim),否则需用-e(临时 Home)模式。
AI Agent 在执行任务时拥有强大的文件系统权限。为防止 Agent 遭遇恶性提示词或误判时删除、清空宿主机文件(如 rm -rf 风险),dkagent 用 挂载模式 × Home 持久化 两个维度组合出清晰的风险等级,每次运行都会打印当前级别。
安全性 ▲
│
🟢 隔离级别 --no-mount + -e 完全隔离,用完即焚
│
🟢 低风险 --no-mount 隔离宿主文件,持久化 home 有配置被改风险
🟢 低风险 全只读挂载 + -e 只能读取宿主文件,退出不留痕
│
🟡 中低风险 全只读挂载 只能读取,但持久化 home 有配置被改风险
🟡 中风险 有可写挂载 + -e 可操作挂载目录,退出不留痕
│
🔴 高风险 有可写挂载 可操作挂载目录 + 持久化 home 可留后门
│
☠️ 逃逸级别 --docker-socket docker.sock = 宿主 root,无视上述所有档位
│
└────────────────────────────────────────────────▶ 便捷性
| 运行方式 | Home | 挂载模式 | 风险 | 适合场景 |
|---|---|---|---|---|
dkagent --no-mount -e |
🧊 用完即焚 | 🟢 不挂载 | 无 (🟢) | 纯粹的沙盒测试 |
dkagent --no-mount |
🏠 持久化卷 | 🟢 不挂载 | 低 (🟢) | 配置容器内环境 |
dkagent -e -m ./dir -r ... |
🧊 用完即焚 | 🟢 全只读 | 低 (🟢) | 只读参考多个项目 |
dkagent -m ./dir -r ... |
🏠 持久化卷 | 🟢 全只读 | 中低 (🟡) | 只读参考 + 持久配置 |
dkagent -e [agent] |
🧊 用完即焚 | 🔴 有可写 | 中 (🟡) | 临时编码任务 |
dkagent -e -m ... [agent] |
🧊 用完即焚 | 🔴 有可写 | 中 (🟡) | 临时沙盒编码 |
dkagent [agent] |
🏠 持久化卷 | 🔴 有可写 | 高 (🔴) | 日常高效编码(信任 Agent) |
dkagent -m ... [agent] |
🏠 持久化卷 | 🔴 有可写 | 高 (🔴) | 多目录编码任务 |
dkagent --docker-socket [agent] |
🏠/🧊 | 🐋 docker.sock | 逃逸 (☠️) | 需在容器内运行 docker 命令 |
Caution
关于 Home 卷持久化的安全提示 (🏠):
持久化 Home 卷会保留你的 Oh-My-Zsh 配置、命令历史及 Agent 的会话 Session。如果 Agent 被外部恶意控制,理论上可能通过修改持久化 Home 的 zsh 启动文件(.zshenv / .zprofile)来埋后门。为此 Agent 命令一律以 zsh -f 启动(不读任何启动文件),但 dkagent 交互 shell 模式仍会 source .zshrc(保留用户配置,属已知权衡)——交互模式下请勿运行不可信内容。对安全性有极端要求时,推荐加 -e(用完即焚)选项。
Caution
关于 --docker-socket 的安全提示 (☠️):
--docker-socket 会挂载宿主机的 /var/run/docker.sock 到容器内。这等同于把宿主机 root 权限交给容器——容器内可任意控制宿主 Docker(包括 docker run -v /:/host 读写宿主根文件系统)。仅在你完全信任 Agent 且确实需要在容器内运行 docker 命令时使用。
Caution
关于 --net host 的安全提示 (🌐):
--net host 共享宿主网络命名空间——容器与宿主网络完全互通、无隔离:容器内端口即宿主端口(双向可达),容器内任何网络监听(包括 RCE 级 API 如 dsh web)都会直接暴露到宿主网络。与 --docker-socket 同级对待,启动时脚本会打印风险提示;仅在你完全信任容器内程序时使用。常规端口暴露请用 --port(保持 bridge 隔离)。
Warning
Docker Desktop 的宿主回环通道(实测): Docker Desktop(Windows / macOS / WSL2 后端)默认向容器注入 host.docker.internal(指向 Docker 虚拟机网关,如 192.168.65.254)。实测:bridge 容器经它可以触达宿主机/物理机只绑 127.0.0.1 的服务(Windows 与 WSL2 发行版的 loopback-only 监听均被触达)——bridge 隔离并不保护宿主机的 loopback 端口,宿主机上敏感的本机服务(本地 API、开发服务器等)对容器是可见的。原生 Linux Docker 无此默认注入(需手动 --add-host)。要彻底阻断容器→宿主的网络通道,用 --net off(实测连解析都不通)。
已在宿主机登录过 Agent?把登录态一次性拷进持久化卷,避免容器内重新登录。核心思路:登录态目录 → docker run 挂载卷拷贝(命令在宿主机执行)。
| Agent | 配置目录 | 关键凭证文件 | 备注 |
|---|---|---|---|
| Claude Code | ~/.claude/ + ~/.claude.json |
~/.claude/.credentials.json (0600) |
还需单独拷 ~/.claude.json 文件 |
| Codex | ~/.codex/ |
~/.codex/auth.json |
文件不存在说明走 keychain,无法迁移 |
| OpenCode | ~/.config/opencode/ + ~/.local/share/opencode/ |
~/.local/share/opencode/auth.json |
两个目录都要拷 |
| Pi | ~/.pi/agent/ |
~/.pi/agent/auth.json |
|
| Antigravity | ~/.antigravitycli/ |
登录态存系统钥匙串 | 无法用文件迁移,容器内重新登录(终端输出授权链接 + 验证码) |
| DeepSeek Harness | ~/.dsh/($DSH_HOME 默认值) |
~/.dsh/.credentials.yaml |
Web UI 里填的 key 存此文件;更省事是直接配 .env 的 DEEPSEEK_API_KEY,无需迁移 |
# 通用模板:把宿主 <src> 拷贝进持久化卷(替换为表中对应路径)
docker run --rm -v agent_docker_kali-home:/home/kali -v "$HOME/<src>:/src:ro" \
alpine sh -c "mkdir -p /home/kali/<dst> && cp -a /src/. /home/kali/<dst>/"Warning
注意事项:Antigravity 建议容器内重新登录(登录态存系统钥匙串,迁移后大概率解不开;终端会输出授权链接 + 验证码流程);命令会覆盖容器内同名文件,先备份;macOS keychain 凭证无法用文件迁移;迁移后凭证读不到通常是属主不对,进容器 sudo chown -R kali:kali ~/.对应目录 修复。
SSH 连物理机跑 Agent 时,终端一断会话就丢。dkagent 默认自动用 tmux 包装(宿主机装了 tmux 时)——会话跑在物理机的 tmux 里,SSH 断了 Agent 继续跑:
ssh user@host
cd ~/project-a
dkagent claude # 创建 tmux 会话 dkagent-project-a,Agent 在其中运行
# SSH 断了重新连上后:
tmux attach -t dkagent-project-a # 接回原会话(再跑 dkagent 会新建 _2 会话而非 attach)每次运行新建独立 session(重名自动加 _2、_3 后缀);容器默认命名 dkagent-<目录名>,方便 docker ps 识别。可用 --tmux-name NAME 自定义会话名、--no-tmux 关闭包装;DKAGENT_NO_CONTAINER_NAME=1 禁用容器命名(回到 Docker 随机名)。
家里电脑没有公网 IP,外面 SSH 连不上——用内网穿透(NAT 穿透 / 反向隧道)打通,两种选择:
选择一:自建隧道(以 FRP 为例):一台有公网 IP 的轻量服务器跑 frps,家里电脑跑 frpc 把 SSH 22 映射到服务器端口,外面直接连服务器:ssh -p 6000 user@server.example.com。同类:ngrok、Tailscale / ZeroTier 组网。
选择二:第三方端口映射服务(以网易 UU 远程为例):免费、零服务器。家里与外面的电脑都装 UU 远程 客户端并登录同一账号;家里电脑在「设备列表 → 更多 → 端口映射」新建映射:本地访问端口(如 13022)→ 目标 127.0.0.1:22,保持规则启用;外面连本机端口即可(TCP):ssh -p 13022 user@127.0.0.1。同类:花生壳等。
手机:直接装 UU 远程 客户端远程控制家里电脑即可(手机端不支持端口映射,无需 SSH 隧道);要纯命令行编程,用 Termux + pkg install openssh 配合选择一。
安全提示:临时映射用完即关;SSH 一律用密钥而非密码。
多台电脑接力工作:dkagent sync 把持久化卷(工具配置 / 命令历史 / Agent 凭证)和项目目录同步到对端。完全手动触发,dkagent claude 等命令绝不会自动同步。
准备工作(两端各一次):装 Docker + dkagent → 配好 SSH 免密 → 构建 dkagent-sync 镜像(见前置要求)→ 编辑 ~/.config/dkagent/peers:
# 每行: alias=ssh://user@host:port(配合隧道时填映射地址,如 ssh://user@127.0.0.1:13022)
laptop=ssh://user@laptop.local:22
该文件含 SSH URL,建议
chmod 600 ~/.config/dkagent/peers。
基本用法:
dkagent sync list # 看 peers + 当前目录映射
cd ~/my-project
dkagent sync push laptop --remote-path ~/my-project # 首次(--remote-path 必填,自动存映射)
dkagent sync push laptop # 后续自动用已存映射
dkagent sync pull laptop # 反向同步(peer → 本地)
dkagent sync push laptop --dry-run # 仅预览不实跑
dkagent sync push laptop -- --exclude=.git/ --exclude=.env # 透传 rsync 参数默认行为:默认同时同步持久化卷 + 当前项目目录;卷走容器嵌套 rsync over ssh,目录走直连 rsync(更快)。默认 flags:-az --delete --numeric-ids --partial --partial-dir=.rsync-partial,ssh keepalive + 内置 10 次重试(间隔 30 秒)。
Caution
--delete 默认开启:远端独有的文件会被删除以维持镜像一致。首次同步前强烈建议 --dry-run 看会删什么——特别留意 .env API keys 与 .git/ 历史。
选项速查:--remote-path PATH / --no-volume / --no-project / --dry-run / -y / --retries N / -- RSYNC_ARGS(详见 dkagent sync --help)。
配置文件:~/.config/dkagent/peers(peer 列表)、~/.config/dkagent/sync-mapping(项目路径映射,脚本自动管理,也可 vi 编辑)。
安全约束:peer 用户名/主机与远端路径仅允许字母数字及 . _ - / ~(不支持空格,防经 rsync 远端 shell 注入);peers 文件权限非 600 时运行会告警;首次卷同步会记录 dkagent-sync 镜像指纹(~/.config/dkagent/sync-image.id),镜像被替换时拒绝执行——确为本人重建镜像时删除该文件即可重新信任;容器内只挂载本机 ssh 实际会用到的身份文件(经 ssh -G 解析)或 SSH agent socket,不再整目录挂载 ~/.ssh。
dkagent [选项] [agent名称] [附加参数...] # agent: claude/agy/pi/codex/opencode/dsh,留空进 zshdkagent # 交互式 Kali shell(挂载当前目录)
dkagent claude # 唤醒容器内 Claude Code
dkagent -m ./a -r -m ./b agy # 多目录挂载,a 只读 b 可写
dkagent -p slim claude # 切换 profile
dkagent --docker-socket claude # 容器内可用 docker(⚠️ 等同宿主 root)
dkagent --port 3080:3080 dsh web # 🌐 dsh Web UI 端口映射(首次需先建 cordis patch 绑 0.0.0.0,见下文「端口映射实战」)
dkagent --dry-run # 只打印 docker run 命令不执行| 选项 | 说明 |
|---|---|
-p, --profile NAME |
选择镜像 profile(默认 kali) |
--image NAME |
直接指定任意 Docker 镜像(优先级最高) |
-e, --ephemeral |
临时 Home 目录,退出不留痕 |
-m, --mount DIR / -r |
挂载目录(可多次);紧跟的 -r 将其设为只读 |
--no-mount |
不挂载任何宿主机目录(最安全) |
--docker-socket |
挂载宿主 docker.sock( |
--port HOST:CONTAINER |
端口映射(可重复,等价 docker run -p),如 8080:8080、127.0.0.1:3000:3000、9000:9000/udp |
--net MODE |
网络模式(默认 bridge):off 完全断网(--network none,无任何网络接口,外网/宿主端口全不可达,最安全);host 共享宿主网络(--network host),--port 均无效 |
--no-tmux / --tmux-name NAME |
关闭 / 自定义 tmux 包装 |
--env FILE |
指定 .env 配置文件 |
--lang zh|en |
界面语言(默认按 $LANG/$LC_ALL 自动识别;export DKAGENT_LANG=en 持久覆盖) |
--dry-run |
仅打印 docker run 命令,不实际启动(环境变量打码,DKAGENT_DRY_RUN_SHOW_SECRETS=1 显明文) |
-h, --help |
显示帮助 |
镜像优先级:--image > --profile > 环境变量 DKAGENT_PROFILE > 默认 kali。
DeepSeek Harness(命令 dsh)既有终端 CLI,也自带 Web UI。默认安全姿势:dsh web 只绑 127.0.0.1(官方安全默认——Web API 可执行 bash,属 RCE 级接口),仅容器内可达;不想开 Web 就直接用 CLI 形式(见要点)。要把它暴露到宿主,两种方式:
方式一:--port 端口映射(✅ 推荐:保持 bridge 隔离,暴露面只有你映射的那个端口)
# 第一次:进容器建配置(opt-in——绑 0.0.0.0 后 Web 才对容器外可见)
dkagent
mkdir -p ~/.dsh && cat > ~/.dsh/cordis.patch.yml <<'EOF'
- id: webserver
config:
host: 0.0.0.0
port: 3080
EOF
# 之后每次:
dkagent --port 3080:3080 dsh web
# 浏览器打开 http://localhost:3080 即可使用(Docker 桌面版 / 局域网机器同理)
⚠️ 安全提示:docker 的-p/-P端口映射把流量转发到容器 eth0 的 IP,容器内只监听127.0.0.1的服务收不到包(实测 5/5 全拒),且当前版本 dsh 的 CLI 故意拒绝--host 0.0.0.0——所以必须经配置层放开绑定。一旦绑 0.0.0.0 并映射端口,RCE 级 Web API 就对局域网可见;用完建议关掉容器,或删除 patch 恢复 loopback。
方式二:--net host 共享宿主网络(
dkagent --net host dsh web
# 浏览器打开 http://localhost:3080(无需 --port;此模式下 docker 忽略端口映射)--network host 下容器与宿主共享网络命名空间(官方文档确认),容器内 127.0.0.1 就是宿主的 127.0.0.1——dsh 保持默认 loopback 绑定即可直接访问。但注意:它比方式一危险得多——方式一的容器只能访问你映射的那一个端口,而 host 模式容器与宿主网络完全互通,可以访问宿主机全部端口与服务,还能直接绑定宿主端口,属高风险操作,启动时脚本会打印风险提示(见安全模型)。能不用就不用。
最安全档:完全断网跑 CLI(--net off)
dkagent --net off dsh --profile headless "跑一下测试"--network none 下容器无任何网络接口——外网、宿主端口(包括 Docker Desktop 的 host.docker.internal 回环通道)全部不可达,只靠挂载目录干活。不开 Web、不联网的任务建议都用这档。
⚠️ 平台注意(实测):WSL2 + Docker Desktop 下--network host挂到的是 Docker 虚拟机(docker-desktop distro,192.168.65.x)的命名空间,不是你的 WSL2 发行版——容器内的127.0.0.1在你的终端不可达(实测 curl 全拒)。原生 Linux Docker 上则正常共享宿主 netns。Docker Desktop 环境请用方式一--port。
要点:
- API Key:启动后浏览器里 Settings → Models 填入(存
~/.dsh/.credentials.yaml,随 Home 卷持久化),或直接写进~/.config/dkagent/.env(DEEPSEEK_API_KEY=sk-...,dkagent 自动注入容器) - 换端口:改
~/.dsh/cordis.patch.yml里的port,与--port映射(方式一)一起改 - CLI 形式:
dkagent dsh --profile headless "跑一下测试"(一次性任务,完全不暴露端口);交互 TUI 用dsh --profile tui - 加
-e(用完即焚)跑 Web UI 也完全没问题,关掉容器不留任何状态(临时 Home 不保留 patch,需每次重建)
不用 CLI 也可 docker compose run --rm 直接启动,三种模式共享同一个持久化 Home 卷(与 CLI 完全互通):agent-shell(仅 Home,🟢)/ agent-isolated(无挂载用完即焚,🟢)/ agent-sandboxed(Home + 挂载 workspace,🟡)。切换镜像:DKAGENT_IMAGE=dkagent-slim docker compose run --rm agent-shell。
桌面端 Agent(如智谱 ZCode)同样可以用这个环境。ZCode 支持直连运行中的容器(无需开放端口):容器名即 dkagent-<项目目录名>(如 dkagent-my-project),容器内用户 kali。仅支持 SSH 的 Agent,可在启动时用 --port 把容器内服务端口映射到宿主机后直接连接(如 dkagent --port 2222:22 claude,容器内需有对应服务在监听),无需隧道。
├── dkagent # 核心 bash CLI(挂载、风险分级、sync 子命令)
├── Dockerfile # 默认 profile (kali)
├── dockerfiles/
│ ├── Dockerfile.slim # slim profile(精简 Debian)
│ └── Dockerfile.sync # dkagent-sync 镜像(rsync + ssh,跨机同步用)
├── docker-compose.yaml # 备用 compose 运行模式
├── install.sh # 一键安装/卸载
├── .env.example # API Keys 配置模板
└── workspace/ # 沙盒模式工作目录
- 多目录挂载 + 逐目录只读控制 | [x] 8 档风险分级可视化 | [x] 多镜像 profile 切换
- 容器内运行 Docker(
--docker-socket) | [x] 中英文双语界面(自动识别) - 容器命名按当前目录(重名
_2_3后缀) | [x] 多机接力同步(dkagent sync push/pull,纯手动) - 断网档位(
--net off,--network none完全断网,实测可阻断 Docker Desktop 的host.docker.internal回环通道) | [ ] 出站限制档位(--net strict:默认拒绝 + 白名单;注意若策略是"只断外网、放行内网",Docker Desktop 网关地址仍可达宿主回环,须显式处理) - 容器端口映射(
--port,映射容器内任意端口到宿主机,供外部 / 桌面 Agent 通信)