Files
gnoma/CLAUDE.md
T
vikingowl 1828151162 docs(claude): big-picture architecture and expanded test commands
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.
2026-05-24 15:39:23 +02:00

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

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:

  1. cmd/gnoma parses flags, picks TUI vs pipe mode, builds the session.
  2. internal/session owns one chat lifecycle; internal/engine runs the agentic loop (stream → tool calls → re-query → until done).
  3. internal/router picks the arm per prompt: multi-armed bandit over provider adapters in internal/provider/{anthropic,openai,google,mistral,openaicompat}, tiered SLM (internal/slm) → CLI-agent subprocess → local → cloud, with Strengths + MaxComplexity + CostWeight shaping selection.
  4. internal/security is the safety boundary: SafeProvider wrapping, firewall (network egress), secret scanner, redaction, incognito mode. internal/safety is separate — it's the pre-launch CWD classifier.
  5. internal/tool is the local-action boundary; internal/permission gates every tool call.
  6. 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.RawMessage for tool schemas and arguments (zero-cost passthrough)
  • Functional options for complex configuration
  • errgroup for parallel work

Testing

  • TDD: write tests first
  • Table-driven tests
  • Build tag //go:build integration for tests hitting real APIs
  • testing/synctest for concurrent tests
  • t.TempDir() for file system tests

Naming

  • Packages: short, lowercase, no underscores
  • Interfaces: describe behavior, not implementation
  • Errors: Err prefix for sentinel errors, *Error suffix 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