# AGENTS.md

## Overview
clnkr is a coding agent CLI that queries LLMs and executes bash commands in a loop. Core library is stdlib only. Talks to the Anthropic Messages API and any OpenAI-compatible endpoint. Ships `clnkr` (plain CLI) and `clnkrd` (stdio JSONL adapter). Evals run through the standalone `clankerval` project.

## Commands
```
make build       # Build shipped binaries (default target)
make test        # Run all tests
make check       # Run the full quality suite
make man         # Generate staged man pages from doc/*.1.md
make docs        # Build the documentation site
make docs-serve  # Run the documentation site locally
make _fmt        # Format source
make _hooks      # Configure repo-local Git hooks
```
Run `make _fmt` then `make check` before committing. Do not commit if either fails.

## Rules
- No external deps in root go.mod. Stdlib only.
- Assume Unix (`bash`, process groups, `/usr/bin/env`). Windows unsupported.
- Root `clnkr` is the only public import surface. `internal/` is allowed when it clarifies ownership.
- Output goes through typed events. Do not add `io.Writer` parameters.
- Policy logic in `Run()`, shared logic in `Step()`. No policy in `Step()`.
- CLI config resolution stays in `cmd/internal/providerconfig`: env/flag precedence, `CLNKR_*`, API keys, base URL parsing, provider detection, and user-facing config errors.
- Provider request semantics stay in `internal/providers/providerconfig`: provider/API constants, request options, model capability checks, and provider-specific validation.
- Provider adapters serialize validated options; they do not resolve CLI config.
- Child-agent orchestration is prompt-guided Unix process composition. Bash may launch `clnkrd`; the host does not special-case child agents, `/delegate`, child counters, or child lifecycle events.
- Wrap errors: `fmt.Errorf("context: %w", err)`. No bare returns or third-party error packages.
- Adapter tests use external packages (`package anthropic_test`). Core tests use internal (`package clnkr`). CLI tests use internal (`package main`). Match the existing pattern.
- `exhaustive` linter is enabled. Switch on sealed types must cover all cases. `default` counts as exhaustive.
- Do not manually edit `CHANGELOG.md`; generated by the release pipeline.
- Do not hand-edit generated files in `build/docs/`, `site/content/docs/clnkr.md`, `site/content/docs/clnkrd.md`, or `site/public/`.
- Public-facing docs describe current behavior, not implementation history. No `in this pass`, `for now`, `currently deferred`.
- SLOC gates count non-test Go only. Treat them as invariants and honesty constraints: do not shrink counted CLI help, diagnostics, UX, or error clarity to satisfy them, and do not weaken tests or docs to normalize that kind of regression. Agents must not raise SLOC limits unless the user explicitly gives a target number. If raising a gate is the only reasonable path, stop and ask for clarification.
- For changes that touch clnkr's agent design, read `doc/clnkr.7.md` for current architecture context: act protocol, transcript, provider boundary, and command execution. It is descriptive, not prescriptive. Verify behavior in code and follow this file for rules.
- Repo-maintenance helpers live under `scripts/`. Read `scripts/README.md` before adding new ones.

## Architecture
Core importable library at module root. Two command adapters. `evaluations/` consumed by external `clankerval` runner.
```
clnkr/                  # core: types, Agent, events (stdlib only)
├── internal/providers/ # Anthropic/OpenAI adapters
├── internal/session    # Session persistence runtime boundary
├── cmd/clnkr/          # Plain CLI (root go.mod, no external deps)
├── cmd/clnkrd/         # Stdio JSONL adapter
└── evaluations/        # Eval suites for clankerval
```

**Agent API:** `Step()` = one typed-turn cycle, no policy. `ExecuteTurn()` = run an act turn, update state, emit events. `Run()` = full-send policy loop (3 consecutive protocol failures = exit).

**Act protocol:** Three turn types: `act`, `clarify`, `done`. Providers own wire translation. Root `ParseTurn` validates canonical internal JSON for replay/tests only.

**Events:** Sealed interface for typed agent notifications. Keep new event types explicit and exhaustive in adapters. Nil `Notify` = silent.

**Command results (host→model):** JSON with `stdout`, `stderr`, `outcome`, and optional `feedback`. Exit outcomes include `exit_code`; non-exit outcomes include timeout, cancelled, denied, skipped, and error.

**Child process boundary:** `clnkrd` is the composable process surface. The prompt teaches models when to launch `clnkrd` through bash for bounded child work and how to read stdout/stderr or event logs. `Driver`, provider adapters, `CommandExecutor`, and `Agent.Step()` do not participate in child-agent policy.

## Release
Tag-driven. Push feature to `main`, wait for CI/evals/site to go green, then push the plain semantic version tag. Release workflow triggers from semver tags, updates `debian/main`, and generates Debian changelog. Remote `main` may move. Fetch and rebase before follow-up pushes.

## Commit Metadata
Before creating a commit, choose the functional area for the work. Every commit made by a coding agent must include exactly one `Functional-Area:` git trailer.

Use a stable hyphenated area name. Pick it from the user-named feature, active roadmap item, or relevant atuin memory key when available. If the area is unclear, ask before committing.

Examples:
- `Functional-Area: context-management` for transcript, compaction, or context-budget changes
- `Functional-Area: provider-config` for provider option and API configuration changes
- `Functional-Area: docs` for documentation-only changes

Commit with the trailer:
```
git commit --trailer "Functional-Area: context-management"
```

## Evals
Optimize for live runs that measure actual agent behavior. Fixture evals exist for harness determinism in CI, not as the primary signal. `clankerval` requires a clean checkout. Make a temporary commit from a dirty worktree, run, then unroll.

## Site
Hugo site under `site/`. Source of truth for reference docs is `doc/*.1.md`. Run `make docs` to regenerate. Do not commit `site/public/`. Deployment to `gh-pages` is automatic from `main`.

## Testing
- Provider adapters: `httptest.NewServer`, external test packages, no real API calls
- Agent loop: `fakeModel`/`fakeExecutor` in `agent_test.go`
- CLI: inject via narrowest local interface, not concrete structs
- Executor: real shell integration tests; handles macOS `/private/tmp` symlink

## CI
GitHub Actions on push to `main` and PRs. Runs lint, tests (`-race`), build, docs, and evals. `make check` also enforces architecture edges and core SLOC accounting. Run `make _hooks` for local pre-commit. golangci-lint required.
