catalyst-stack
catalyst-stack is the canonical command for bringing the Catalyst service stack up and down. It starts the four services in dependency order and is idempotent — already-running services are left alone.
Dependency order
Section titled “Dependency order”| Start order | Stop order |
|---|---|
mitmproxy (opt-in, --proxy only) | execution-core |
| broker | monitor |
| monitor | broker |
| execution-core | mitmproxy |
Subcommands
Section titled “Subcommands”| Subcommand | Description |
|---|---|
start | Start all services (idempotent). |
stop | Stop all services in reverse order. |
restart | Stop then start. Accepts the same flags as start. |
status | Print running/stopped state for each service. |
--proxy
Section titled “--proxy”Opt-in to Linear traffic capture via mitmproxy. When passed, catalyst-stack will:
- Verify
mitmdumpis installed (offerbrew install mitmproxyif absent). - Generate the mitmproxy CA cert at
~/.mitmproxy/mitmproxy-ca-cert.pemif missing. - Copy the vendored addon to
~/catalyst/mitm_linear_addon.pyif absent. - Start mitmproxy, then set
HTTPS_PROXY/NODE_USE_ENV_PROXY/NODE_EXTRA_CA_CERTS/NO_PROXY=api.anthropic.com,...as an inline env prefix for the execution-core daemon.
Traffic is logged to ~/catalyst/linear-proxy.jsonl (one JSON record per Linear API response,
including rate-limit headers and caller attribution).
Proxy is off by default. The daemon runs correctly without it — use --proxy only for short
diagnostic windows (e.g. investigating Linear rate-limiting). The proxy vars are never written to
disk; a plain catalyst-stack restart removes them. NO_PROXY ensures Claude worker API calls
bypass the proxy even if mitmdump hiccups.
--no-proxy
Section titled “--no-proxy”Accepted for backward compatibility; no-op (proxy is already off by default).
--hotpatch
Section titled “--hotpatch”Apply a post-merge update in one command: ff-only pull each pluginDirs checkout, then start/restart.
# After merging or pulling new code:catalyst-stack restart --hotpatchBehavior:
- Resolves the checkout(s) from
pluginDirsvialib/plugin-dirs.sh(CATALYST_PLUGIN_DIRSenv → repo.catalyst/config.json→ machine config). - Uses
git pull --ff-only origin main— aborts on non-fast-forward merges or a dirty/diverged checkout (resolve manually, then retry). - Emits a
node.checkout.updatedevent recording the old → new commit. start --hotpatchrefuses if the stack is already running. Userestart --hotpatchinstead.- The deprecated marketplace-cache rsync survives only behind
catalyst-stack hotpatch --legacy-rsync(usesCATALYST_REPO_DIR).
setup-plugin-source.sh
Section titled “setup-plugin-source.sh”plugins/dev/scripts/setup-plugin-source.sh provisions the pristine, main-only checkout that --hotpatch keeps fresh and registers it as catalyst.orchestration.pluginDirs in the machine config.
plugins/dev/scripts/setup-plugin-source.sh [--path DIR] [--repo-url URL] [--force]- Clones the repo (main, single-branch) to
~/catalyst/plugin-sourceby default (--pathor$CATALYST_PLUGIN_SOURCEto override), or ff-only pulls an existing checkout. - Registers
<path>/plugins/devaspluginDirs, preserving every other machine-config key. Idempotent;--forcere-points to a new path. - Refuses a linked git worktree or a non-
maincheckout — the source must stay pristine.
parity
Section titled “parity”catalyst-stack parity reports node-freshness + setup drift for the pluginDirs checkout (exit code = number of drift findings). In addition to the freshness/dirty/manifest checks, it flags a checkout that is off main or is a linked worktree (run setup-plugin-source.sh to fix).
Non-interactive mode under --proxy: auto-approves brew install mitmproxy instead of prompting.
Environment variables
Section titled “Environment variables”| Variable | Default | Purpose |
|---|---|---|
CATALYST_REPO_DIR | ~/code-repos/github/coalesce-labs/catalyst | Repo root used by the deprecated hotpatch --legacy-rsync path. |
CATALYST_PLUGIN_SOURCE | ~/catalyst/plugin-source | Default checkout location used by setup-plugin-source.sh. |
MITM_LOG | ~/catalyst/linear-proxy.jsonl | JSONL capture path read by the mitmproxy addon (mitm_linear_addon.py) — not the process log. The mitmdump process log is fixed at ~/catalyst/mitm.log and cannot be overridden. |
Exit codes
Section titled “Exit codes”| Code | Meaning |
|---|---|
0 | Success. |
1 | Error (unknown argument, proxy preflight failed, non-ff pull, etc.). |
Examples
Section titled “Examples”# Start the stack (proxy off by default)catalyst-stack start
# Start with Linear traffic loggingcatalyst-stack start --proxy
# Check what's runningcatalyst-stack status
# Stop everythingcatalyst-stack stop
# Restart after pulling new codecatalyst-stack restart --hotpatch
# Restart with proxy enabledcatalyst-stack restart --proxySee also
Section titled “See also”- Post-reboot and updates — day-to-day workflow for booting and updating
- Install Catalyst — initial setup including
catalyst-stack startas step 4