Lathe generates agent-friendly Cobra CLIs from Swagger 2.0, OpenAPI 3, google.api.http protobuf APIs, and policy-curated GraphQL schemas. Declared API specs and project configuration are the source of truth. Pinned Git sources are reproducible; local_path sources intentionally follow the referenced working tree.
Lathe is a spec-to-agent-toolchain generator. It turns declared API specs, from pinned Git sources or explicit local working trees, plus repo-local configuration into one inspectable Cobra CLI that both humans and AI agents can run safely.
The core product promise is: agents should not guess command names, flags, auth state, request body shape, HTTP path, or output format. Generated CLIs must expose machine-readable contracts (search, commands --json, commands show, commands schema) and generated Skill guidance so agents can discover, inspect, verify auth, and then execute.
Lathe also owns lathe init for CLI-first application repositories and lathe skill install for its bundled Agent Skill. These distribution surfaces must serve the spec-to-agent workflow; Lathe is not a generic scaffolder, CLI framework, plugin loader, GUI/TUI, API gateway, or hand-written SDK replacement. Product work should strengthen spec fidelity, reproducibility, generated command correctness, runtime catalog inspectability, auth/body/output behavior, application initialization, and generated Skill quality. Challenge features that move product weight into manually authored commands, runtime plugins, or unrelated scaffolding.
- Follow this file for repository structure, commands, style, tests, commits, PR rules, and release workflow entry points.
- Follow
CONTRIBUTING.mdfor contributor workflow and public contribution scope. - Trust code and current Makefile targets over stale documentation when they disagree.
- In this repository, do not commit generated output under
internal/generated/, upstream clones under.cache/, example build artifacts, or ad-hoc generatedskills/<cli-name>/directories. Downstream repositories created bylathe inithave their own generated-output policy.
cmd/lathecontains the executable entry point for init, Skill installation, spec syncing, code generation, bootstrap, and version reporting.internal/lathecmdorchestrates CLI commands;internal/projectinitandinternal/latheskillown application initialization and the bundled Lathe Skill.internal/sourceconfig,internal/specsync,internal/codegen/{app,backends,normalize,rawir,render}, andinternal/overlayown the generation pipeline.internal/authholds implementation-only runtime authentication support.pkg/runtime,pkg/config, andpkg/latheare downstream-facing runtime/library surfaces for generated CLIs.- Tests live beside implementation as
*_test.go; golden fixtures live under package-localtestdata/. examples/contains example generation paths, anddocs/contains architecture and usage guides.
- The generation pipeline has two phases: codegen-time (
cmd/lathe,internal/lathecmd,internal/sourceconfig,internal/specsync,internal/codegen/**,internal/overlay) and runtime (pkg/config,pkg/runtime,pkg/lathe,internal/auth, plus generated modules). - API operations cross the seam as generated
[]runtime.CommandSpecliterals ininternal/generated/<module>/<module>_gen.go;internal/generated/modules_gen.gocomposes those modules with generated workflows and bundled capabilities throughgenerated.Mount. pkg/runtimemust remain independent ofinternal/codegen/**; runtime behavior cannot depend on raw specs, overlays, or sync cache state.- Overlays are codegen-time polish only. They are merged into
CommandSpec; the runtime must not learn overlay concepts. specs/sources.yaml,cli.yaml, pinned upstream refs or explicitlocal_pathsources, and optional overlays are the durable inputs. A local source is not pinned; sync state must record and validate its resolved path. Generated files are outputs, not hand-edited source.
- Keep changes small and focused; avoid speculative abstractions.
- Prefer configuration or overlays (
cli.yaml,specs/sources.yaml, overlay config) over hard-coded generated behavior. - Preserve package boundaries:
internal/**is implementation-only,pkg/**is downstream-facing API. - Use standard Go formatting through
gofmt/go fmt. - Wrap errors with context using
fmt.Errorf("...: %w", err). - For codegen, normalization, or runtime behavior changes, use focused package-local tests. Use golden fixtures only when serialized generated output or IR is the contract.
- For CLI-visible behavior changes, update docs or examples only when the user-facing output or workflow actually changes.
- If a change alters generated command shape, catalog JSON, auth flow, body building, output formatting, retry/debug behavior, or Skill rendering, treat it as product behavior and prove it with focused tests or an example run.
make helpis the source of truth for available Make targets.make buildbuilds./bin/lathe;make installcopies it intoBINDIR.make checkis the full local quality gate: format check,go vet,golangci-lint, and tests.make testrunsgo test ./....make fmt,make fmt-check,make vet,make lint, andmake tidyrun focused maintenance tasks.- Generation workflows use an installed
latheorgo run ./cmd/lathe:specsync,codegen, andbootstrap. There are no Make wrappers for these commands. docs/cli-usage.mddocuments the end-to-end generated CLI workflow.- Prefer the narrowest Make target that proves the changed surface.
- Use
make checkbefore commit or PR unless the change is documentation-only and the user agrees to skip it.
- Before claiming completion, run the narrowest command that proves the changed surface.
- For runtime-sensitive changes, also run the relevant example script or
go test -race ./.... - For codegen changes, verify regenerated output behavior, but do not commit generated output under
internal/generated/. - For
lathe initor bundled Skill changes, run the focused package tests and a scratch init. For shell-level Skill smoke, combine a user-scope dry-run with a project-scope install in scratch; never overrideHOMEor write to the real user Skill directory. - CI runs
go build ./...,go vet ./...,golangci-lint, andgo test -race ./...; local proof should explain any narrower substitute. - If a command cannot be run because a dependency is missing, report that directly instead of claiming success.
- The runtime catalog is the source of truth for generated CLI operation details. Generated Skill files are guidance and indexes, not execution authority.
- Use
<cli> __lathe verify --jsonto validate the generated CLI contract before broader acceptance checks. - Preserve the agent loop:
search "<intent>" --jsonfor candidates,commands show <path...> --jsonfor exact command detail,auth status --hostname <host>whenauth.required=true, then execute with known flags/body/output. - Search results are discovery only. Agents must not execute directly from search output.
- Prefer
-o jsonfor machine-readable command output unless the user asked for table, yaml, or raw output. - Changes touching
pkg/runtime/catalog.go,pkg/lathe/catalog.go,pkg/runtime/build.go,internal/codegen/app/**, orinternal/codegen/render/skill.gomust consider catalog schema compatibility, generated Skill instructions, and agent inspectability.
- HTTP runtime changes must account for SSRF, unsafe TLS, retry/debug logging, header handling, token leakage, and response error leakage.
- Host config and auth changes must protect persisted credentials and avoid printing secrets in normal, debug, or error output.
- Spec sync and codegen path handling must reject traversal, unsafe output roots, and accidental deletion of non-owned directories.
- Code templates must not emit shell-sensitive or injection-prone behavior from untrusted spec text.
- Treat upstream specs as trusted product inputs but still escape or validate anything that becomes Go code, CLI flags, help text, file paths, or generated Skill markdown.
- Commit messages use Conventional Commits.
- Use
git commit -sfor every commit. - Keep PRs focused and include the exact verification commands run.
- Use
.agents/skills/lathe-release/SKILL.mdfor versioned release validation and publishing. It starts read-only; tagging and publishing still require explicit authorization.
- If
CLAUDE.local.mdexists, read it before starting non-trivial work; some non-Claude-Code agents will not load it automatically, but its instructions are still required.