SuperAPI AI Directory

redeploy-local

Deployment & operations

View repository

Updated 10-15 23:46

About this skill

Skill: Redeploy Local

Purpose

After the Agent modifies code, execute the project's build and restart the locally deployed environment—without the user needing to know the project's tech stack. Suitable for projects deployed locally via Docker Compose, systemd unit, or a process manager (pm2, supervisorctl). Hot-reload development servers are intentionally excluded; the target is a running local environment, not development watch mode.


Core Objective

Primary objective: Given a directory, successfully perform one build and one local deployment restart, and report what was run.

Success criteria(all must be satisfied):

  1. ✅ Directory confirmed: The target directory was verified to exist before any command execution
  2. ✅ Build command determined or configured: The command can be traced to a configuration file or detection heuristic—not invented
  3. ✅ Build succeeded: Exit code 0; build artifacts exist in the expected location
  4. ✅ Deployment method determined or configured: The deployment target was identified (Compose / systemd / pm2 / supervisord)
  5. ✅ Deployment restarted: The service/container was restarted and is reachable (health check or status check passed)
  6. ✅ Run report output: A table of command → exit code → duration for each executed step

Acceptance test: After the skill completes, the locally deployed service reflects the latest code changes, and the status check reports healthy/running.


Scope Boundaries

This skill is responsible for:

  • Detecting the build system from project files (package.json, Makefile, go.mod, Cargo.toml, pom.xml, build.gradle, *.csproj, pyproject.toml)
  • Detecting the local deployment method from project files (docker-compose.yml / compose.yaml, systemd unit, pm2 ecosystem file, supervisord.conf)
  • Reading project-level configuration overrides (.cortex.yaml build_command / deploy_command)
  • Persisting successful inferences to .cortex/redeploy-local.yaml, reused on the next run
  • Sequentially executing build + restart
  • Reporting results

This skill is not responsible for:

  • Hot-reload development servers (npm run dev, vite, next dev)—these are not a "local deployment environment"
  • Remote deployment (SSH, cloud, Kubernetes)—use a deployment skill targeting remote infrastructure
  • Database migrations—run separately before invoking this skill
  • Secret injection—environment variables / secrets must already be available in the deployment

Handoff point: The skill completes when the run report shows exit code 0 for all steps. If any step fails, the skill reports failure and stops—it does not automatically retry or fix build errors.


Use Cases

  • Rebuild after editing: The Agent has finished modifying code; the user wants the local service to reflect the changes without manually running build + restart commands
  • Multi-stack projects: The project mixes compiled languages (Go, Rust) with Docker Compose deployment; the skill automatically detects both
  • Scripted overrides: Via .cortex.yaml to achieve CI-style reproducibility—the same commands every run, with no detection variance
  • Team-shared environment: Different team members have different local configurations; skills adapt based on detected signals rather than requiring the same toolchain

Detection Approach

This skilldoes notmaintain a hardcoded "file X → command Y" mapping. Build and deploy commands vary from project to project—two Go projects may have completely different build conventions (custom ldflags, output paths, cross-compilation targets), and a Node project's build script is not necessarily what's needed for deployment (it may require build:prod). The Agent's job is toscan the directory, read the relevant files, and infer the commands the project actually uses—then present those inferences to the user for confirmation.

Step 0: Prefer configuration overrides

Check the target directory for .cortex.yaml:

build_command: make release
deploy_command: docker compose up -d --build

If both fields are present, use them directly and skip steps 1–4 (no confirmation needed either). If only one field is present, run inference for the other and still perform the step 4 confirmation.

Step 0.5: Prefer the inference cache

After step 0 (overrides) and before step 1 (full scan), check the target directory for .cortex/redeploy-local.yaml. If valid, reuse the cached inference and jump directly to step 4 (present the inference for confirmation—the user still needs to confirm the report, annotated with (from cache, scanned YYYY-MM-DD; <N> signal files unchanged)). If it does not exist, is malformed, or is expired, fall back to step 1—never automatically delete an expired cache file; the next successful run will overwrite it.

.cortex.yaml overrides (step 0) take precedence over the cache. If step 0 set one of the commands, that command comes from .cortex.yaml, and the cache is used only for the other field (if its validation still passes).

Never commit .cortex/redeploy-local.yaml—it encodes host-local absolute paths and mtimes; add it (or the entire .cortex/ directory) to .gitignore. This file can be regenerated after the first successful run.

Cache file schema(.cortex/redeploy-local.yaml):

# Auto-generated by redeploy-local skill; do not edit by hand
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 records only file + ref(such as scripts.build)—the command body itself is not duplicated, keeping the cache small and drift-free.signal_files records every file that wasreadduring inference (including cross-references), not just the files that are the source of the selected command.

Validation pseudologic—check in order; the first failure counts as a cache miss:

  1. The file exists and parses as YAML; the top-level required keys are present (skill_version、project_path、written_at、build、deploy、signal_files)。
  2. skill_version string equals the version value in the current skill's frontmatter.
  3. project_path equals the resolved absolute target directory (resolving symlinks via realpath ).
  4. now() - written_at < 30 days.
  5. signal_files For each entry in : the path still exists, and the current mtime equals the recorded mtime.
  6. build.command and deploy.command are non-empty strings.

All pass → cache hit (jump to step 4 with an annotation). Any failure → cache miss; record cache invalid: <reason>; falling back to full scan and continue to step 1.

Step 1: Enumerate signal files

Traverse the target directory (depth 1, plus deploy/、.github/workflows/、docs/), and collect the presence of the following files:

  • Build orchestration:Makefile、Taskfile.yml、justfile、package.json、scripts/build*
  • Containers:Dockerfile、docker-compose.yml、compose.yaml、compose.*.yaml
  • Language manifests:go.mod、Cargo.toml、pom.xml、build.gradle*、*.csproj、*.sln、pyproject.toml、setup.py
  • Local deployment:ecosystem.config.{js,cjs,json}、supervisord.conf、supervisor/*.conf、deploy/*.service、Procfile
  • Documentation that usually encodes commands:README.md、CONTRIBUTING.md、docs/development*.md、docs/build*.md
  • CI as the authoritative reference:.github/workflows/*.yml、.gitlab-ci.yml、Jenkinsfile—these usually pin down the team-approved build commands

Step 2: Read and infer the build command

For each signal found,read its contents(do not assume defaults):

  • Makefile: enumerate targets (grep -E '^[a-zA-Z_-]+:' Makefile); look for build、release、compile、dist、all. Read the body of candidate targets to confirm that it actually performs a build (rather than just echo). If multiple reasonable targets exist, list them and ask the user which to choose.
  • package.json: read the scripts object. Look for build、build:prod、compile、bundle. If the Dockerfile copies dist/, prefer the script that produces dist/ . Detect the package manager via the lockfile (pnpm-lock.yaml → pnpm;yarn.lock → yarn;package-lock.json → npm)。
  • Taskfile.yml / justfile: enumerate tasks/recipes in the same way as with a Makefile.
  • Dockerfile: check the COPY、RUN、CMD lines to understand what artifacts the image expects and what builds happen inside the container. Use as across-reference(e.g. COPY dist/ means the host build must produce dist/) — the Dockerfile itself is almost never the host build command.
  • CI workflow: search for build-type jobs/steps; the authoritative command will appear verbatim. Use as across-referenceto validate other signals.
  • README.md / docs/: scan the "Build"/"Development"/"Getting Started" sections; look for code blocks containing shell commands.
  • Language manifest only(no Makefile, no scripts): only in this case fall back to the language's conventional command, and only use it after scanning the README/CI and confirming there is no project-specific override. Examples (as a last-resort default only): Go → go build ./...;Rust → cargo build --release;Python → pip install -e .;Java/Maven → mvn package;Java/Gradle → ./gradlew build;.NET → dotnet build。

Evidence priority(high to low):

  1. with explicit build semantics, the Makefile / Taskfile / justfile target
  2. package.json script (Node projects)
  3. build steps documented in the CI workflow
  4. code block in the README's "Build" section
  5. language manifest fallback (go build、cargo build etc.) — use only when none of the above exist

Conflict resolution: if the Makefile says make build while CI says make release, show both and their sources to the user and ask which to run. Never choose silently.

Step 3: Read and infer the deploy command

Same principle — read deployment-related files, do not assume:

  • docker-compose.yml: list the defined services; the standard command is docker compose up -d --build. If the Makefile has a deploy/up/run target that wraps Compose, prefer the Makefile target — it includes project-specific flags (profiles, env files).
  • ecosystem.config.{js,cjs}: read the file and extract apps[].name. If exec_mode: cluster, prefer pm2 reload <name>(zero downtime); otherwise pm2 restart <name>。
  • supervisord.conf: enumerate the [program:<name>] sections. If there are multiple programs, list them and ask which to restart (or the user confirms supervisorctl restart all)。
  • deploy/*.service: derive the unit name from the filename. Check file ownership and the current uid to determine whether sudo。
  • containing deploy/restart/up targets, the Makefile: these targets usually encode the project's real restart procedure (env vars, pre-hooks). Prefer over raw docker compose / systemctl。
  • Compose-only project(no other build orchestration): the build step is docker compose up -d --build subsumed— do not run the build separately; mark the build step as "skipped — subsumed by deploy".

Evidence priority(high to low):

  1. Makefile 's deploy/restart/up Goal (project-specific wrapper)
  2. Compose / pm2 / supervisord / systemd configuration files (the deployment medium itself)
  3. Code blocks in the "Deploy"/"Run" section of the README

Step 4: Present inference for confirmation

Before performing any operation, present a structured inference report to the user:

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

Continue execution only after user confirmation. Both commands come from .cortex.yaml skip confirmation when .


Behavior

Workflow (Checklist)

  1. Confirm target directory

    • Default: CWD
    • If the user provided a path: verify that it exists (test -d <path>)
    • Abort with a clear error when the directory does not exist
  2. Read configuration overrides(if .cortex.yaml exists)

    • Parse build_command and/or deploy_command
    • Record which fields are overridden; skip heuristic detection of overridden fields
  3. Check inference cache(detection method step 0.5)

    • If present, read .cortex/redeploy-local.yaml
    • Validate according to the 6-step pseudologic
    • Cache hit: skip steps 4–5, proceed to step 6 with a report annotated with (from cache, scanned YYYY-MM-DD; <N> signal files unchanged) Cache hit: skip steps 4–5, proceed to step 6 with a report annotated with
    • Cache miss / malformed / stale: continue to step 4 (do not delete the file)
    • .cortex.yamlFields overridden in (step 2) are excluded from cache reuse; the cache is used only for the remaining fields (if validation still passes)
  4. Infer build command(if not overridden and not cached)

    • Execute detection method steps 1–2: enumerate signals, read files, cross-reference
    • Record evidence sources and the selected command
    • If it is a Compose-only project (no other build orchestration): mark "build skipped — subsumed by deploy"
    • If there is no evidence: stop and ask the user build_command or have them fill in .cortex.yaml
    • If evidence conflicts: present the options to the user, do not silently choose
  5. Infer deploy command(if not overridden and not cached)

    • Execute detection method step 3: read deployment configuration files, prefer a Makefile wrapper
    • Record the source and the selected command (including the extracted service/unit name)
    • If there is no evidence: stop and ask the user
  6. Present inference and confirm

    • Present the structured inference report (according to detection method step 4); add a note if the cache is used
    • Wait for user confirmation
    • Skip confirmation only when both commands come from .cortex.yaml Skip confirmation only when both commands come from
    • If the same directory + commands have already been confirmed in this conversation, skip repeated confirmation
  7. Execute build(if not skipped)

    • Run the build command from the target directory
    • Stream output in real time (do not silently buffer)
    • Use { start=$(date +%s); <cmd>; echo $(($(date +%s)-start))s; } record elapsed time
    • When exit code ≠ 0: show the last 20 lines, report the failure, stop—do not run deployment
  8. Execute deployment restart

    • Run the restart command
    • Record elapsed time in the same way
    • When exit code ≠ 0: show the last 20 lines, report partial status, stop
  9. Health check

    • Docker Compose:docker compose ps — confirm all containers show Up
    • systemd:systemctl is-active <unit>
    • pm2:pm2 list | grep <name>
    • supervisord:supervisorctl status <program>
    • Record the result; if the health check command is unavailable, warn (but do not mark the skill run as failed)
  10. Output the run report

    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
    
  11. Write cache after success

    • Write only when the build exit code is 0 (or skipped due to absorption), the deploy exit code is 0, and the health check passes
    • If both commands come from .cortex.yaml, skip writing (the cache adds no value)
    • Skip writing on partial success (deploy 0 but unhealthy)—do not cache a known problematic configuration
    • If .cortex/ does not exist, create it (mode 0755), then write .cortex/redeploy-local.yaml, with the # Auto-generated by redeploy-local skill; do not edit by hand header
    • Record the current skill_version, the resolved absolute project_path、ISO 8601 UTC written_at, the selected command with evidence, and every signal file read during inference along with its current mtime
    • On write failure (permission denied, disk full, concurrent write): log cache write skipped: <reason> and continue—the deployment has already succeeded; the cache is only an optimization layer

Interaction policy

  • Ask only when detection is ambiguous or fails
  • .cortex.yaml Do not ask when two commands are provided
  • A single confirmation prompt covers build and deploy; do not prompt repeatedly within the same run
  • If the same directory and commands have already been confirmed in this conversation, skip re-confirmation

Input & Output

Input requirements

  • Target directory (explicit path or CWD)
  • Optional: containing build_command and/or deploy_command of .cortex.yaml

Output contract

Provide:

  • Inference report listing each selected command and its evidence source (file + section/line + cross-reference)
  • Build output live stream (or a "skipped" notice for Compose-only projects)
  • Deploy output live stream
  • Health check result
  • Run report table (command / exit code / duration for each step)
  • After a fully successful run (build + deploy + health check all pass), the inference cache writes to .cortex/redeploy-local.yaml

Restrictions

Hard Boundaries

  • Neverrun rm -rf or destructive cleanup commands without explicit user configuration
  • Neverassume the service name for systemd, pm2, or supervisord—extract it from the config file or ask
  • Nevercontinue after a step fails—report and stop
  • Neverrun a deploy restart without a preceding successful build (exit code 0), except for Compose-only projects (where deploy absorbs the build)
  • Neverinject or modify the target deployment's environment variables
  • Neveradd sudowithout evidence (e.g., the systemd unit file is owned by root while the current uid differs); ask the user to confirm privilege escalation before running

Failure modes

Failure case Behavior
Directory not found Abort immediately; show the exact path checked
No build evidence Stop before building; ask the user build_command or have them fill in .cortex.yaml
No deployment evidence Stop before deploying; ask the user deploy_command or have them fill in .cortex.yaml
Conflicting evidence (e.g., Makefile inconsistent with CI) Stop; show both options and their sources to the user; let the user choose
Name/unit extraction failed Stop; ask the user to explicitly provide the name
Build exit code ≠ 0 Show the last 20 lines; stop; do not run deployment
Deployment exit code ≠ 0 Show the last 20 lines; stop; report partial status
Health check failed Warn; do not mark the skill run as failed; do not write to cache
Cache file format error or missing required key Treat as cache miss; fall back to full scan; do not delete; overwrite after a successful run
Recorded signal file deleted / mtime changed Cache miss; rescan
Cache skill_version differs from current Cache miss; rescan
Cache write failed (permissions / disk full) Log a warning; do not mark the skill run as failed—deployment already succeeded

Self-Check Checklist

Core success criteria

  • Directory confirmed: the target directory was verified to exist before any command
  • Detection traceable: every inferred command is attributed to specific evidence (file + line/section, preferably with cross-references)—nothing fabricated
  • Avoid double build: Compose-only projects skip the build step;--build handled in the deployment command
  • User confirmed: commands were shown and confirmed before first execution (skipped only when both commands come from .cortex.yaml )
  • Build succeeded: exit code 0 was confirmed before the deployment run (or the build step was reasonably skipped)
  • Deployment succeeded: exit code 0 was confirmed before the health check
  • Health check ran: status was checked and recorded (warn if unavailable; do not fail)
  • Run report output: the table covers each step's command / exit code / duration
  • Cache respected or refreshed: read before scanning .cortex/redeploy-local.yaml; write only after a fully successful run (build + deployment + health check all passed)

Process quality checks

  • No silent buffering: build and deployment output streams in real time, without buffering
  • Durations recorded: wall-clock time was measured for each step
  • Name/unit from source: pm2/supervisord/systemd names are extracted from configuration files, not hardcoded
  • Minimal interaction: no redundant prompts; skip re-confirmation when already confirmed in this conversation

Examples

Example 1: Node.js app + Docker Compose

Directory contents:package.json、pnpm-lock.yaml、Dockerfile、docker-compose.yml、README.md

Inference process:

  • Read package.json scripts: found build、build:prod、test、lint
  • Read Dockerfile:COPY dist/ /app/—the image expects dist/ to exist
  • Read package.json scripts.build:tsc && vite build --outDir dist—produces dist/, matching
  • scripts.build:prod is NODE_ENV=production npm run build—also usable, but build is the default referenced in the README
  • Detect package manager:pnpm-lock.yaml → pnpm

Inference report shown to the user:

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

After user confirmation, run report:

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

Example 2: Go service + Makefile wrapper

Directory contents:go.mod、Makefile、deploy/myapp.service、.github/workflows/ci.yml

Inference process:

  • Read Makefile targets:build、test、lint、release、install
  • Read Makefile in build target body:go build -ldflags "-X main.Version=$(VERSION)" -o bin/myapp ./cmd/myapp—project-specific ldflags and output path; do not default to go build ./...
  • Cross-reference .github/workflows/ci.yml: the build step runs make build—confirmed as authoritative
  • Read deploy/myapp.service filename → unit myapp; check file owner (root) vs current uid → may need sudo systemctl restart myapp

Inference report:

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

Example 3: Compose-only project (skip build step)

Directory contents:docker-compose.yml、Dockerfile(no Makefile, package.json, or language manifest in the root directory)

Inference process:

  • No build orchestration found outside the Docker context
  • Dockerfile in docker compose up --build performs the build during
  • Therefore: skip the standalone build; the deploy command absorbs the build

Run report:

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

Example 4: Configuration override via .cortex.yaml

.cortex.yaml:

build_command: make release GOARCH=arm64
deploy_command: supervisorctl restart api-worker

Detection: both commands read from .cortex.yaml —no heuristics applied, no confirmation prompt shown.

Run report:

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

Example 5: Build failure (edge case)

Scenario:pnpm run build exits with exit code 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.

Example 6: Cache hit for a previously deployed project

Directory contents: same as Example 1 (package.json、pnpm-lock.yaml、Dockerfile、docker-compose.yml、README.md), plus the .cortex/redeploy-local.yaml。

Detection process:

  • Step 0: no .cortex.yaml override
  • Step 0.5: read .cortex/redeploy-local.yaml; validation passed (same skill version, same project_path, 2 days ago, all 4 signal_files mtimes unchanged)
  • Skip steps 1–3 (full scan); go directly to step 4 with a cache note

Inference report shown to the user:

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

After user confirmation, run report (same commands as Example 1, no scan overhead):

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

The cache file is rewritten after success with refreshed written_at and current signal file mtimes.