App install
Lease a unique port and a unique container / Compose name, then bring up this project's copy of the local helper app (the Docker-served intake form + dashboard) so it runs concurrently with every other project's helper — zero port or name collisions. It is an operation-layer op-card: you run it directly by sending its prompt path, it drives the deterministic engine _tools/app/install.sh, validates the bring-up, and records its work as an operation_record born complete in 4_done/.
Source of truth: the registry row in _processes/_shared/request-types.md and the op-card prompt _processes/00_app/app-install.prompt.md.
The flow
You trigger app-install directly by sending its prompt path; it executes immediately (no clarify, no stage loop). It first preflights (workflow root, Docker daemon, existing .env / running container), then runs bash _tools/app/install.sh install and parses exactly one JSON object from stdout — the script leases a unique port + names, migrates .env, and runs docker compose build && up -d. The agent validates that the helper is actually serving (preferring install.sh doctor --check-health, which probes /health and corroborates the container identity with Docker), then recommends app-init if the content layer is not yet bootstrapped, and finally records the run as an operation_record job born complete in 4_done/.
What it is for
app-install stands up this project's helper container so several projects can run their helper apps at once without stepping on each other. It leases a unique port and unique container / Compose-project names from a per-user registry (under a lock), migrates .env, and runs docker compose build && up -d. It then probes /health, corroborates the container identity with Docker, and — once the container is serving — recommends running app-init to bootstrap the workflow content layer.
- Infrastructure, not content. app-install owns the Docker host layer (naming + the running container). It never writes
app.mdorconfig.json— that is app-init's content-layer job. - Runs before app-init, needs no
app.md. A missing or placeholderapp.mdis the expected state on the fresh install you are about to enable — it is never a refusal reason. - The script owns all state mutation. The agent never allocates a port, derives a name, or edits
.env/ the registry itself — it drives_tools/app/install.shand reads its JSON. The agent adds only judgment: preflight, validation, diagnosis, and the next-step recommendation. - Idempotent. Re-running reuses an existing lease (same port) rather than allocating a new one.
app.md / config.json are missing, app-install recommends _processes/00_app/app-init.prompt.md. It may offer to chain into it, but never runs it silently and never writes the content files itself.
The logic
app-install sits in the operation layer with shape op-card. It is one of the workflow's standalone / infra agents the user invokes directly — no orchestrator dispatches it and it does not run the stage pipeline. Like the other operation agents it may invoke AskUserQuestion directly (scope-tight: no orchestrator sits above it to relay through), and it authors exactly one tracked operation_record job at end-of-run so the install is recorded like every other action (D-44, D-54).
- Direct-invoked. You start it by sending the prompt path; it begins executing immediately rather than waiting to be routed.
- Records an
operation_record. At end-of-run it authorsjobs/4_done/<op-slug>/born complete — it never writes a.lockand never moves or edits another job's state, preserving the sole-4_done-mover invariant (D-44, D-54). - Infra → content boundary. It enforces the separation: bring up the container (infra), then recommend app-init (content). It never crosses into writing
app.md/config.json.
The fields
## Stages, no ## Approval gates, no ## Per-stage config, and no ## Action block. It is surfaced in the form only as a copy-the-prompt-path card — you run it by sending its path, not by filling in fields. The only JOB.md it produces is the report-only operation_record it authors for itself at end-of-run.
What the run leases and writes is owned by _tools/app/install.sh (the agent only reads its JSON result):
| Leased / written | What it is |
|---|---|
| Unique port | A free host port leased from the per-user registry (under a lock) within the port range; published by this project's container on 127.0.0.1 only. |
| Identity name | The lease/identity slug (cwapp-<dir>-<hash>) that drives the unique container name and Compose-project name — the collision-free naming that lets projects coexist. |
| Display name | The human project name shown in the form header (the host/parent project for a sub-folder install, the repo dir name standalone); leased into .env as CWAPP_DISPLAY_NAME. |
.env | Migrated by the script (port + names written / reconciled, registry-wins); the agent never edits it directly. |
| Helper app (container) | The Docker-served intake form + dashboard, brought up via docker compose build && up -d and validated against /health with a Docker identity check. |
operation_record job | The end-of-run record at jobs/4_done/<op-slug>/ — its 09_action/action-report.md captures the leased port/name, container status, /health result, and the app-init recommendation. |
How to run it
app-install is a direct-invoked op-card: copy its prompt path and send it to the agent. There is no intake to fill out — it starts executing immediately and records its own run in 4_done/.
_processes/00_app/app-install.prompt.md
_processes/...); prefix with _code_workflow/ when your cwd is the host project root. See How to use → Two invocation modes.