feat(init): scaffolded apps carry their own backend — init, npm start, done - #219
Merged
Conversation
A compose stack that boots BackAI from the published release images, pinned to the CLI's own version (a dev build pins :latest), plus what running it outside a checkout needs: a Go port of the port preflight (foreign conflicts move up, ports our own compose project holds stay), .env read/write seeded from .env.example, and readiness waits on the runtime and the demo agent. The two mounted files are copies of the repo's, pinned to it by a drift test. buildinfo carries the version main sets from its ldflag so init can pin images to the binary. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Signed-off-by: Abir Abbas <abirabbas1998@gmail.com>
… app When no checkout encloses the directory but it is an app written by `af-stack init <name>`, dev no longer demands a clone: it writes any missing backend files, allocates free host ports into .env, runs docker compose up -d, waits for /ready and for the supportdesk agent to register, writes AF_STACK_URL (and VITE_AF_STACK_URL for the saas template) into .env, and prints where things are. Always detached, so npm's prestart hook can run it. A runtime that never becomes ready is reported with its last status and the log command; a missing docker says what to install. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Signed-off-by: Abir Abbas <abirabbas1998@gmail.com>
…start
Both templates get docker-compose.yml + backend/ from the starter
package. The node app runs af-stack dev through a prestart hook (plus
backend / backend:stop scripts) and its starter now calls
supportdesk.echo and prints the reply; the saas app gets a predev hook.
.env.example, README, CLAUDE.md, the failure text, and the printed next
steps describe the self-contained path instead of a backend from a
clone. The node starter tests use the runtime's {"agents":[...]} shape
and an echo endpoint.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Signed-off-by: Abir Abbas <abirabbas1998@gmail.com>
…lded app The images matrix gains af-stack-supportdesk-agent (its Dockerfile needs its own directory as context). A second smoke builds the CLI at the release version, scaffolds an app, runs npm start, and refuses to publish unless the echo reply comes back. Before it, an anonymous manifest fetch asserts each image is pullable with no registry login, because GHCR packages are private by default and a scaffold from a released CLI pulls exactly that way; the runner logs out of GHCR so the smoke pulls like a user. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Signed-off-by: Abir Abbas <abirabbas1998@gmail.com>
README, the dx hub and run.md, cli-distribution, cli-admin, and the skill describe the two init forms as they now behave: the positional form scaffolds an app that boots BackAI from the release images (no clone; Docker required), the flag form brands a fork inside a clone. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Signed-off-by: Abir Abbas <abirabbas1998@gmail.com>
6 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
af-stack init my-ai-productthennpm startstill failed after #217: the scaffolded app had no backend of its own, and nothing in the docs said where one should come from. The starter only ever called a BackAI; on a machine where port 8080 belongs to something else (an AgentField control plane, in the report) it got that server's 404. The product promise is one bundled thing: init, start, done.Now the scaffold carries its backend.
af-stack init <name>writes adocker-compose.ymland abackend/directory that boot BackAI from the published release images pinned to the CLI's own version (Postgres, MinIO, LiteLLM, the AgentField control plane, the runtime, the operator dashboard, and thesupportdeskdemo agent).af-stack devruns inside that app: it allocates free host ports when the defaults are busy, runsdocker compose up -d, waits for the runtime's/readyand the demo agent's registration, and writesAF_STACK_URLinto the app's.env.npm startruns it first through aprestarthook, then the app lists the registered agents and callssupportdesk.echo. No clone is involved; Docker is the only prerequisite.Changes
starterpackage (services/cli/internal/starter): the compose stack and the two files it mounts (postgres-init.sh,litellm-config.yaml, copied from the repo and pinned to it by a drift test), the image tag mapping (released CLI → its version, dev build →latest), a Go port of the checkout's port preflight (busy foreign port moves up, a port bound by our own compose project stays,COMPOSE_PROJECT_NAMEfrom the directory),.envread/write that seeds from.env.example, and the readiness waits.af-stack devin a scaffolded app: when no checkout encloses the directory but it is an app written byinit <name>,devboots the bundled backend instead of demanding a clone. Apps scaffolded by an older CLI get the backend files written on firstdev. Always detached; it returns once the backend is ready, which is what the npm hook needs. A runtime that never becomes ready is reported with its last/readystatus and the log command.nodegetsprestart/backend/backend:stopscripts and its starter now callssupportdesk.echoand prints the reply;saasgets apredevhook andVITE_AF_STACK_URLis kept in step. READMEs,CLAUDE.md,.env.example, and the printed next steps describe the self-contained path. The starter's failure text now says to runaf-stack devhere.af-stack-supportdesk-agent, and adds a second smoke that builds the CLI at the release version, scaffolds an app, runsnpm start, and refuses to publish unless the echo reply comes back. Before that it asserts each image is pullable without a registry login, and logs out of GHCR so the smoke pulls the way a user does.run.md,cli-distribution.md,cli-admin.md, and the skill now describe the twoinitforms accurately: positionalinit <name>is a complete app with a bundled backend;init --namebrands a fork inside a clone.Verification
.envkey, every service is image-based;EnsureBackendis idempotent and never overwrites an edited compose file; port allocation moves only foreign conflicts and never hands two services the same port;.envwrites replace in place and seed from the example;WaitReady/WaitAgentagainst fake runtimes.devin a scaffolded app is driven with a stubdockeron PATH and anhttptestruntime: writes the backend, runscompose up -d, keeps the port our project holds, writesAF_STACK_URL, prints the map; the unready case, the no-docker case, and the Vite key are pinned. The node starter is run with realnodeagainst a fake runtime that serves the runtime's{"agents":[…]}shape and the echo endpoint.af-stack init my-ai-product && cd my-ai-product && npm install && npm startboots the stack (ports moved to 8082/8083/5434), printsRegistered agents: supportdeskandEcho agent replied: {"message":"hello from http://localhost:8082"}; a secondnpm startis a 2-second no-op; the dashboard answers on 33000. Run in an app scaffolded by the released 0.12.6,af-stack devwrites the backend files and boots it. Local copies of the runtime/dashboard/agent images stood in for the registry (see below).go build,go vet, fullgo test ./services/cli/...; golangci-lint v2.13.1 in CI's new-issues mode: 0 issues. Prettier warnings on five touched docs files are pre-existing atmain(identical output on theHEADcopies).Blocker for the released path (owner action)
The GHCR packages
af-stack-runtime,af-stack-dashboard,af-stack-customer-appare private: an anonymous manifest fetch returns 403 while a public image on the same registry returns 200, anddocker pullis denied. Nothing scaffolded by a released CLI can pull them until each package is set to Public in the org's package settings (GitHub has no API for this).docker-compose.prod.ymlhas had the same problem all along. The new release gate fails with that instruction until it is done; thesupportdesk-agentpackage will be created private by the first release that builds it and needs the same flip, then a re-run of the smoke job.🤖 Generated with Claude Code