|
| 1 | +# odek — Agent Maintenance Guide |
| 2 | + |
| 3 | +This file is automatically loaded by odek when running inside this repository. |
| 4 | +It provides context about the project's architecture, conventions, and how to update/maintain it. |
| 5 | + |
| 6 | +--- |
| 7 | + |
| 8 | +## Project Identity |
| 9 | + |
| 10 | +- **Package:** `odek` (Go module: `github.com/BackendStack21/kode`) |
| 11 | +- **What it is:** Minimal Go autonomous agent runtime — ReAct (Reasoning + Acting) loop with zero external dependencies (stdlib only). |
| 12 | +- **Binary:** `odek` — single static binary, ~11 MB, instant startup. |
| 13 | +- **Config:** Layered priority: `~/.odek/config.json` → `./odek.json` → `ODEK_*` env vars → CLI flags. |
| 14 | + |
| 15 | +## Source Layout |
| 16 | + |
| 17 | +``` |
| 18 | +odek.go Public API (Config, New, Run, Close, ModelProfile, KnownProfiles) |
| 19 | +odek_test.go Tests for public API |
| 20 | +cmd/odek/ |
| 21 | + main.go CLI entry point, flag parsing, commands, sandbox |
| 22 | + shell.go Built-in shell tool (local or docker exec) |
| 23 | + serve.go Web UI server (HTTP + WebSocket) |
| 24 | + subagent.go Sub-agent command (--goal, --context, --task) |
| 25 | + subagent_tool.go delegate_tasks built-in tool |
| 26 | + ui/index.html Single-page Web UI (~770 LOC, vanilla JS + CSS) |
| 27 | + *_test.go CLI, subagent, contract, and E2E tests |
| 28 | +internal/ |
| 29 | + config/loader.go Config file loading, env vars, priority merge |
| 30 | + llm/client.go OpenAI-compatible HTTP client |
| 31 | + loop/loop.go ReAct engine (observe → think → act → repeat) |
| 32 | + session/session.go Session store (CRUD, trim, cleanup) |
| 33 | + render/render.go Terminal output with model label and color |
| 34 | + resource/resource.go @-reference resolver (files, sessions) |
| 35 | + ws/ws.go RFC 6455 WebSocket framing (~200 LOC) |
| 36 | + tool/registry.go Thread-safe tool registry, clarify.go |
| 37 | + danger/classifier.go Command/URL classification for security gating |
| 38 | + memory/ MemoryManager (facts, buffer, episodes, merge, scan) |
| 39 | + skills/ Skill system (types, loader, triggers, self-improve, curator, import) |
| 40 | + telegram/ Telegram bot client, poller, handler, commands |
| 41 | +docs/ Documentation (CLI, API, CONFIG, MCP, MEMORY, etc.) |
| 42 | +``` |
| 43 | + |
| 44 | +## How It Works |
| 45 | + |
| 46 | +1. **Agent Loop (`internal/loop/loop.go`):** ReAct cycle: observe → think → act → repeat. |
| 47 | + - LLM returns a tool call or final answer. |
| 48 | + - Tools execute and return results. |
| 49 | + - Max 90 iterations by default (`--max-iter`). |
| 50 | +2. **Tools:** Built-in: `read_file`, `write_file`, `search_files`, `patch`, `shell`, `browser`, `memory`, `clarify`, `delegate_tasks`. All gated by the `danger` security classifier. |
| 51 | +3. **Skills:** Trigger-matched `SKILL.md` files loaded on-demand. Auto-learns from patterns every session. Stored in `~/.odek/skills/` and `./.odek/skills/`. |
| 52 | +4. **Memory:** Three tiers — facts (durable entries), session buffer (turn summaries), episodes (LLM-extracted knowledge). Uses go-vector RandomProjections for merge-on-write. |
| 53 | +5. **Sub-agents:** `delegate_tasks` spawns real OS subprocesses via `odek subagent`. Each gets a fresh agent process with its own config. |
| 54 | + |
| 55 | +## Key Conventions |
| 56 | + |
| 57 | +- **Zero-dependency policy:** No external Go modules beyond stdlib. All contributions must maintain this. |
| 58 | +- **Tests:** 1760+ tests, run with `go test ./...` (no network, no Docker needed for unit tests). |
| 59 | +- **Error handling:** Return errors, don't panic. Fatal errors go through `fmt.Fprintf(os.Stderr, ...)`. |
| 60 | +- **Config structs:** JSON tags for serialization. `*bool` for optional tristate fields (nil = not set). |
| 61 | +- **Security:** Symlinked AGENTS.md is refused. Shell commands are classified into 8 risk classes. Sandbox mode uses Docker with no network and read-only mounts. |
| 62 | +- **Model profiles:** Added in `odek.go`'s `KnownProfiles` var. Longest-prefix matching. |
| 63 | + |
| 64 | +## How to Update/Maintain This Project |
| 65 | + |
| 66 | +### Building |
| 67 | + |
| 68 | +```bash |
| 69 | +go build -o bin/odek ./cmd/odek # build binary |
| 70 | +go build ./... # check compilation |
| 71 | +``` |
| 72 | + |
| 73 | +### Testing |
| 74 | + |
| 75 | +```bash |
| 76 | +go test ./... -count=1 # all unit tests |
| 77 | +go test -race ./... -count=1 # with race detector |
| 78 | +go test -v ./internal/session/ # specific package |
| 79 | +KODE_E2E=true go test ./cmd/odek/ -run "TestE2E_" # E2E tests |
| 80 | +``` |
| 81 | + |
| 82 | +### Adding a New Model Profile |
| 83 | + |
| 84 | +Edit `odek.go`, add to `KnownProfiles`: |
| 85 | +```go |
| 86 | +{ |
| 87 | + Prefix: "my-model", |
| 88 | + Profile: ModelProfile{ |
| 89 | + Label: "My Model", |
| 90 | + DefaultThinking: "enabled", |
| 91 | + Timeout: 120, |
| 92 | + MaxContext: 128_000, |
| 93 | + }, |
| 94 | +}, |
| 95 | +``` |
| 96 | + |
| 97 | +### Adding a New Tool |
| 98 | + |
| 99 | +1. Create the tool struct in `cmd/odek/` or `internal/tool/`. |
| 100 | +2. Implement `Name()`, `Description()`, `Schema()`, `Call(args string) (string, error)`. |
| 101 | +3. Register in `registerBuiltinTools()` in `cmd/odek/main.go`. |
| 102 | +4. Add security classification in `internal/danger/classifier.go` if it runs shell commands. |
| 103 | +5. Add tests. |
| 104 | + |
| 105 | +### Adding a New Command/Flag |
| 106 | + |
| 107 | +1. Define the flag in `main.go`'s `flags` struct. |
| 108 | +2. Parse in `parseFlags()`. |
| 109 | +3. Wire through `resolveConfig()` into the resolved config. |
| 110 | +4. Pass to `odek.New()` or the relevant handler. |
| 111 | +5. Document in `docs/CLI.md` and `docs/CONFIG.md`. |
| 112 | +6. Add env var support in `internal/config/loader.go`. |
| 113 | + |
| 114 | +### Documentation |
| 115 | + |
| 116 | +- All docs are Markdown in `/docs/`. |
| 117 | +- `docs/CLI.md` — CLI reference (commands, flags, error codes). |
| 118 | +- `docs/API.md` — Programmatic API with Go examples. |
| 119 | +- `docs/CONFIG.md` — Configuration system. |
| 120 | +- `docs/DEVELOPMENT.md` — Building, testing, contributing. |
| 121 | +- Update docs when adding/changing features. |
| 122 | + |
| 123 | +### Skill System Maintenance |
| 124 | + |
| 125 | +- Skills live in `~/.odek/skills/` and `./.odek/skills/` as `SKILL.md` files with YAML frontmatter. |
| 126 | +- Learning is on by default (`--no-learn` to disable). |
| 127 | +- Use `odek skill curate` to audit quality/overlap. |
| 128 | +- Use `odek skill import <uri>` to import from URLs. |
| 129 | + |
| 130 | +### Memory System |
| 131 | + |
| 132 | +- Facts: `~/.odek/memory/user.md` and `~/.odek/memory/env.md`. |
| 133 | +- Episodes: Stored as JSON files in `~/.odek/memory/episodes/`. |
| 134 | +- Buffer: Ring buffer of turn summaries, stored in `~/.odek/memory/buffer.json`. |
| 135 | +- Use the `memory` tool (6 actions: read, add, replace, remove, consolidate, search). |
| 136 | + |
| 137 | +### Security Considerations |
| 138 | + |
| 139 | +- **Prompt injection:** Identity anchoring anchors agent identity at the start of the system prompt. Anti-injection rules applied on top. AGENTS.md comes after identity. |
| 140 | +- **Symlink protection:** `LoadProjectFile()` refuses symlinks. |
| 141 | +- **Sandbox:** `--sandbox` flag runs in Docker with no network, no host mounts beyond working dir, zero capabilities. |
| 142 | +- **Danger classifier:** Commands classified into 8 risk classes. Configurable via `dangerous` config section. |
| 143 | + |
| 144 | +### Release Process |
| 145 | + |
| 146 | +1. Update version tag: `git tag v0.x.y` |
| 147 | +2. Build cross-platform: `make build-all` |
| 148 | +3. Run full test suite: `make test-all` |
| 149 | +4. Push tag: `git push origin v0.x.y` |
| 150 | + |
| 151 | +## Common Gotchas |
| 152 | + |
| 153 | +- When modifying `Config` struct in `odek.go`, also update `internal/config/loader.go` (CLI flags, env vars, JSON serialization). |
| 154 | +- When adding to KnownProfiles, ensure tests in `odek_test.go` cover the new profile. |
| 155 | +- The Web UI (`cmd/odek/ui/index.html`) is embedded — rebuild the binary to see UI changes. |
| 156 | +- Session files are JSON in `~/.odek/sessions/` — corrupt data is handled gracefully with fallback scan. |
| 157 | +- The Telegram bot uses long-polling (no webhooks), built on stdlib `net/http`. |
| 158 | +- `delegate_tasks` sub-agents have a 120s default timeout. Override via `subagent.timeout_seconds` config. |
0 commit comments