Architecture#
- Language: Go 1.25+, 100% Go
- Size: 33 packages, ~294 Go files, ~100K LOC
- Entry point:
cmd/gokin/main.go(Cobra CLI) - Orchestrator:
internal/app/app.go(~1200 LOC)
Package Structure#
internal/
├── app/ # Orchestrator (builder, queue, signals, message_processor)
├── agent/ # Multi-agent system (delegation, reflection, tree planning)
├── tools/ # AI tool registry (54 tools, 10 tool sets)
├── ui/ # TUI on Bubble Tea (themes, progress, command palette)
├── client/ # API clients (Gemini, Gemini OAuth, Anthropic, Ollama)
├── config/ # Configuration (YAML, 22+ sections, provider registry)
├── chat/ # Session and history management
├── permission/ # Permission system (RiskLow/Medium/High)
├── plan/ # Task planning and execution
├── context/ # Context management and summarization
├── memory/ # Memory, learning, persistence
├── security/ # Security (sandbox, command/SSH validation)
├── semantic/ # Semantic search with embeddings
├── mcp/ # Model Context Protocol (external servers)
├── router/ # Smart request routing
├── format/ # Formatting utilities (Duration, Bytes)
├── fileutil/ # Atomic file transactions
├── hooks/ # Pre/post-tool hooks
├── auth/ # OAuth authorization (Gemini)
├── update/ # Self-update system with rollback
├── audit/ # Audit logging
├── cache/ # Result caching
├── ratelimit/ # API rate limiting
├── watcher/ # File change monitoring
├── tasks/ # Background tasks (bash shells)
├── commands/ # Slash commands
├── logging/ # Structured logging (slog)
├── git/ # Git integration
├── highlight/ # Syntax highlighting
├── ssh/ # SSH validation
├── robustness/ # Error recovery, circuit breaker
└── undo/ # Undo stackKey Dependencies#
| Library | Version | Purpose |
|---|---|---|
| Cobra | v1.10.2 | CLI framework |
| Bubble Tea | v1.3.10 | TUI framework (charmbracelet) |
| genai SDK | v1.42.0 | Google Gemini integration |
| Glamour | v0.10.0 | Markdown rendering in terminal |
| Lipgloss | — | TUI styling |
| fsnotify | — | File watching |
Design Patterns#
Registry#
Tool registration and lookup by name. Lazy loading via ToolEntry.
// internal/tools/registry.go
type Registry struct {
tools map[string]Tool
}Builder#
DI container for assembling application dependencies.
// internal/app/builder.go — selectToolSets, client creation, wiringFactory#
Client creation based on provider/model.
// internal/client/factory.go
func NewClient(ctx, cfg, modelID) (Client, error)Strategy#
Delegation strategy and MCP transport.
// internal/agent/delegation.go
type DelegationStrategy struct { ... }Observer#
Progress callbacks and tool activity notifications.
Command#
Slash commands with metadata (category, priority, platform, requires).
Snapshot-then-async#
Serialize data under lock, write to file without lock:
dm.mu.Lock()
snapshot, _ := dm.save() // Serialize under lock
dm.mu.Unlock()
go dm.writeSnapshot(snapshot) // Async write without lockConcurrency#
RWMutex#
All client setters/getters are protected by sync.RWMutex:
// Setters — under Lock()
func (c *Client) SetModel(m string) {
c.mu.Lock()
defer c.mu.Unlock()
c.model = m
}
// Getters — under RLock()
func (c *Client) GetModel() string {
c.mu.RLock()
defer c.mu.RUnlock()
return c.model
}Snapshot-then-async#
Mutable data is copied under lock, writes happen asynchronously.
Semaphore#
Concurrency limiting (up to 5 agents, up to 5 tools, up to 3 token count requests).
WaitGroup#
Parallel execution of plan steps and MCP connections.
Channels#
donechannels withdoneOnce.Do(close(done))for safe shutdowncmdDonebefore panic recovery to prevent hanging
Creating a Custom Tool#
1. Implement the Tool interface#
// internal/tools/my_tool.go
package tools
type MyTool struct {
workDir string
}
func (t *MyTool) Name() string {
return "my_tool"
}
func (t *MyTool) Description() string {
return "Description of my tool"
}
func (t *MyTool) Declaration() *genai.FunctionDeclaration {
return &genai.FunctionDeclaration{
Name: "my_tool",
Description: "Description of my tool",
Parameters: &genai.Schema{
Type: genai.TypeObject,
Properties: map[string]*genai.Schema{
"input": {
Type: genai.TypeString,
Description: "Input parameter",
},
},
Required: []string{"input"},
},
}
}
func (t *MyTool) Execute(ctx context.Context, args map[string]any) (ToolResult, error) {
input, _ := args["input"].(string)
// ... logic ...
return ToolResult{Output: "result"}, nil
}
func (t *MyTool) Validate(args map[string]any) error {
if _, ok := args["input"].(string); !ok {
return fmt.Errorf("input is required")
}
return nil
}2. Register in the registry#
// internal/tools/registry.go — add to DefaultRegistry or DefaultLazyRegistry3. Add to a tool set#
// internal/tools/registry.go — add to the appropriate toolSetDefinitions4. Add the declaration#
// internal/tools/declarations.go — add FunctionDeclaration5. Assign a safety level#
// internal/tools/safety.go — add to the appropriate levelCode Style#
| Category | Style |
|---|---|
| Exported names | CamelCase: NewRegistry, Tool |
| YAML/JSON tags | snake_case: yaml:"api_key" |
| Receivers | 1-2 chars: r *Registry, c *Config |
| Mutexes | mu sync.RWMutex — setters under Lock, getters under RLock |
| Errors | fmt.Errorf("context: %w", err) |
| Tests | _test.go in the same package |
Development Commands#
# Compile all packages
go build ./...
# Static analysis
go vet ./...
# Tests with race detection
go test -race -coverprofile=coverage.out ./...
# Dependencies
go mod download && go mod tidy
# Build binary
go build -o gokin ./cmd/gokin
# Build with version
go build -ldflags "-X main.version=1.0.0" -o gokin ./cmd/gokinCI/CD#
- Automated tests on every PR
- Cross-platform builds: linux/darwin/windows × amd64/arm64
- Releases on
v*tags - Coverage via codecov
Key Files#
| File | LOC | Purpose |
|---|---|---|
app/app.go | ~1200 | Main orchestrator, message processing loop |
app/builder.go | — | DI container, selectToolSets |
app/message_processor.go | — | Model message processing |
agent/agent.go | — | Agent struct, Run(), execution, delegation |
agent/delegation.go | — | DelegationStrategy, rules, scoring |
agent/tree_planner.go | — | Task decomposition into tree |
tools/registry.go | — | Registry, ToolSet, FilteredGeminiTools |
tools/executor.go | — | Tool call execution, streaming |
tools/declarations.go | — | All 54 tool declarations |
client/factory.go | — | NewClient(), pool, fallback |
client/model_profiles.go | — | ModelProfile for Ollama |
config/provider_registry.go | — | 7 providers, models, validation |
Contributing#
- Fork the repository
- Create a branch:
git checkout -b feature/my-feature - Ensure it compiles:
go build ./... - Static analysis:
go vet ./... - Tests:
go test -race ./... - Commit and PR