Add a 'Big picture' section summarising the request flow (cmd → session → engine → router → security/permission → extensibility) so future Claude Code instances can orient without reading INDEX.md plus five package directories first. Note that internal/safety and internal/slm aren't in INDEX.md yet. Document the somegit.dev / GitHub mirror split and the ruleset that blocks force-push and deletion on main/dev. Expand build/test section with make check, make test-integration, single-test, and benchmark commands.
3.7 KiB
Gnoma — Project Instructions
What is this?
Provider-agnostic agentic coding assistant in Go 1.26. Named after the northern pygmy-owl (Glaucidium gnoma). Agents are called "elfs" (elf owl).
Module & repo layout
- Module:
somegit.dev/Owlibou/gnoma - Upstream (primary, accepts PRs): https://somegit.dev/Owlibou/gnoma
- GitHub mirror (read-only): https://github.com/VikingOwl91/gnoma
PRs go to the upstream Gitea instance, not GitHub. The GitHub side is a
push mirror — direct pushes to main/dev there will be rejected by the
ruleset.
Big picture (read this before diving in)
Single static Go binary. Request flow:
cmd/gnomaparses flags, picks TUI vs pipe mode, builds the session.internal/sessionowns one chat lifecycle;internal/engineruns the agentic loop (stream → tool calls → re-query → until done).internal/routerpicks the arm per prompt: multi-armed bandit over provider adapters ininternal/provider/{anthropic,openai,google,mistral,openaicompat}, tiered SLM (internal/slm) → CLI-agent subprocess → local → cloud, withStrengths+MaxComplexity+CostWeightshaping selection.internal/securityis the safety boundary: SafeProvider wrapping, firewall (network egress), secret scanner, redaction, incognito mode.internal/safetyis separate — it's the pre-launch CWD classifier.internal/toolis the local-action boundary;internal/permissiongates every tool call.- Extensibility surfaces:
internal/hook,internal/skill,internal/mcp(JSON-RPC over stdio),internal/plugin(TOFU-pinned).
Discriminated unions (struct + type discriminant) are the project's
chosen way to model variants — see internal/message and
internal/stream. Don't reach for interfaces when a discriminant fits.
Full essentials (vision, domain model, ADRs, process flows):
docs/essentials/INDEX.md. Read INDEX.md before changing
architectural boundaries or adding new packages. Note: INDEX
predates internal/safety and internal/slm — cross-check the actual
tree.
Build & Test
make build # ./bin/gnoma
make test # unit tests
make test-integration # //go:build integration — needs real API keys
make lint # golangci-lint run ./...
make check # fmt + vet + lint + test — canonical pre-commit gate
make cover # coverage.html
# Run a single test / package
go test -run TestRouterSelect ./internal/router/
go test -v ./internal/router/
# Benchmarks
go test -bench=. ./internal/router/
Conventions
Go Style
- Go 1.26 idioms:
new(expr),errors.AsType[E],sync.WaitGroup.Go - Structured logging with
log/slog - Discriminated unions via struct + type discriminant (not interfaces)
- Pull-based stream iterators:
Next() / Current() / Err() / Close() json.RawMessagefor tool schemas and arguments (zero-cost passthrough)- Functional options for complex configuration
errgroupfor parallel work
Testing
- TDD: write tests first
- Table-driven tests
- Build tag
//go:build integrationfor tests hitting real APIs testing/synctestfor concurrent testst.TempDir()for file system tests
Naming
- Packages: short, lowercase, no underscores
- Interfaces: describe behavior, not implementation
- Errors:
Errprefix for sentinel errors,*Errorsuffix for error types
Commits
- Conventional commits (feat:, fix:, refactor:, test:, docs:, chore:)
- No co-signing
Providers
- Mistral:
github.com/VikingOwl91/mistral-go-sdk(user's own SDK) - Anthropic:
github.com/anthropics/anthropic-sdk-go - OpenAI:
github.com/openai/openai-go - Google:
google.golang.org/genai - Ollama/llama.cpp: via OpenAI SDK with custom base URL