| name | redeploy-local |
| description | After code changes, auto-detect the project's build system and local deployment method for a given directory, then build the project and restart its locally-deployed environment (Docker Compose / systemd / process manager). Never assumes — asks only when detection is ambiguous. Caches detected commands per project in .cortex/redeploy-local.yaml; re-invocations on the same project skip re-scanning until signal files change, the cache expires (30 days), or the skill version bumps. |
| description_zh | 代码修改后,自动探测目标目录的构建系统与本地部署方式,执行构建并重启本地部署环境(Docker Compose / systemd / 进程管理器)。无法确定时才询问,不盲猜。首次探测后将结果缓存至 .cortex/redeploy-local.yaml;下次同项目调用直接复用,直到信号文件变更、缓存过期(30 天)或技能版本变化。 |
| tags | ["deploy","build","local","workflow","automation","docker","systemd","pm2"] |
| version | 3.2.0 |
| license | MIT |
| recommended_scope | both |
| metadata | {"author":"ai-cortex"} |
| triggers | ["redeploy local","redeploy locally","rebuild and redeploy","update local env","rebuild local","deploy local","build and deploy","本地重部署","重部署本地","更新本地环境","重建并部署","本地部署"] |
| input_schema | {"type":"free-form","description":"A directory path (defaults to CWD). May include an optional override for build or deploy command via .cortex.yaml. Cache at .cortex/redeploy-local.yaml is honored when valid."} |
| output_schema | {"type":"side-effect","description":"Build artifacts produced; local deployment updated (Docker Compose / systemd / process manager); inferences cached to .cortex/redeploy-local.yaml on success. Outputs (1) an inference report attributing each chosen command to its evidence source, and (2) a structured run report with command, exit code, and duration per step."} |
技能(Skill):本地重部署(Redeploy Local)
目的(Purpose)
Agent 修改代码后,执行项目的构建并重启本地部署的环境——无需用户了解项目技术栈。适用于通过 Docker Compose、systemd unit 或进程管理器(pm2、supervisorctl)在本地部署的项目。有意排除热重载开发服务器;目标是运行中的本地环境,而非开发监听模式。
核心目标(Core Objective)
首要目标:给定一个目录,成功执行一次构建和一次本地部署重启,并报告运行了什么。
成功标准(必须全部满足):
- ✅ 目录已确认:目标目录在任何命令执行前已验证存在
- ✅ 构建命令已确定或已配置:命令可追溯至配置文件或检测启发式规则——不凭空生成
- ✅ 构建成功:退出码 0;构建产物存在于预期位置
- ✅ 部署方式已确定或已配置:部署目标已识别(Compose / systemd / pm2 / supervisord)
- ✅ 部署已重启:服务/容器已重启并可达(健康检查或状态检查通过)
- ✅ 运行报告已输出:每个执行步骤的命令 → 退出码 → 耗时表格
验收测试:技能完成后,本地部署的服务反映最新代码变更,且状态检查报告 healthy/running。
范围边界(Scope Boundaries)
本技能负责:
- 从项目文件检测构建系统(package.json、Makefile、go.mod、Cargo.toml、pom.xml、build.gradle、*.csproj、pyproject.toml)
- 从项目文件检测本地部署方式(docker-compose.yml / compose.yaml、systemd unit、pm2 ecosystem 文件、supervisord.conf)
- 读取项目级配置覆盖(
.cortex.yaml build_command / deploy_command)
- 将成功推断持久化到
.cortex/redeploy-local.yaml,下次运行复用
- 顺序执行构建 + 重启
- 上报结果
本技能不负责:
- 热重载开发服务器(npm run dev、vite、next dev)——这些不是"本地部署环境"
- 远程部署(SSH、云、Kubernetes)——使用针对远程基础设施的部署技能
- 数据库迁移——在调用本技能前单独运行
- Secret 注入——环境变量 / secrets 必须已在部署中可用
转交点:运行报告显示所有步骤退出码为 0 时,技能完成。若任一步骤失败,技能上报失败并停止——不自动重试或修复构建错误。
使用场景(Use Cases)
- 编辑后重建:Agent 修改代码完毕;用户想让本地服务反映变更,无需手动运行 build + restart 命令
- 多栈项目:项目混合编译语言(Go、Rust)与 Docker Compose 部署;技能自动检测两者
- 脚本化覆盖:通过
.cortex.yaml 实现 CI 式可重现性——每次运行相同命令,无检测差异
- 团队共享环境:不同团队成员本地配置各异;技能按检测到的信号自适应,而非要求相同工具链
检测方式(Detection Approach)
本技能不维护"文件 X → 命令 Y"的硬编码映射。构建和部署命令因项目而异——两个 Go 项目可能有截然不同的构建约定(自定义 ldflags、输出路径、交叉编译目标),而 Node 项目的 build 脚本未必是部署所需(可能需要 build:prod)。Agent 的职责是扫描目录、读取相关文件、推断项目实际使用的命令——然后将这些推断展示给用户确认。
步骤 0:优先使用配置覆盖
检查目标目录中的 .cortex.yaml:
build_command: make release
deploy_command: docker compose up -d --build
若两个字段均存在,直接使用,跳过步骤 1–4(也无需确认)。若只有一个字段,对另一个运行推断,并仍进行步骤 4 的确认。
步骤 0.5:优先使用推断缓存
在步骤 0(覆盖)之后、步骤 1(完整扫描)之前,检查目标目录中的 .cortex/redeploy-local.yaml。若有效,复用缓存推断,直接跳到步骤 4(展示推断以供确认——用户仍需确认报告,标注 (from cache, scanned YYYY-MM-DD; <N> signal files unchanged))。若不存在、格式错误或已过期,回落到步骤 1——绝不自动删除过期缓存文件;下次成功运行会覆盖它。
.cortex.yaml 覆盖(步骤 0)优先于缓存。若步骤 0 设置了其中一个命令,该命令来自 .cortex.yaml,缓存仅供另一个字段使用(若其验证仍通过)。
绝不提交 .cortex/redeploy-local.yaml——它编码了宿主机本地的绝对路径和 mtime;请将其(或整个 .cortex/ 目录)加入 .gitignore。该文件在首次成功运行后可重新生成。
缓存文件 schema(.cortex/redeploy-local.yaml):
skill_version: 3.2.0
project_path: /Users/alice/work/api-service
written_at: 2026-05-20T14:32:11Z
build:
command: pnpm run build
evidence:
- file: package.json
ref: scripts.build
- file: Dockerfile
ref: "COPY dist/ (cross-ref)"
deploy:
command: docker compose up -d --build
evidence:
- file: docker-compose.yml
ref: "services: api, worker, db"
signal_files:
- path: package.json
mtime: 2026-05-20T11:02:44Z
- path: pnpm-lock.yaml
mtime: 2026-05-18T09:14:02Z
- path: Dockerfile
mtime: 2026-05-19T16:55:31Z
- path: docker-compose.yml
mtime: 2026-05-20T10:48:09Z
evidence 仅记录 file + ref(如 scripts.build)——命令体本身不重复,保持缓存小而不漂移。signal_files 记录推断期间读取过的每个文件(包括交叉引用),不只是所选命令来源的文件。
验证伪逻辑——按顺序检查,首次失败即视为缓存未命中:
- 文件存在且可解析为 YAML;顶级必填键存在(
skill_version、project_path、written_at、build、deploy、signal_files)。
skill_version 字符串等于当前技能 frontmatter 中的 version 值。
project_path 等于解析后的绝对目标目录(通过 realpath 解析符号链接)。
now() - written_at < 30 天。
signal_files 中每条:路径仍存在,且当前 mtime 等于记录的 mtime。
build.command 和 deploy.command 为非空字符串。
全部通过 → 缓存命中(跳到步骤 4 并加注释)。任一失败 → 缓存未命中;记录 cache invalid: <reason>; falling back to full scan 并继续步骤 1。
步骤 1:列举信号文件
遍历目标目录(深度 1,加 deploy/、.github/workflows/、docs/),收集以下文件的存在情况:
- 构建编排:
Makefile、Taskfile.yml、justfile、package.json、scripts/build*
- 容器:
Dockerfile、docker-compose.yml、compose.yaml、compose.*.yaml
- 语言 manifest:
go.mod、Cargo.toml、pom.xml、build.gradle*、*.csproj、*.sln、pyproject.toml、setup.py
- 本地部署:
ecosystem.config.{js,cjs,json}、supervisord.conf、supervisor/*.conf、deploy/*.service、Procfile
- 通常编码了命令的文档:
README.md、CONTRIBUTING.md、docs/development*.md、docs/build*.md
- 作为权威参考的 CI:
.github/workflows/*.yml、.gitlab-ci.yml、Jenkinsfile——这些通常固定了团队认可的构建命令
步骤 2:读取并推断构建命令
对每个找到的信号,读取其内容(不假设默认值):
Makefile:枚举目标(grep -E '^[a-zA-Z_-]+:' Makefile);查找 build、release、compile、dist、all。读取候选目标的主体以确认它确实执行构建(而非只是 echo)。若存在多个合理目标,列出并询问用户选哪个。
package.json:读取 scripts 对象。查找 build、build:prod、compile、bundle。若 Dockerfile 复制了 dist/,优先使用产出 dist/ 的脚本。通过 lockfile 检测包管理器(pnpm-lock.yaml → pnpm;yarn.lock → yarn;package-lock.json → npm)。
Taskfile.yml / justfile:与 Makefile 相同方式枚举任务/recipe。
Dockerfile:检查 COPY、RUN、CMD 行,理解镜像期望什么产物以及容器内发生了哪些构建。用作交叉引用(如 COPY dist/ 意味着宿主机构建必须产出 dist/)——Dockerfile 本身几乎不是宿主机构建命令。
- CI workflow:搜索构建类 job/step;权威命令会逐字出现。用作交叉引用以验证其他信号。
README.md / docs/:扫描"Build"/"Development"/"Getting Started"节;查找包含 shell 命令的代码块。
- 仅有语言 manifest(无 Makefile,无 scripts):只有在此情况下才回退到语言的惯例命令,且仅在扫描 README/CI 后确认没有项目特定覆盖时使用。示例(仅作最后兜底默认值):Go →
go build ./...;Rust → cargo build --release;Python → pip install -e .;Java/Maven → mvn package;Java/Gradle → ./gradlew build;.NET → dotnet build。
证据优先级(从高到低):
- 有明确构建语义的
Makefile / Taskfile / justfile 目标
package.json script(Node 项目)
- CI workflow 中有文档记录的构建步骤
- README 的"Build"节代码块
- 语言 manifest 兜底(
go build、cargo build 等)——仅在上述均不存在时使用
冲突解决:若 Makefile 说 make build 而 CI 说 make release,将两者及其来源展示给用户,询问运行哪个。绝不默默选择。
步骤 3:读取并推断部署命令
原则相同——读取部署相关文件,不假设:
docker-compose.yml:列出定义的服务;标准命令是 docker compose up -d --build。若 Makefile 有包装 Compose 的 deploy/up/run 目标,优先使用 Makefile 目标——它包含项目特定标志(profiles、env files)。
ecosystem.config.{js,cjs}:读取文件,提取 apps[].name。若 exec_mode: cluster,优先 pm2 reload <name>(零停机);否则 pm2 restart <name>。
supervisord.conf:枚举 [program:<name>] 节。若有多个 program,列出并询问重启哪个(或用户确认 supervisorctl restart all)。
deploy/*.service:从文件名推导 unit 名称。检查文件所有权与当前 uid,判断是否需要 sudo。
- 含
deploy/restart/up 目标的 Makefile:这些目标通常编码了项目真实的重启流程(env vars、pre-hooks)。优先于原始 docker compose / systemctl。
- 仅 Compose 项目(无其他构建编排):构建步骤被
docker compose up -d --build 吸收——不单独运行构建,将构建步骤标记为"skipped — subsumed by deploy"。
证据优先级(从高到低):
Makefile 的 deploy/restart/up 目标(项目特定包装器)
- Compose / pm2 / supervisord / systemd 配置文件(部署介质本身)
- README 的"Deploy"/"Run"节代码块
步骤 4:展示推断以供确认
在执行任何操作前,向用户展示结构化推断报告:
Detected build:
Source: Makefile target `build` (line 12, calls `go build -ldflags ...`)
Cross-ref: README "Building" section confirms `make build`
Command: make build
Detected deploy:
Source: docker-compose.yml (services: api, worker, db)
Cross-ref: Makefile `up` target wraps it with --env-file
Command: make up ← Makefile wrapper preferred over raw compose
仅在用户确认后继续执行。两个命令均来自 .cortex.yaml 时跳过确认。
行为(Behavior)
工作流程(Checklist)
-
确认目标目录
- 默认:CWD
- 若用户提供了路径:验证其存在(
test -d <path>)
- 目录不存在时以清晰错误中止
-
读取配置覆盖(若 .cortex.yaml 存在)
- 解析
build_command 和/或 deploy_command
- 记录哪些字段被覆盖;跳过被覆盖字段的启发式检测
-
检查推断缓存(检测方式步骤 0.5)
- 若存在,读取
.cortex/redeploy-local.yaml
- 按 6 步伪逻辑验证
- 缓存命中:跳过步骤 4–5,以标注了
(from cache, scanned YYYY-MM-DD; <N> signal files unchanged) 的报告进入步骤 6
- 缓存未命中 / 格式错误 / 过期:继续步骤 4(不删除文件)
.cortex.yaml(步骤 2)覆盖的字段从缓存复用中剔除;缓存仅供剩余字段使用(若验证仍通过)
-
推断构建命令(若未被覆盖且未缓存)
- 执行检测方式步骤 1–2:列举信号,读取文件,交叉引用
- 记录证据来源和选定命令
- 若为仅 Compose 项目(无其他构建编排):标记"build skipped — subsumed by deploy"
- 若无证据:停止并询问用户
build_command 或让其填写 .cortex.yaml
- 若证据冲突:将选项展示给用户,不默默选择
-
推断部署命令(若未被覆盖且未缓存)
- 执行检测方式步骤 3:读取部署配置文件,优先 Makefile 包装器
- 记录来源和选定命令(含提取的服务/unit 名称)
- 若无证据:停止并询问用户
-
展示推断并确认
- 展示结构化推断报告(按检测方式步骤 4);若使用缓存则加注释
- 等待用户确认
- 仅当两个命令均来自
.cortex.yaml 时跳过确认
- 若本次对话中已对相同目录 + 命令确认过,跳过重复确认
-
执行构建(若未跳过)
- 从目标目录运行构建命令
- 实时流式输出(不静默缓冲)
- 用
{ start=$(date +%s); <cmd>; echo $(($(date +%s)-start))s; } 记录耗时
- 退出码 ≠ 0 时:显示最后 20 行,上报失败,停止——不运行部署
-
执行部署重启
- 运行重启命令
- 同样方式记录耗时
- 退出码 ≠ 0 时:显示最后 20 行,上报部分状态,停止
-
健康检查
- Docker Compose:
docker compose ps ——确认所有容器显示 Up
- systemd:
systemctl is-active <unit>
- pm2:
pm2 list | grep <name>
- supervisord:
supervisorctl status <program>
- 记录结果;若健康检查命令不可用,警告(但不将技能运行标记为失败)
-
输出运行报告
Step Command Exit Duration
─────── ────────────────────────────── ──── ────────
Build pnpm run build 0 18.2s
Deploy docker compose up -d --build 0 6.3s
Health docker compose ps 0 0.2s
-
成功后写入缓存
- 仅当构建退出码 0(或因吸收而跳过)、部署退出码 0、且健康检查通过时写入
- 若两个命令均来自
.cortex.yaml,跳过写入(缓存无附加价值)
- 部分成功(部署 0 但健康不健康)时跳过写入——不缓存已知有问题的配置
- 若
.cortex/ 不存在,创建(mode 0755),然后写入 .cortex/redeploy-local.yaml,带 # Auto-generated by redeploy-local skill; do not edit by hand 头部
- 记录当前
skill_version、解析后的绝对 project_path、ISO 8601 UTC written_at、带证据的选定命令,以及推断期间读取过的每个信号文件及其当前 mtime
- 写入失败(权限拒绝、磁盘满、并发写)时:记录
cache write skipped: <reason> 并继续——部署已成功;缓存仅是优化层
交互策略
- 仅在检测有歧义或失败时询问
.cortex.yaml 提供两个命令时不询问
- 一次确认提示涵盖构建和部署;同一次运行中不重复提示
- 若本次对话中相同目录和命令已确认,跳过重新确认
输入与输出(Input & Output)
输入要求
- 目标目录(显式路径或 CWD)
- 可选:含
build_command 和/或 deploy_command 的 .cortex.yaml
输出契约
提供:
- 推断报告,列出每个选定命令及其证据来源(文件 + 节/行 + 交叉引用)
- 构建输出实时流(或 Compose-only 项目的"skipped"提示)
- 部署输出实时流
- 健康检查结果
- 运行报告表格(每步的命令 / 退出码 / 耗时)
- 完全成功运行后(构建 + 部署 + 健康检查全部通过),推断缓存写入
.cortex/redeploy-local.yaml
约束(Restrictions)
硬边界(Hard Boundaries)
- 绝不在未有显式用户配置的情况下运行
rm -rf 或破坏性清理命令
- 绝不假设 systemd、pm2 或 supervisord 的服务名——从配置文件提取或询问
- 绝不在步骤失败后继续——上报并停止
- 绝不在未有前置成功构建(退出码 0)的情况下运行部署重启,仅 Compose-only 项目(部署吸收构建)除外
- 绝不注入或修改目标部署的环境变量
- 绝不在无证据支撑时添加
sudo(如 systemd unit 文件为 root 所有而当前 uid 不同);运行前询问用户确认提权
失败模式
| 失败情况 | 行为 |
|---|
| 目录未找到 | 立即中止;显示检查的确切路径 |
| 无构建证据 | 在构建前停止;询问用户 build_command 或让其填写 .cortex.yaml |
| 无部署证据 | 在部署前停止;询问用户 deploy_command 或让其填写 .cortex.yaml |
| 证据冲突(如 Makefile 与 CI 不一致) | 停止;将两个选项及其来源展示给用户;让用户选择 |
| 名称/unit 提取失败 | 停止;询问用户明确提供名称 |
| 构建退出码 ≠ 0 | 显示最后 20 行;停止;不运行部署 |
| 部署退出码 ≠ 0 | 显示最后 20 行;停止;上报部分状态 |
| 健康检查失败 | 警告;不将技能运行标记为失败;不写入缓存 |
| 缓存文件格式错误或缺少必填键 | 视为缓存未命中;回落到完整扫描;不删除;成功运行后覆盖 |
| 记录的信号文件被删除 / mtime 变更 | 缓存未命中;重新扫描 |
缓存 skill_version 与当前不同 | 缓存未命中;重新扫描 |
| 缓存写入失败(权限 / 磁盘满) | 记录警告;不将技能运行标记为失败——部署已成功 |
自检清单(Self-Check)
核心成功标准
过程质量检查
示例(Examples)
示例 1:Node.js 应用 + Docker Compose
目录内容:package.json、pnpm-lock.yaml、Dockerfile、docker-compose.yml、README.md
推断过程:
- 读取
package.json scripts:找到 build、build:prod、test、lint
- 读取
Dockerfile:COPY dist/ /app/——镜像期望 dist/ 存在
- 读取
package.json scripts.build:tsc && vite build --outDir dist——产出 dist/,匹配
scripts.build:prod 是 NODE_ENV=production npm run build——也可用,但 build 是 README 中引用的默认值
- 检测包管理器:
pnpm-lock.yaml → pnpm
向用户展示的推断报告:
Detected build:
Source: package.json scripts.build (tsc && vite build --outDir dist)
Cross-ref: Dockerfile copies dist/, matches output path
Command: pnpm run build
Detected deploy:
Source: docker-compose.yml (3 services: api, worker, db)
Command: docker compose up -d --build
用户确认后,运行报告:
Step Command Exit Duration
─────── ────────────────────────────── ──── ────────
Build pnpm run build 0 18.2s
Deploy docker compose up -d --build 0 6.3s
Health docker compose ps 0 0.2s
示例 2:Go 服务 + Makefile 包装器
目录内容:go.mod、Makefile、deploy/myapp.service、.github/workflows/ci.yml
推断过程:
- 读取
Makefile 目标:build、test、lint、release、install
- 读取
Makefile 中 build 目标的主体:go build -ldflags "-X main.Version=$(VERSION)" -o bin/myapp ./cmd/myapp——项目特定 ldflags 和输出路径;不默认使用 go build ./...
- 交叉引用
.github/workflows/ci.yml:构建步骤运行 make build——确认为权威
- 读取
deploy/myapp.service 文件名 → unit myapp;检查文件所有者(root)vs 当前 uid → 可能需要 sudo systemctl restart myapp
推断报告:
Detected build:
Source: Makefile target `build` (line 8)
Cross-ref: .github/workflows/ci.yml uses `make build`
Command: make build
Detected deploy:
Source: deploy/myapp.service (unit name from filename)
Note: unit file owned by root → sudo required
Command: sudo systemctl restart myapp
示例 3:仅 Compose 项目(跳过构建步骤)
目录内容:docker-compose.yml、Dockerfile(根目录无 Makefile、package.json 或语言 manifest)
推断过程:
- Docker 上下文之外未找到构建编排
Dockerfile 在 docker compose up --build 期间执行构建
- 因此:跳过独立构建;部署命令吸收构建
运行报告:
Step Command Exit Duration
─────── ────────────────────────────── ──── ────────
Build (skipped — subsumed by deploy) — —
Deploy docker compose up -d --build 0 9.1s
Health docker compose ps 0 0.2s
示例 4:通过 .cortex.yaml 配置覆盖
.cortex.yaml:
build_command: make release GOARCH=arm64
deploy_command: supervisorctl restart api-worker
检测:两个命令均从 .cortex.yaml 读取——不应用启发式规则,不显示确认提示。
运行报告:
Step Command Exit Duration
─────── ─────────────────────────────── ──── ────────
Build make release GOARCH=arm64 0 22.7s
Deploy supervisorctl restart api-worker 0 0.8s
Health supervisorctl status api-worker 0 0.1s
示例 5:构建失败(边缘情况)
场景:pnpm run build 以退出码 1 退出
[build] FAILED — exit 1 after 4.2s
Last 20 lines of output:
...
Error: cannot find module 'express'
Deployment step skipped.
Suggested fix: run `pnpm install` to restore dependencies, then retry.
示例 6:之前部署过的项目缓存命中
目录内容:与示例 1 相同(package.json、pnpm-lock.yaml、Dockerfile、docker-compose.yml、README.md),加上之前成功运行后写入的 .cortex/redeploy-local.yaml。
检测过程:
- 步骤 0:无
.cortex.yaml 覆盖
- 步骤 0.5:读取
.cortex/redeploy-local.yaml;验证通过(相同技能版本、相同 project_path、2 天前、4 个 signal_files 的 mtime 均未变更)
- 跳过步骤 1–3(完整扫描);直接进入步骤 4 并加缓存注释
向用户展示的推断报告:
Detected build:
Source: .cortex/redeploy-local.yaml (cached 2026-05-20; 4 signal files unchanged)
Command: pnpm run build
Detected deploy:
Source: .cortex/redeploy-local.yaml (cached 2026-05-20; 4 signal files unchanged)
Command: docker compose up -d --build
用户确认后,运行报告(与示例 1 命令相同,无扫描开销):
Step Command Exit Duration
─────── ────────────────────────────── ──── ────────
Build pnpm run build 0 17.8s
Deploy docker compose up -d --build 0 6.1s
Health docker compose ps 0 0.2s
缓存文件在成功后以刷新的 written_at 和当前信号文件 mtime 重新写入。