-
Notifications
You must be signed in to change notification settings - Fork 0
docs: add CLAUDE.md for Claude Code guidance #235
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,109 @@ | ||
| # CLAUDE.md | ||
|
|
||
| This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. | ||
|
|
||
| ## Commands | ||
|
|
||
| ```bash | ||
| make fmt # gofmt + goimports | ||
| make lint # golangci-lint | ||
| make vuln # govulncheck | ||
| make test # run all module tests with -race | ||
| make test-coverage # generate coverage report in .coverage/ | ||
| make test-patch-coverage # patch-only coverage vs origin/main | ||
| make tools # install all pinned dev tools | ||
| make setup-hooks # install dev tools + git hooks (lefthook + commitlint) | ||
| make cli-smoke-build # build the modkit CLI binary | ||
| make cli-smoke-scaffold # smoke test CLI scaffold flow | ||
| ``` | ||
|
|
||
| Run a single package's tests: | ||
| ```bash | ||
| cd modkit/kernel && go test -race ./... | ||
| ``` | ||
|
|
||
| Run tests for all workspace modules (including examples): | ||
| ```bash | ||
| # make test does this automatically by iterating all go.mod files | ||
| make test | ||
| ``` | ||
|
|
||
| ## Architecture | ||
|
|
||
| modkit is a multi-module Go workspace (`go.work`). The root module is `github.com/go-modkit/modkit`. Examples are separate modules under `examples/`. | ||
|
|
||
| ``` | ||
| modkit/ | ||
| ├── modkit/ # Core framework packages (the library) | ||
| │ ├── module/ # Public API: ModuleDef, ProviderDef, Token, Resolver | ||
| │ ├── kernel/ # Graph builder, visibility enforcer, lazy singleton container, bootstrap | ||
| │ ├── http/ # Chi-based HTTP adapter: Router, RegisterRoutes, Serve, middleware | ||
| │ ├── logging/ # Logger interface + slog adapter + nop | ||
| │ ├── config/ # Typed env config module helpers | ||
| │ ├── data/ # DB providers: sqlmodule (shared contract), postgres, sqlite sub-packages | ||
| │ └── testkit/ # Test harness: bootstrap helpers, provider overrides | ||
| ├── examples/ # Runnable apps (separate go.mod each) | ||
| │ ├── hello-simple/ # Minimal bootstrap, no Docker | ||
| │ ├── hello-mysql/ # Full CRUD: auth, users, middleware, sqlc, swagger | ||
| │ ├── hello-postgres/ | ||
| │ └── hello-sqlite/ | ||
| ├── cmd/modkit/ # CLI tool (cobra): `modkit new app <name>` | ||
| └── docs/ # Guides and architecture reference | ||
| ``` | ||
|
|
||
| ### Bootstrap Flow | ||
|
|
||
| `kernel.Bootstrap(rootModule)` does four things in order: | ||
|
|
||
| 1. **Build graph** — flattens the import tree depth-first, rejects cycles and duplicate names | ||
| 2. **Build visibility** — computes which tokens each module can access (own providers + exported tokens from imports) | ||
| 3. **Create container** — registers provider factory functions (not built yet) | ||
| 4. **Build controllers** — calls each `ControllerDef.Build`, which triggers lazy provider construction | ||
|
|
||
| Providers are lazy singletons: built on first `Get()`, cached for subsequent calls. | ||
|
|
||
| ### Key Interfaces | ||
|
|
||
| ```go | ||
| // A module must be a pointer and implement: | ||
| type Module interface { | ||
| Definition() ModuleDef | ||
| } | ||
|
|
||
| // Controllers must implement to register HTTP routes: | ||
| type RouteRegistrar interface { | ||
| RegisterRoutes(router Router) | ||
| } | ||
|
|
||
| // Resolve a typed dependency inside a Build function: | ||
| svc, err := module.Get[T](r, "token.name") | ||
| ``` | ||
|
|
||
| ### Token Naming Convention | ||
|
|
||
| Tokens follow `"module.component"` — e.g., `"users.service"`, `"db.connection"`. Shared SQL contract tokens live in `sqlmodule`: `sqlmodule.TokenDB`, `sqlmodule.TokenDialect`. | ||
|
|
||
| ## Conventions | ||
|
|
||
| - Modules must be **pointers** — pointer identity determines shared import deduplication | ||
| - `Definition()` must be **pure/deterministic** — no mutable side effects or counters | ||
| - Resolve deps via `r.Get()` inside `Build` functions; always check `err` before use | ||
| - Controllers call explicit `r.Handle(method, path, handler)` — no reflection, no decorators | ||
| - Error handling: return/wrap errors; no panic-driven control flow | ||
| - Tests: `*_test.go` alongside implementation, table-driven where useful | ||
|
|
||
| ## Anti-Patterns | ||
|
|
||
| - Do not add reflection or decorator magic to user-facing APIs | ||
| - Do not make `Definition()` stateful | ||
| - Do not wire across module boundaries without going through the export/import mechanism | ||
| - Do not hand-edit generated files (`*.sql.go`, swagger-generated docs) | ||
|
|
||
| ## Branch and PR Workflow | ||
|
|
||
| - `main` is integration-only — never commit directly on it | ||
| - Create work on a worktree branch: `git worktree add .worktrees/<task> -b feat/<task> main` | ||
| - Before opening a PR: `make fmt && make lint && make vuln && make test && make test-coverage` | ||
| - If the repo has a PR template (`.github/pull_request_template.md`), follow it exactly and actively check/uncheck each item | ||
| - Include `Resolves #<number>` lines for any GitHub issues the PR addresses | ||
| - Commit messages follow Conventional Commits: `feat:`, `fix:`, `docs:`, `test:`, `chore:`, `refactor:`, `perf:`, `ci:` — header ≤80 characters | ||
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.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add a language specifier to the fenced code block.
The architecture tree block is missing a language tag, which triggers markdownlint MD040. Using
textsatisfies the rule without implying any specific syntax.📝 Proposed fix
📝 Committable suggestion
🧰 Tools
🪛 markdownlint-cli2 (0.21.0)
[warning] 35-35: Fenced code blocks should have a language specified
(MD040, fenced-code-language)
🤖 Prompt for AI Agents