Forge — a terminal-native autonomous coding agent in Go

I’ve been building Forge, a terminal-native autonomous coding agent in Go, as a model-agnostic alternative to Claude Code.I wanted to share it with this community since it’s a fairly Go-idiomatic design.

What it does

You give it a task in plain English. It reads your repo, plans, calls tools, generates a unified diff, and asks for confirmation before applying anything. Standard agent loop, but a few things are different:

Six specialized model roles, not one model doing everything

Every LLM call is tagged with a role and routed independently through Costguard (an LLM gateway I also built):

type ModelRole string

const (
	RolePlanner    ModelRole = "planner"     // reasoning, decides what to do next
	RoleCoder      ModelRole = "coder"       // writes patches
	RoleToolCaller ModelRole = "tool_caller" // intent -> structured tool call
	RoleCompactor  ModelRole = "compactor"   // summarizes on context overflow
	RoleReviewer   ModelRole = "reviewer"    // catches mistakes before patches reach you
)

Each role can point at a different model — e.g. Claude for planning, a cheap local Ollama model for tool-calling, GPT-4 class for code. Unconfigured roles fall back to the planner model, so single-model use still works with zero config:

func (c Config) selectModel(role ModelRole) string {
	switch role {
	case RoleCoder:
		if c.CoderModel != "" {
			return c.CoderModel
		}
	// ...
	}
	return c.PlannerModel
}

Planner → INTENT → tool-caller two-step protocol

The expensive reasoning model never has to emit a structured tool call directly. It emits INTENT: <natural language>, and a second, cheaper model translates that into the actual TOOL:/ARGS: call. This is the part I think is most interesting architecturally, it cleanly separates “deciding what to do” from “formatting it correctly,” This lets you use a powerful model for thinking, and a small local model for turning the result into structured tool calls.

Patch review gate

Before any patch reaches you, a reviewer-role model (can be a stronger model than the one that wrote the code) checks it. Runs even in autonomous mode.

Stdlib-heavy, no Docker dependency for file edits, it edits the working tree directly like Claude Code does.

Repo: GitHub - marcoantonios1/Forge: Terminal-native AI coding agent powered by multiple LLMs. Like Claude Code, but model-agnostic — use local or cloud models via Costguard. · GitHub

Curious what this community thinks of the role-based routing pattern, and whether the INTENT two-step is the right way to split reasoning from structured output, or if there’s a cleaner Go pattern I’m missing.