Skip to content

Latest commit

 

History

History
257 lines (234 loc) · 10.4 KB

File metadata and controls

257 lines (234 loc) · 10.4 KB

Claude Context: mini-agent

Project Overview

mini-agent is a local-first AI CLI agent written in Go. It resolves Ollama first, can fall back to supported remote providers, and provides an interactive REPL (chat), single-shot execution (run), tool management (tool), goal-driven autonomous execution (/goal inside chat), and session persistence (session) via SQLite.

Technology Stack (from go.mod)

Package Purpose
github.com/spf13/cobra CLI framework
github.com/spf13/viper Configuration management
github.com/joho/godotenv .env file loading
gorm.io/gorm + gorm.io/driver/sqlite ORM and SQLite driver
github.com/google/uuid UUID generation for sessions
github.com/fatih/color Terminal colors

Critical Constraints

  1. English Only: All output strings, comments, docs, and variable names must be in English. No exceptions.
  2. Go 1.25.4: Locked. Do not modify go.mod Go version.
  3. Windows-First: Development happens on Windows. Do not assume Unix-only behavior. Use filepath, os.PathSeparator, and cross-platform exec. Prefer PowerShell command execution on Windows.
  4. Lint-Free: go vet, golangci-lint, and staticcheck must pass. No unused variables or imports.
  5. Test-Driven: Every new package or exported function gets unit tests. Mock HTTP and filesystem boundaries.
  6. Git Hooks:
    • pre-commit: go fmt, go vet, golangci-lint run
    • pre-push: go test ./... -race
  7. Release Process:
    • Every published version must update CHANGELOG.md
    • Every published version must use a tag like v0.0.1
    • .github/workflows/release.yml publishes release artifacts only for new matching tags

Architecture Mental Model

User Input -> cmd/ -> agent/ -> mcp/ -> llm/ -> ollama or remote provider
                              |
                              v
                           tools/ (registry + exec)
                              |
                              v
                           storage/ -> db/ -> SQLite
  • LLM Factory: Resolves Ollama-first or OpenAI-compatible remote providers (OpenAI, OpenRouter, Groq, DeepSeek) from flags, env, and saved profiles.
  • Provider Profiles: Persist endpoint, model, encrypted API key, timeout, temperature, extra headers, and raw request options per remote profile.
  • Ollama Client: Plain HTTP client. POST /api/chat with JSON and honor context.Context cancellation.
  • Secrets Manager: Encrypts saved remote provider API keys with a local AES-GCM master key stored under ~/.mini-agent/master.key.
  • MCP Server: Receives messages, attaches tools, calls Ollama. If the response contains tool_calls, executes them via tools.Registry, appends results as tool role messages, and re-calls Ollama. It also accepts plain JSON tool-call fallbacks, caps tool calls per iteration, and stops after repeated tool or validation failures.
  • Tools: run_shell, read_file, write_file, list_dir, search_files, glob_files, git_status, git_diff, run_validation, apply_patch. Each implements the Tool interface.
  • Sandbox Policy: Optional workspace sandboxing can constrain file tools to a configured root and reduce shell execution to allowed read or validation commands.
  • Agent: Manages the REPL loop. Persists every message to SQLite via storage.SessionStore.
  • Goal Manager: Creates persistent goal runs, tracks work items, and coordinates iterative execution until completion or manual stop, including heuristic context selection, bounded repair attempts after failed validation, persisted context visibility in session output, throttled stop polling, and reduced redundant progress writes during execution.
  • Repo Context Selector: Ranks likely-relevant files from the goal text, recent messages, session summary, and git changes before goal execution.
  • Planner: Builds a lightweight execution plan before entering goal mode, including risk level and suggested starting context for normal and repair prompts.
  • Memory: Stores a compact session summary after goal execution.
  • SessionStore: GORM-backed CRUD for Session, Message, GoalRun, and WorkItem, plus provider profile persistence.

How to Modify Code

Adding a New Tool

  1. Create a new file in internal/tools/ (e.g., git.go).
  2. Implement the Tool interface: Name(), Description(), Parameters(), Execute(ctx, args).
  3. Register it in tools.NewRegistry().
  4. Add unit tests in internal/tools/ (mock filesystem or exec).
  5. Run go test ./... and lint.

Adding a New CLI Command

  1. Create cmd/<command>.go.
  2. Use cobra.Command with Run or RunE.
  3. Add init() to register with rootCmd.
  4. Bind persistent flags in cmd/root.go if needed.
  5. Keep business logic in internal/; cmd/ is thin.

Changing the Database Schema

  1. Update internal/models/session.go.
  2. GORM AutoMigrate handles additions, but back up data if renaming columns.
  3. Update internal/storage/session.go if queries change.
  4. Add migration tests if logic is complex.

Changing the Ollama Integration

  1. Modify internal/ollama/client.go.
  2. Ensure ToolDef is the single source of truth (defined only here).
  3. internal/tools/registry.go imports mini-agent/internal/ollama and returns []ollama.ToolDef.
  4. Update mcp/server.go only if the tool-call loop logic changes.

Changing Provider Support

  1. Update internal/llm/ for provider resolution and remote client behavior.
  2. Keep Ollama as the default path unless the user selects another provider.
  3. Store saved provider API keys only through internal/secrets/.
  4. Keep runtime files under ~/.mini-agent.
  5. Keep provider profile schema, CLI flags, and remote request settings aligned.
  6. If sandbox is enabled, keep tool policy, CLI wiring, and prompt wording aligned.

Common Pitfalls

  • Duplicate ToolDef: Never redefine ToolDef in tools/. Import from ollama package.
  • Missing Context: Always pass ctx context.Context down the stack. Respect cancellation and timeouts.
  • English Leak: Do not write Spanish or other languages in error strings or UI output. Use English only.
  • Windows Paths: path.Join is for URLs; filepath.Join is for files.
  • Uncommitted Tests: If you change logic, you must update or add tests.
  • Race Conditions: The agent is currently single-threaded (REPL), but go test -race should still pass.
  • Goal Loops: Goal mode must always respect stop signals and iteration limits, tool-call limits, and consecutive-failure limits.
  • Sandbox Drift: Do not update shell or filesystem tools without checking whether sandbox policy enforcement must also change.
  • Secrets: Never log or print decrypted API keys.
  • Provider Output: provider show and related UX must redact secrets.
  • Patch Safety: Prefer apply_patch for existing files to reduce accidental full-file rewrites.

Testing Strategy

  • Unit tests: Test each tool in isolation with mocked exec.Command or afero (if we add virtual FS).
  • Integration tests: Use a temporary SQLite DB (:memory: or temp file) for storage tests.
  • HTTP tests: Use httptest.Server to mock Ollama responses in ollama/client_test.go.
  • Agent tests: Mock the MCP server and storage to test the REPL loop without real HTTP or DB calls.

File Inventory

mini-agent/
├── .env
├── .github/
│   └── workflows/
│       ├── pages.yml
│       └── release.yml
├── CHANGELOG.md
├── go.mod
├── go.sum
├── lefthook.yml
├── main.go
├── cmd/
│   ├── root.go
│   ├── chat.go
│   ├── run.go
│   ├── tool.go
│   └── session.go
├── internal/
│   ├── config/
│   │   └── config.go
│   ├── db/
│   │   └── db.go
│   ├── llm/
│   │   ├── client.go
│   │   ├── client_test.go
│   │   ├── openai_compatible.go
│   │   └── openai_compatible_test.go
│   ├── goal/
│   │   ├── manager.go
│   │   ├── manager_test.go
│   │   └── types.go
│   ├── context/
│   │   ├── context.go
│   │   ├── context_test.go
│   │   └── ranker.go
│   ├── memory/
│   │   ├── summary.go
│   │   └── summary_test.go
│   ├── models/
│   │   └── session.go
│   ├── secrets/
│   │   ├── manager.go
│   │   └── manager_test.go
│   ├── storage/
│   │   ├── session.go
│   │   └── session_test.go
│   ├── ollama/
│   │   ├── client.go
│   │   └── client_test.go
│   ├── tools/
│   │   ├── registry.go
│   │   ├── shell.go
│   │   ├── shell_test.go
│   │   ├── files.go
│   │   ├── files_test.go
│   │   ├── git.go
│   │   ├── git_test.go
│   │   ├── glob.go
│   │   ├── glob_test.go
│   │   ├── patch.go
│   │   ├── patch_test.go
│   │   ├── validate.go
│   │   └── validate_test.go
│   ├── mcp/
│   │   ├── server.go
│   │   └── server_test.go
│   ├── agent/
│   │   └── agent.go
│   ├── planner/
│   │   ├── planner.go
│   │   ├── planner_test.go
│   │   └── prompt.go
│   └── ui/
│       └── ui.go

Prompting Rules for Claude

When asked to generate code:

  • Generate complete file contents, not diffs, unless explicitly asked for a patch.
  • Include package declaration and all imports.
  • Run goimports-style logic mentally: remove unused imports, group standard library vs third-party.
  • Follow the Windows-first and English-only rules strictly.
  • If a change requires a new dependency, warn the user and justify it.
  • If a change breaks existing tests, update the tests in the same response.
  • If a change touches goal execution, keep /goal, /stop, iteration limits, and validation behavior consistent with the docs.
  • Prefer patch-based edits for existing files and document any repair-loop behavior changes.
  • If a change affects release distribution, update CHANGELOG.md, .github/workflows/release.yml, and the relevant release documentation.
  • Before any published version, prepare a changelog entry and create a version tag such as v0.0.1.