init-project
Scaffold a new Go hexagonal / DDD microservice from a bundled, frozen template — an
empty-but-runnable snapshot of the account-service architecture (clean layers + tooling + infra
wiring + .kiro/ steering + CLAUDE.md) with zero business domains. The generated project
builds and serves GET /health immediately and is ready for using-neo (or Kiro) to add the first domain
with no setup.
This skill only creates the empty skeleton. Authoring domains / AC / endpoints / tests is the
using-neoskill — point the user there once the project exists.
What it produces
A complete service skeleton under the target dir:
- Layers —
cmd/api(composition root),config,internal/delivery/http/{router,middleware}(with/health),internal/adapters/repository/{postgres,redis,cache},pkg/{clock,idgen,cache/valkey,lib/kafka}. - Tooling —
Makefile,Dockerfile,docker-compose.yaml(postgres + valkey + kafka),.gitlab-ci.yml(workflow + Go cache;prepare-mod/test/ec2-shellbuild— no e2e untiltests/e2eexists),.golangci.yaml,.mockery.yaml,sqlc.yaml, pinnedtools/*modules. - Agentic context —
.kiro/steering/*(architecture guides) +CLAUDE.md. Skills and agents come from the neo plugin / user install — not bundled under the service tree. internal/core/{domain,usecase}, gateways, and HTTP handlers are created through using-neo, not the skeleton — a fresh service legitimately has none.
The boot path is best-effort: go run ./cmd/api serves /health even with no Postgres / Redis /
Kafka running (it warns and continues — it never panics on missing infra).
Tools
| Tool | Purpose |
|---|---|
AskUserQuestion / chat |
Gather the new service's identity (module path, name, id, postgres schema, target dir). |
Bash |
Run assets/scaffold.py (generate) + assets/initcheck.py (L1 verify). |
Agent |
Dispatch the L2 fresh-eyes verifier (references/init-verifier.md). |
Read |
Read the guide / verifier references. |
In the steps below, <skill-dir> is this skill's base directory (shown to you when the skill loads).
Preconditions
- Go ≥ 1.26 on PATH.
- Private module access for the org
common-libthe template depends on —GOPRIVATEset for the module host (e.g.gitlab.awesome-poc-th.com/*) and working git credentials (SSH or~/.netrc). Without itgo mod tidy/go buildfail with an auth error andscaffold.pyprints a hint; you can still create the project with--no-buildand tell the user to build once they have access.
Steps
Gather identity. Get five values from the user (ask for the module path first; derive sensible suggestions for the rest and confirm):
- module path — the Go module path, e.g.
gitlab.awesome-poc-th.com/libero-engineering/core/<svc>. - service name — kebab-case; default to the last path segment of the module.
- service id — UPPER short id used in the error envelope / tracer (e.g.
NEOPAY); suggest one from the name and confirm. - postgres schema — the schema this service owns inside the shared database (services share
one database —
sit_core— one schema per service, pinned viasearch_path); suggest the service name minus a trailing-servicewith dashes→underscores (e.g.account-service→account) and confirm. - target dir — where to create the project (suggest a sibling dir
../<service-name>).
Confirm all five before generating. Never invent the module path — it is org-specific; ask.
- module path — the Go module path, e.g.
Generate. Run the bundled scaffold:
python3 <skill-dir>/assets/scaffold.py \ --target-dir <dir> --module-path <mod> --service-name <name> --service-id <id> --schema <schema>It copies the frozen template, substitutes the four sentinels, runs
go mod tidy,git init, andgo build ./.... If the build fails on private-module auth (the output prints a hint), re-run with--no-buildand tell the user to rungo mod tidy && go build ./...once they have access.L1 verify (deterministic). Run the checker; every check must PASS:
python3 <skill-dir>/assets/initcheck.py \ --target-dir <dir> --module-path <mod> --service-name <name> --service-id <id> --schema <schema>It proves: build + vet, module identity,
go mod verify, no leftover sentinels, steering placeholders preserved, manifest present, zero business survivors, no domain imports in outer layers,/healthwired with an emptyHandlers, and a best-effort (never-panicking) boot path. If any check FAILs, fix and re-run before reporting success.L2 verify (fresh eyes). Dispatch a sub-agent —
Agent(subagent_type: "fresh-eyes"), read-only by tool grant (harness without that type →general-purpose) — with the contract inreferences/init-verifier.md, passing the target dir. It independently confirms the project is a genuinely empty, runnable skeleton (serves/healthwithout Docker, no business leak, steering intact). Relay any issue it surfaces.Report. Summarize concisely: where the project is, that it builds + serves
/health, and the next step —cd <dir> && go run ./cmd/api(curllocalhost:8080/health), then useusing-neoto add the first domain.
Notes
- The bundled template is a frozen snapshot under
assets/template/(sentinel module pathexample.com/neo/service, nameneo-service, idNEOSVC, postgres schemaneoschema). To refresh it whenaccount-service's conventions change, followreferences/init-project-guide.md. - Generic steering placeholders (
{{MODULE_PATH}},<context>, …) are intentionally left unresolved forusing-neoto fill per-domain — only the four sentinels are substituted at generation time.