skills/process-compose-ops/SKILL.md
Process Compose orchestration for non-containerized local services. Use for: process-compose.yaml schema, replacing PM2/supervisord/Foreman, health checks (readiness_probe, liveness_probe), restart policies (always/exit_on_failure/no), process dependencies (depends_on conditions), TUI navigation and shortcuts (F4 maximize, Tab panes, r/s/t process control), REST API and MCP server integration, headless mode (-t=false for daemons), per-process and consolidated logging (log_location), cron and interval scheduling (availability.schedule), namespace grouping for multi-stack composition, environment variable handling (env files, secrets), Windows Task Scheduler boot persistence, supply-chain verified single-binary install, multi-replica processes, foreground/serial execution patterns, dry-run validation, project update (hot reload without restart), process restart/stop/start via CLI or TUI, log tailing and follow modes, shutdown timeouts and signals, agent-friendly MCP tools for process control.
npx skillsauth add 0xDarkMatter/claude-mods process-compose-opsInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Process Compose is a Go-based supervisor for non-containerized services. Single binary, YAML config, built-in TUI, REST API, MCP server, and proper Windows support. Replacement for PM2/supervisord/Foreman in the local-dev role.
Why not PM2: PM2 5.x has 15+ known CVEs (axios/lodash/tar/minimist transitive npm exposure). PC compiles all deps in at build time with go.sum hashes — structurally resistant to TanStack-style npm worm attacks.
Why not Docker Compose: Container overhead is unnecessary for local Python/Node/Go dev servers running directly. PC gives you health checks, dependencies, and restart policies without the container layer.
# Pin a specific version, verify SHA-256 against upstream checksums
VER="v1.110.0"
BASE="https://github.com/F1bonacc1/process-compose/releases/download/$VER"
curl -fsSL -o pc.zip "$BASE/process-compose_windows_amd64.zip"
curl -fsSL -o checksums.txt "$BASE/process-compose_checksums.txt"
EXPECTED=$(grep "process-compose_windows_amd64.zip" checksums.txt | awk '{print $1}')
ACTUAL=$(sha256sum pc.zip | awk '{print $1}')
[ "$EXPECTED" = "$ACTUAL" ] || { echo "HASH MISMATCH"; exit 1; }
unzip pc.zip
# Commit process-compose.exe to your repo's bin/ directory
Record the binary's hash in your repo's SUPPLY-CHAIN.md for re-verification on next upgrade.
version: "0.5"
log_level: info
log_length: 1000
processes:
my-service:
command: "pythonw -m uvicorn main:app --host 127.0.0.1 --port 8000"
working_dir: "X:/path/to/repo"
environment:
- "DJANGO_SETTINGS_MODULE=myapp.settings"
- "PYTHONUNBUFFERED=1"
readiness_probe:
http_get:
host: localhost
port: 8000
path: /
initial_delay_seconds: 5
period_seconds: 10
timeout_seconds: 3
failure_threshold: 3
availability:
restart: always # always | exit_on_failure | on_failure | no
backoff_seconds: 5
max_restarts: 20
depends_on:
database:
condition: process_healthy # process_started | process_healthy | process_completed
shutdown:
signal: 15 # SIGTERM
timeout_seconds: 30
log_location: "logs/my-service.log"
scheduled-job:
command: "python backup.py"
schedule: "0 2 * * *" # 2am daily cron
availability:
restart: exit_on_failure
| Policy | Restarts on... |
|---|---|
| always | Any exit (success or failure) — best for long-running daemons |
| on_failure | Non-zero exit codes only |
| exit_on_failure | Stops PC entirely if this process fails — use for critical deps |
| no | Never restart |
| Condition | Wait until... |
|---|---|
| process_started | Dependency spawned (PID exists). Fastest, weakest guarantee. |
| process_healthy | Dependency's readiness_probe passes. Strong guarantee. |
| process_completed | Dependency exited successfully (for init/setup processes). |
# Lifecycle
process-compose up -f config.yaml # Start (foreground TUI by default)
process-compose up -f config.yaml -t=false # Headless (no TUI)
process-compose up -f config.yaml --dry-run # Validate config without starting
process-compose down # Stop all processes + project
# Inspection (against running PC)
process-compose -p 8888 process list # all processes + status
process-compose -p 8888 process logs <name> --follow
process-compose -p 8888 attach # TUI for running project
# Process control
process-compose -p 8888 process restart <name>
process-compose -p 8888 process stop <name>
process-compose -p 8888 process start <name>
# Reload config without stopping (hot update)
process-compose -p 8888 project update -f config.yaml
# Standalone inspection (no running PC)
process-compose info # config home info
process-compose graph -f config.yaml # dependency graph
process-compose analyze -f config.yaml # startup timing analysis
Key flag gotcha: there's no --detached flag. To run in background:
process-compose up -t=false & (shell backgrounding)Start-Process with -WindowStyle HiddenLaunch: process-compose attach (or up without -t=false).
| Key | Action |
|---|---|
| ↑ ↓ or j k | Navigate process list |
| Tab | Switch focus between process list and log pane |
| F4 | Maximize current pane (toggle) |
| F5 | Unfollow logs (lets you scroll history) |
| F6 | Unwrap log lines |
| r | Restart selected process |
| s | Stop selected process |
| t | Start selected process |
| / | Filter process list |
| ? | Help overlay |
| q | Quit TUI (PC keeps running in background) |
PC ships a built-in MCP server exposing processes as tools for AI agents. Enable via the config or CLI flag. With the MCP server on, a Claude Code agent can directly:
This replaces shell-based glue scripts (the old PM2-broker pattern).
Default API port is 8080. Common collisions:
| Port 8080 user | Workaround |
|---|---|
| Dagu dashboard | Use -p 8888 until Dagu decommissioned |
| Tomcat / Spring Boot dev | Use -p 8888 |
| Other dev tool defaults | Pick anything free in 8000–9999 range |
If you change the API port, every subsequent CLI call needs -p <port>:
process-compose -p 8888 process list
process-compose -p 8888 process logs axiom --follow
Task Scheduler runs with minimal PATH. Use a wrapper script that sets PATH explicitly before launching PC.
# scripts/boot-start.ps1
$root = "X:\00_Orchestration\compose-portless"
$pcExe = "$root\bin\process-compose.exe"
# Explicit PATH for managed services (Python, uv, Git tools, cloudflared, etc.)
$env:PATH = (@(
"$root\bin"
"C:\Program Files\Git\usr\bin" # openssl, bash
"C:\Users\<user>\AppData\Local\Programs\Python\Python313\Scripts"
"$env:PATH"
) -join ';')
# Optional: source secrets from gitignored .env
$envFile = "$root\.env"
if (Test-Path $envFile) {
Get-Content $envFile | ForEach-Object {
if ($_ -match '^\s*([A-Z_]+)\s*=\s*(.+?)\s*$') {
[Environment]::SetEnvironmentVariable($matches[1], $matches[2], 'Process')
}
}
}
# Launch headless
& $pcExe -p 8888 -t=false -L "$root\logs\process-compose.log" up -f "$root\process-compose.yaml"
Register as a Task Scheduler entry with LogonType S4U (runs at boot, no password, no interactive logon needed):
$principal = New-ScheduledTaskPrincipal -UserId $env:USERNAME -LogonType S4U -RunLevel Highest
$action = New-ScheduledTaskAction -Execute "powershell.exe" `
-Argument "-NoProfile -ExecutionPolicy Bypass -WindowStyle Hidden -File `"$root\scripts\boot-start.ps1`""
$trigger = New-ScheduledTaskTrigger -AtStartup
Register-ScheduledTask -TaskName "ProcessCompose-Boot" `
-Action $action -Trigger $trigger -Principal $principal -Force
| Gotcha | Symptom | Fix |
|---|---|---|
| Windows PATH with backslashes in double-quoted YAML | yaml: found unknown escape character | Use single quotes: - 'PATH=C:\Program Files\Git\usr\bin;...' |
| command with quoted paths containing spaces | First arg eaten | Wrap whole command in single quotes, inner paths in double: '"C:/Program Files/foo.exe" arg1 arg2' |
| Forgot working_dir | Process starts in PC's cwd, can't find files | Always specify absolute working_dir |
| Health probe wrong port | Process restart-loops with Not Ready | Match readiness_probe.http_get.port to where the process actually binds |
| Secrets in YAML | Committed to git | Use environment to pass-through; set in shell env or gitignored .env |
# Validate config before applying
process-compose up --dry-run -f process-compose.yaml
# Hot-reload after editing config
process-compose -p 8888 project update -f process-compose.yaml
# Restart one service after code change
process-compose -p 8888 process restart axiom
# Watch logs of a misbehaving service
process-compose -p 8888 process logs axiom --follow
# Stop one service temporarily for debugging
process-compose -p 8888 process stop axiom
# Now run it manually with your debugger, then:
process-compose -p 8888 process start axiom
| Need | Tool | |---|---| | Local non-containerized services with health/dependencies/MCP | Process Compose | | Production node.js process supervision | PM2 (despite age) | | Container-based stack | Docker Compose | | Job queue with cron + DAGs | Dagu, Temporal, Airflow | | System service supervision | systemd (Linux), Windows Services | | One-shot Procfile run | Foreman / Overmind / Hivemind (Unix-only) |
See X:\00_Orchestration\compose-portless\ for an 11-process production stack:
process-compose.yaml — health-checked services with depends_on chainsscripts/boot-start.ps1 — PATH-aware boot wrapperdocs/MIGRATION-LOG.md — full migration from PM2 + Caddy, every gotcha documenteddocs/SUPPLY-CHAIN.md — binary verification procedureBAD: process-compose up --detached # flag does not exist
GOOD: process-compose up -t=false & # background via shell
BAD: put secrets in process-compose.yaml (commits to git)
GOOD: source from gitignored .env in boot wrapper
BAD: use API port 8080 (clashes with Dagu, Tomcat, others)
GOOD: -p 8888 (or any free port), document the choice
BAD: ignore readiness_probe and just hope services come up
GOOD: configure http_get probe on a real endpoint; depends_on uses process_healthy
BAD: upgrade PC by running an installer (npm install -g, scoop install, brew install)
GOOD: download specific version, verify SHA-256 against upstream checksums.txt, commit binary
references/schema-reference.md — full process-compose.yaml schema with field semantics, defaults, and command-quoting gotchasprobe-patterns.md — readiness probe recipes by stack (Python, Go, Node, TCP-only, daemons)dependency-patterns.md — depends_on patterns: companion daemons, DB-before-app, tunnel-after-service, one-shot inittui-shortcuts.md — TUI cheatsheet (keys, status legend, search/sort/filter)boot-persistence-windows.md — Task Scheduler setup with S4U logon, PATH-aware wrappersupply-chain-verification.md — full SHA-256 verification procedure for the binaryscripts/install-process-compose.ps1 — download + verify + extract a pinned version, writes VERIFICATION.mdverify-binary.ps1 — re-verify committed binary hash (monthly / pre-commit)boot-start.template.ps1 — PATH-aware boot wrapper (copy + adapt per machine)boot-task-install.template.ps1 — Task Scheduler entry registration (S4U logon)assets/python-uvicorn.yaml — uvicorn/FastAPI/Django basic service templatedjango-with-companions.yaml — Django + queue daemon + audit watcher chaingo-binary-service.yaml — Go binary with HTTP or TCP probetunnel-with-dependency.yaml — Cloudflare tunnel waiting on its target servicecron-job.yaml — scheduled task patternsportless-ops — the routing layer we pair with PC (replaces Caddy)docker-ops — container alternative for the same rolemcp-ops — PC's MCP server fits this ecosystemcli-ops — general CLI tool patternstools
Behavioural-first software supply chain defense - catches poisoned npm/PyPI packages in the publish-to-advisory window that CVE tools miss. Use BEFORE every install or version bump (not only when an attack is suspected) - the 7-day cooldown gate + behavioural score catches freshly-published malware that CVE tools won't see for days. Socket.dev integration (free CLI + GitHub app + depscore MCP for Claude Code), stale-OIDC audit, dependency cooldown policy, publish-token rotation, VS Code extension audit, and a self-integrity scan that detects worm persistence hooks injected into Claude Code / VS Code settings. Triggers on: pip install, uv add, uv tool install, npm install, pnpm add, yarn add, cargo add, go get, composer require, gem install, upgrade dependency, dependency upgrade, version bump, bump version, bump package, adding dependency, new dependency, vetting a dependency, vet package, is this package safe, safe to install, should I install, before installing, pre-install check, preinstall scan, preinstall-check, PyPI cooldown, npm cooldown, release cooldown, minimumReleaseAge, score a package, package score, depscore, socket score, supply chain, supply chain attack, malicious package, poisoned dependency, npm worm, Shai-Hulud, behavioural scanning, Socket.dev, socket scan, dependency security, postinstall malware, OIDC token theft, compromised maintainer, typosquat, dependency confusion, package provenance, SLSA, persistence hook, malicious VS Code extension.
testing
GitHub remote operations — repo creation, metadata (description/homepage/topics), releases, README 'Recent Updates' enforcement, and issue / PR management with preview-before-send discipline. Companion to git-ops (local) and push-gate (pre-push safety). Three modes: new (first publish), update (subsequent release), audit (read-only checklist), plus atomic operations for issues and PRs. Triggers on: push to github, publish repo, ship release, cut release, gh release, set topics, repo description, github metadata, recent updates section, audit github repo, repo visibility, make repo public, gh repo create, gh issue, gh pr, create issue, comment on issue, close issue, triage issue, create PR, review PR, merge PR, pre-merge check, pr checks.
tools
Defend the agent's instruction surface against adversarial content - hidden-Unicode prompt injection (Trojan Source bidi reordering, U+E0000 tag-block ASCII smuggling, zero-width text), homoglyph confusables, and poisoned context that a human reviewer can't see but the model obeys. Scan CLAUDE.md / AGENTS.md / SKILL.md / .cursorrules and MCP tool descriptions; sanitize fetched web pages, issue/PR bodies, and dependency READMEs before they enter context. Triggers on: prompt injection, hidden unicode, invisible characters, zero-width space, bidi override, Trojan Source, ASCII smuggling, tag characters, homoglyph, confusable, unicode steganography, poisoned CLAUDE.md, malicious tool description, MCP tool poisoning, instruction injection, jailbreak in file, is this file safe, sanitize untrusted content, scan for hidden text.
tools
Set tool permissions for Claude Code. Configures allowed commands, rules, and preferences in .claude/ directory. Triggers on: setperms, init tools, configure permissions, setup project, set permissions, init claude.