Skip to content
This repository was archived by the owner on Apr 19, 2026. It is now read-only.

Commit 79f00f0

Browse files
jpleva91claude
andcommitted
feat: replace Crush with Aider as local model driver
Crush doesn't work with local models (OpenAI-compat shim loses tool calls). Aider has native Ollama support and actually executes tools. - shellforge run aider "prompt" — headless with --yes-always --no-git - Setup wizard: pip3 install aider-chat (5 seconds, not 5 minutes) - Status page: shows Aider instead of Crush - Passes OLLAMA_MODEL to Aider automatically Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 0758e94 commit 79f00f0

2 files changed

Lines changed: 22 additions & 54 deletions

File tree

cmd/shellforge/main.go

Lines changed: 21 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ cmdReport(repo)
4747
case "run":
4848
if len(os.Args) < 3 {
4949
fmt.Fprintln(os.Stderr, "Usage: shellforge run <driver> \"prompt\"")
50-
fmt.Fprintln(os.Stderr, "Drivers: claude, copilot, codex, gemini, crush")
50+
fmt.Fprintln(os.Stderr, "Drivers: aider, claude, copilot, codex, gemini")
5151
os.Exit(1)
5252
}
5353
driver := os.Args[2]
@@ -272,60 +272,22 @@ fmt.Println()
272272
steps++
273273
fmt.Printf("── Step %d/%d: Agent drivers ──\n", steps, total)
274274

275-
// On Mac: offer Crush (local models). On server: skip Crush, show API drivers.
275+
// On Mac/GPU: offer Aider (local models via Ollama). On server: skip, show API drivers.
276276
if !isServer {
277-
if _, err := exec.LookPath("crush"); err != nil {
278-
fmt.Println(" CrushGo AI coding agent with AgentGuard governance (local models)")
279-
fmt.Print(" Install Crush? [Y/n] ")
277+
if _, err := exec.LookPath("aider"); err != nil {
278+
fmt.Println(" Aider — AI coding agent with native Ollama support (local models)")
279+
fmt.Print(" Install Aider? [Y/n] ")
280280
if confirm(reader) {
281-
fmt.Println(" → Installing Crush (AgentGuardHQ fork with governance)...")
282-
// Ensure Go is installed (needed to build Crush)
283-
if _, err := exec.LookPath("go"); err != nil {
284-
fmt.Println(" → Go not found — installing...")
285-
if runtime.GOOS == "darwin" {
286-
run("brew", "install", "go")
287-
} else {
288-
run("sh", "-c", "curl -fsSL https://go.dev/dl/go1.23.0.linux-amd64.tar.gz | sudo tar -C /usr/local -xz && sudo ln -sf /usr/local/go/bin/go /usr/local/bin/go")
289-
}
290-
if _, err := exec.LookPath("go"); err != nil {
291-
fmt.Println(" ⚠ Go install failed. Install manually: brew install go")
292-
fmt.Println(" Then re-run: shellforge setup")
293-
}
294-
}
295-
// Clone, build, and install our governed fork
296-
crushDir := filepath.Join(os.TempDir(), "shellforge-crush-install")
297-
os.RemoveAll(crushDir)
298-
run("git", "clone", "--depth", "1", "https://github.com/AgentGuardHQ/crush.git", crushDir)
299-
buildCmd := exec.Command("go", "build", "-o", "crush", ".")
300-
buildCmd.Dir = crushDir
301-
buildCmd.Stdout = os.Stdout
302-
buildCmd.Stderr = os.Stderr
303-
if err := buildCmd.Run(); err != nil {
304-
fmt.Printf(" ⚠ Build failed: %s\n", err)
305-
fmt.Println(" Requires Go 1.22+. Check: go version")
306-
} else {
307-
// Move binary to /usr/local/bin (always in PATH)
308-
crushBin := filepath.Join(crushDir, "crush")
309-
dest := "/usr/local/bin/crush"
310-
cpCmd := exec.Command("cp", crushBin, dest)
311-
if err := cpCmd.Run(); err != nil {
312-
// Try with sudo
313-
fmt.Println(" → Need permissions to install to /usr/local/bin...")
314-
run("sudo", "cp", crushBin, dest)
315-
run("sudo", "chmod", "+x", dest)
316-
}
317-
if _, err := exec.LookPath("crush"); err == nil {
318-
fmt.Println(" ✓ Crush installed to /usr/local/bin/crush")
319-
fmt.Println(" ✓ AgentGuard governance built in")
281+
fmt.Println(" → Installing Aider...")
282+
run("pip3", "install", "aider-chat")
283+
if _, err := exec.LookPath("aider"); err == nil {
284+
fmt.Println(" ✓ Aider installed")
320285
} else {
321-
fmt.Println(" ⚠ Install failed. Try manually:")
322-
fmt.Printf(" sudo cp %s /usr/local/bin/crush\n", crushBin)
323-
}
286+
fmt.Println(" ⚠ Install failed — try: pip3 install aider-chat")
324287
}
325-
os.RemoveAll(crushDir)
326288
}
327289
} else {
328-
fmt.Println(" ✓ Crush installed (local model driver)")
290+
fmt.Println(" ✓ Aider installed (local model driver)")
329291
}
330292
}
331293

@@ -534,11 +496,17 @@ var drivers = map[string]driverConfig{
534496
hasHooks: false,
535497
initHint: "agentguard gemini-init",
536498
},
537-
"crush": {
538-
binary: "crush",
539-
buildCmd: func(p string) []string { return []string{"--yolo", "run", "--quiet", p} },
499+
"aider": {
500+
binary: "aider",
501+
buildCmd: func(p string) []string {
502+
model := os.Getenv("OLLAMA_MODEL")
503+
if model == "" {
504+
model = ollama.Model
505+
}
506+
return []string{"--model", "ollama/" + model, "--yes-always", "--no-git", "--message", p}
507+
},
540508
interactive: []string{},
541-
hasHooks: true,
509+
hasHooks: false,
542510
initHint: "",
543511
},
544512
}

cmd/shellforge/status.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ func cmdStatusFull() {
6363
desc string
6464
install string
6565
}{
66-
{"crush", "crush", "Charm AI coding agent (Go, TUI + headless)", "brew install charmbracelet/tap/crush"},
66+
{"aider", "aider", "AI coding agent with native Ollama support", "pip3 install aider-chat"},
6767
{"claude", "claude", "Claude Code CLI", "npm i -g @anthropic-ai/claude-code"},
6868
{"copilot", "github-copilot-cli", "GitHub Copilot CLI", "gh extension install github/gh-copilot"},
6969
{"codex", "codex", "OpenAI Codex CLI", "npm i -g @openai/codex"},

0 commit comments

Comments
 (0)