Skip to content

Commit 871a247

Browse files
roodboiclaude
andcommitted
docs: document partial adoption (backing-services-only) as a valid hack setup
A real agent-driven onboarding hit a polyglot monorepo where heavy native toolchains (.NET) and existing host workflows made full containerization the wrong call, but nothing told the agent that running only backing services under hack — with app dev servers on the host pointed at routed services — was a supported, deliberate end state rather than a fallback to fix later. - docs/guides/agent-first-setup.md: add a "Partial adoption" section covering when to choose it, what hack still provides (stable hostnames/TLS, branch instances, committed env, lifecycle hooks), how to wire it, and tradeoffs vs full containerization. - src/agents/onboarding-prompt.ts (Phase 2): add a bullet presenting full containerization vs backing-services-only as an explicit decision, plus a bullet to prefer reusing existing prod Dockerfiles/compose contexts over authoring new dev-mode services from scratch. - src/agents/onboarding-prompt.ts (Phase 1): extend the env-inventory bullet so agents also harvest hack env candidates from compose `environment:` blocks, Dockerfile `ENV` lines, and CI config when a repo has no `.env*` files. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
1 parent e3c6da0 commit 871a247

2 files changed

Lines changed: 50 additions & 1 deletion

File tree

docs/guides/agent-first-setup.md

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,53 @@ never go stale on substance.
6464
5. Verification loop — `hack up --json``hack ps --json``hack open --json`
6565
→ curl or `hack logs`, iterating until `hack doctor` is clean.
6666

67+
## Partial adoption (backing services only)
68+
69+
Full containerization (every process in compose) is the default recommendation, but
70+
it is not the only supported shape. hack works fine running only the backing
71+
services — postgres, temporal, redis, and similar — while app dev servers (`bun
72+
dev`, `dotnet watch`, `vite`) stay on the host.
73+
74+
**When to choose it:**
75+
- Heavy native toolchains (.NET, large native builds) develop faster on the host
76+
than in a container.
77+
- The hot-path dev server (the one you restart constantly) benefits from host-native
78+
file watching, debuggers, or hot reload that containers make slower or flakier.
79+
- The team already has a working host-based dev workflow and containerizing it is
80+
not worth the churn.
81+
82+
**What hack still gives you in this shape:**
83+
- Stable hostnames and TLS for the backing services via Caddy (`postgres.<project>.hack`,
84+
`temporal.<project>.hack`, ...), so host processes and containers address them the
85+
same way.
86+
- Branch instances for the containerized services (`--branch <name>`), even though
87+
the host-run app processes are not branch-isolated on their own.
88+
- Committed, hack-managed env (`hack env add`) for connection strings and secrets,
89+
instead of hand-maintained `.env` files.
90+
- Lifecycle hooks (`startup`/`lifecycle` in `.hack/hack.config.json`) for host-side
91+
setup — tunnels, SSO bootstrap — that would otherwise be ad-hoc terminal steps.
92+
93+
**How to wire it:**
94+
- Define only the backing services in `.hack/docker-compose.yml`; add Caddy labels
95+
where a stable hostname is useful (databases usually don't need one — connect by
96+
container port — but admin UIs, queues, or shared services often do).
97+
- Give host dev servers their connection info via `hack host exec --scope <svc> --
98+
<cmd>` (injects the resolved env without touching `.env` files) or `hack env list`
99+
for a one-off lookup.
100+
- App URLs can stay on plain `localhost:<port>` for the fast path, or get promoted
101+
to a routed compose service later if you want a stable `*.hack` hostname for them
102+
too — the two are not mutually exclusive and can be migrated incrementally.
103+
104+
**Tradeoffs vs full containerization:**
105+
- No single `hack up` brings up the whole stack for a newcomer — they still need to
106+
start the host dev servers themselves (document that step).
107+
- Host-run app processes are not branch-isolated by hack; running two branches side
108+
by side means varying ports/env per worktree yourself.
109+
110+
Partial adoption is a valid end state, not an incomplete migration — do not treat it
111+
as something to "finish" into full containerization unless the tradeoffs above
112+
actually bite.
113+
67114
## Copy-paste bootstrap
68115

69116
Paste this into a fresh Claude Code / Codex session started at the repo root:

src/agents/onboarding-prompt.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ function renderInventoryPhase(): string[] {
108108
"- Read the root package.json, workspace globs, and lockfiles to identify the package manager and monorepo layout.",
109109
"- Identify runnable services (web, api, workers): dev/start scripts, framework configs, and the ports they listen on.",
110110
"- Detect databases, caches, and queues from code and config: ORM schemas (prisma/drizzle), migration dirs, existing Dockerfiles and compose files.",
111-
"- List every `.env*` file. Their keys and values are candidates for `hack env add`; treat `.env.example` values as placeholders (ask the user for real values or leave them unset).",
111+
"- List every `.env*` file. Their keys and values are candidates for `hack env add`; treat `.env.example` values as placeholders (ask the user for real values or leave them unset). Not every repo has `.env*` files — also harvest candidate keys from `environment:` blocks in existing compose files, `ENV` lines in Dockerfiles, and CI config (workflow env/secrets).",
112112
"- Note repo scripts that need env vars to run (migrations, seeds, codegen) — they will run via `hack host exec` or an ops container later.",
113113
"- Read README/docs for one-time setup steps you might otherwise miss.",
114114
];
@@ -128,6 +128,8 @@ function renderSetupPhase(opts: {
128128
"## Phase 2 — Set up hack",
129129
"",
130130
bootstrap,
131+
"- Decide full containerization vs backing-services-only (partial adoption): if the inventory shows heavy native toolchains (.NET, large native builds) or the human prefers host dev servers, compose backing services (db/queue/cache) only and keep app dev servers on the host pointed at the routed services — ask the human when it's ambiguous; partial adoption is a valid end state, not a fallback to fix later.",
132+
"- Check for reuse before authoring new services: if the repo already containerizes for prod (existing Dockerfiles/compose with build contexts, runtime-config injection points like an nginx-served runtime-config.js), prefer reusing those images/contexts with minimal glue over hand-authoring new dev-mode services from scratch.",
131133
"- Define one compose service per runnable process in `.hack/docker-compose.yml`. HTTP services need the Caddy labels (`caddy`, `caddy.reverse_proxy`, `caddy.tls=internal`) and the `hack-dev` network to be routable.",
132134
`- Design hostnames: the primary app answers on dev_host (${devHostExample}); every other routable service gets a subdomain (\`api.${devHostExample}\`, \`grafana.${devHostExample}\`, ...). Set dev_host in \`.hack/hack.config.json\`.`,
133135
"- Migrate env values: for each key found during inventory run `hack env add <KEY> <value>` — add `--secret` for anything sensitive (API keys, tokens, passwords, connection strings with credentials). Never commit plaintext secrets to the repo.",

0 commit comments

Comments
 (0)