chore: move agent routing to OpenCode Go; add firstmate tooling
- crew-dispatch.json: route crew tasks to OpenCode Go models - opencode/opencode2: pin opencode-go/gpt-6-luna - grok: default to grok-4.5 with high reasoning, permission auto - home.nix: axiTools activation for the *-axi CLIs; crewmate harness opencode; no-mistakes agent list opencode-only
This commit is contained in:
@@ -46,7 +46,7 @@ in
|
|||||||
cc = "claude --dangerously-skip-permissions";
|
cc = "claude --dangerously-skip-permissions";
|
||||||
co = "codex --full-auto";
|
co = "codex --full-auto";
|
||||||
gb = "grok --yolo";
|
gb = "grok --yolo";
|
||||||
# firstmate primary session via OpenCode 2 (isolated config; crewmates = Pi)
|
# firstmate primary session via OpenCode 2 (isolated config; crewmates = OpenCode)
|
||||||
fm = "cd ${firstmateHome} && exec ${home}/.local/bin/oc2";
|
fm = "cd ${firstmateHome} && exec ${home}/.local/bin/oc2";
|
||||||
oc2 = "${home}/.local/bin/oc2";
|
oc2 = "${home}/.local/bin/oc2";
|
||||||
# Sync ~/Music into the beets library on Unraid (requires NAS mounted).
|
# Sync ~/Music into the beets library on Unraid (requires NAS mounted).
|
||||||
@@ -170,10 +170,10 @@ in
|
|||||||
};
|
};
|
||||||
|
|
||||||
# firstmate is a mutable agent distro (self-update, state/, projects/). Clone once;
|
# firstmate is a mutable agent distro (self-update, state/, projects/). Clone once;
|
||||||
# never put it in the Nix store. Seed Pi+herdr defaults only when absent.
|
# never put it in the Nix store. Seed OpenCode+herdr defaults only when absent.
|
||||||
# Do NOT npm install -g here: activation PATH often resolves Nix's npm, which
|
# Do NOT npm install -g here: activation PATH often resolves Nix's npm, which
|
||||||
# cannot write into the store (EACCES). Use Homebrew's node for globals:
|
# cannot write into the store (EACCES). The firstmate companion CLIs (*-axi)
|
||||||
# /opt/homebrew/bin/npm install -g tasks-axi quota-axi no-mistakes gh-axi lavish-axi chrome-devtools-axi
|
# are installed by home.activation.axiTools below via Homebrew's node.
|
||||||
home.activation.firstmate = lib.hm.dag.entryAfter [ "writeBoundary" ] ''
|
home.activation.firstmate = lib.hm.dag.entryAfter [ "writeBoundary" ] ''
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
fm="${firstmateHome}"
|
fm="${firstmateHome}"
|
||||||
@@ -188,11 +188,11 @@ in
|
|||||||
|
|
||||||
# Local gitignored operating choices (do not overwrite captain edits)
|
# Local gitignored operating choices (do not overwrite captain edits)
|
||||||
[ -f "$fm/config/backend" ] || printf 'herdr\n' > "$fm/config/backend"
|
[ -f "$fm/config/backend" ] || printf 'herdr\n' > "$fm/config/backend"
|
||||||
[ -f "$fm/config/crew-harness" ] || printf 'pi\n' > "$fm/config/crew-harness"
|
[ -f "$fm/config/crew-harness" ] || printf 'opencode\n' > "$fm/config/crew-harness"
|
||||||
|
|
||||||
# Crew dispatch profile - source of truth in dotfiles (reproducible across
|
# Crew dispatch profile - source of truth in dotfiles (reproducible across
|
||||||
# machines). Symlinked into firstmate config so a rebuild restores routing.
|
# machines). Symlinked into firstmate config so a rebuild restores routing.
|
||||||
# Crewmates run on Pi + opencode-go/mimo-v2.5-pro (see crew-dispatch.json).
|
# Crew harness and model routing are task-specific in crew-dispatch.json.
|
||||||
ln -sfn "${dotfiles}/home/.config/firstmate/crew-dispatch.json" "$fm/config/crew-dispatch.json"
|
ln -sfn "${dotfiles}/home/.config/firstmate/crew-dispatch.json" "$fm/config/crew-dispatch.json"
|
||||||
|
|
||||||
# Gitea PR helper for local-only mode: after the first mate (opencode)
|
# Gitea PR helper for local-only mode: after the first mate (opencode)
|
||||||
@@ -200,6 +200,33 @@ in
|
|||||||
ln -sfn "${dotfiles}/home/bin/fm-gitea-pr.sh" "$HOME/.local/bin/fm-gitea-pr.sh"
|
ln -sfn "${dotfiles}/home/bin/fm-gitea-pr.sh" "$HOME/.local/bin/fm-gitea-pr.sh"
|
||||||
'';
|
'';
|
||||||
|
|
||||||
|
# Firstmate companion CLIs (*-axi). None is a Homebrew or Nix formula, so
|
||||||
|
# install them through Homebrew's npm. tasks-axi is version-gated by firstmate
|
||||||
|
# (>= 0.2.6 is required before a spawn/teardown automatic backlog transition
|
||||||
|
# will run), so pin it and reinstall on drift; the rest install when absent.
|
||||||
|
home.activation.axiTools = lib.hm.dag.entryAfter [ "writeBoundary" ] ''
|
||||||
|
set -euo pipefail
|
||||||
|
# Activation PATH lacks /opt/homebrew/bin, so npm's `#!/usr/bin/env node`
|
||||||
|
# shebang and the installed shims would fail. Prepend only - replacing PATH
|
||||||
|
# breaks the rest of the HM activation (nix-env, gettext).
|
||||||
|
export PATH="/opt/homebrew/bin:$PATH"
|
||||||
|
npm=/opt/homebrew/bin/npm
|
||||||
|
if [ ! -x "$npm" ]; then
|
||||||
|
echo "axiTools: /opt/homebrew/bin/npm missing (declare node in homebrew.brews)" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
# Pin tasks-axi; reinstall only when the installed version differs.
|
||||||
|
want_tasks_axi="0.2.6"
|
||||||
|
have_tasks_axi="$(tasks-axi --version 2>/dev/null | head -1 | tr -d '[:space:]')"
|
||||||
|
if [ "$have_tasks_axi" != "$want_tasks_axi" ]; then
|
||||||
|
"$npm" install -g "tasks-axi@$want_tasks_axi"
|
||||||
|
fi
|
||||||
|
# Companion CLIs without a firstmate-enforced version floor: install once.
|
||||||
|
for tool in quota-axi gh-axi lavish-axi chrome-devtools-axi; do
|
||||||
|
[ -x "/opt/homebrew/bin/$tool" ] || "$npm" install -g "$tool"
|
||||||
|
done
|
||||||
|
'';
|
||||||
|
|
||||||
# Authorize the SSH key so the phone can log in through the ngrok tunnel.
|
# Authorize the SSH key so the phone can log in through the ngrok tunnel.
|
||||||
# (home-manager 26.05 removed programs.ssh.authorizedKeys; manage the file
|
# (home-manager 26.05 removed programs.ssh.authorizedKeys; manage the file
|
||||||
# here so ~/.ssh is 0700 and authorized_keys is 0600. Public key is not a secret.)
|
# here so ~/.ssh is 0700 and authorized_keys is 0600. Public key is not a secret.)
|
||||||
@@ -236,9 +263,38 @@ in
|
|||||||
"$npm" install -g --allow-scripts=@opencode-ai/cli @opencode-ai/cli@beta
|
"$npm" install -g --allow-scripts=@opencode-ai/cli @opencode-ai/cli@beta
|
||||||
'';
|
'';
|
||||||
|
|
||||||
|
# backpass (kunchenguid/backpass) - gradient descent for agent memory: reads
|
||||||
|
# the transcript stores of the harnesses this config already declares
|
||||||
|
# (claude/codex/pi/opencode/grok), proposes evidence-backed edits to AGENTS.md
|
||||||
|
# and skills, gated by `backpass apply`. Every model call goes through `acpx`
|
||||||
|
# to a harness you already authenticated, so acpx is a hard runtime dep and
|
||||||
|
# must be on PATH. Homebrew node v26 satisfies backpass (>= 22.5) and acpx
|
||||||
|
# (>= 22.13). Neither is a Homebrew formula: install via Homebrew's npm,
|
||||||
|
# never Nix's npm (EACCES on the store). Skip-if-present like opencode2 so a
|
||||||
|
# rebuild never pulls a new version mid-session; refresh manually with
|
||||||
|
# /opt/homebrew/bin/npm update -g backpass acpx
|
||||||
|
home.activation.backpass = lib.hm.dag.entryAfter [ "writeBoundary" ] ''
|
||||||
|
set -euo pipefail
|
||||||
|
# Activation PATH lacks /opt/homebrew/bin, so npm's `#!/usr/bin/env node`
|
||||||
|
# shebang fails with "env: node: No such file or directory". Prepend only -
|
||||||
|
# replacing PATH breaks the rest of the HM activation (nix-env, gettext).
|
||||||
|
export PATH="/opt/homebrew/bin:$PATH"
|
||||||
|
npm=/opt/homebrew/bin/npm
|
||||||
|
if [ ! -x "$npm" ]; then
|
||||||
|
echo "backpass: /opt/homebrew/bin/npm missing (declare node in homebrew.brews)" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
if [ ! -x /opt/homebrew/bin/acpx ]; then
|
||||||
|
"$npm" install -g acpx@latest
|
||||||
|
fi
|
||||||
|
if [ ! -x /opt/homebrew/bin/backpass ]; then
|
||||||
|
"$npm" install -g backpass
|
||||||
|
fi
|
||||||
|
'';
|
||||||
|
|
||||||
# kunchenguid/no-mistakes gate (git push no-mistakes) - declarative install + daemon + global config
|
# kunchenguid/no-mistakes gate (git push no-mistakes) - declarative install + daemon + global config
|
||||||
# Covers every harness declared in Nix: pi (pi-coding-agent), opencode (oc2/fm), grok (grok-build),
|
# Uses OpenCode only for pipeline steps (the opencode-go subscription), by the
|
||||||
# plus claude/codex aspirational (aliases cc/co). Binary lives in ~/.no-mistakes/bin
|
# captain's decision. Binary lives in ~/.no-mistakes/bin
|
||||||
# with symlink ~/.local/bin/no-mistakes (installer default). Do NOT npm install -g no-mistakes
|
# with symlink ~/.local/bin/no-mistakes (installer default). Do NOT npm install -g no-mistakes
|
||||||
# - that npm name is jonathanong's static-analysis tool (shadowing bug fixed 2026-09-21).
|
# - that npm name is jonathanong's static-analysis tool (shadowing bug fixed 2026-09-21).
|
||||||
home.activation.noMistakes = lib.hm.dag.entryAfter [ "writeBoundary" ] ''
|
home.activation.noMistakes = lib.hm.dag.entryAfter [ "writeBoundary" ] ''
|
||||||
@@ -252,14 +308,14 @@ in
|
|||||||
fi
|
fi
|
||||||
curl -fsSL https://raw.githubusercontent.com/kunchenguid/no-mistakes/main/docs/install.sh | sh
|
curl -fsSL https://raw.githubusercontent.com/kunchenguid/no-mistakes/main/docs/install.sh | sh
|
||||||
fi
|
fi
|
||||||
# Ensure global config covers all Nix harnesses (idempotent - only writes if missing or still `agent: auto`)
|
# Ensure global config selects OpenCode (idempotent - only writes if missing or still `agent: auto`)
|
||||||
cfg="$HOME/.no-mistakes/config.yaml"
|
cfg="$HOME/.no-mistakes/config.yaml"
|
||||||
if [ -f "$cfg" ] && grep -qE '^\s*agent:\s*auto\s*$' "$cfg"; then
|
if [ -f "$cfg" ] && grep -qE '^\s*agent:\s*auto\s*$' "$cfg"; then
|
||||||
tmp="$(mktemp)"
|
tmp="$(mktemp)"
|
||||||
awk '
|
awk '
|
||||||
/^\s*agent:\s*auto\s*$/ {
|
/^\s*agent:\s*auto\s*$/ {
|
||||||
print "# Managed by dotfiles/home.nix home.activation.noMistakes";
|
print "# Managed by dotfiles/home.nix home.activation.noMistakes";
|
||||||
print "agent: [pi, opencode, grok, claude, codex]";
|
print "agent: [opencode]";
|
||||||
next
|
next
|
||||||
}
|
}
|
||||||
{ print }
|
{ print }
|
||||||
@@ -267,10 +323,9 @@ in
|
|||||||
fi
|
fi
|
||||||
if [ ! -f "$cfg" ]; then
|
if [ ! -f "$cfg" ]; then
|
||||||
mkdir -p "$(dirname "$cfg")"
|
mkdir -p "$(dirname "$cfg")"
|
||||||
printf 'agent: [pi, opencode, grok, claude, codex]\n' > "$cfg"
|
printf 'agent: [opencode]\n' > "$cfg"
|
||||||
fi
|
fi
|
||||||
# Ensure daemon running (launchd on macOS)
|
# Ensure daemon running (launchd on macOS)
|
||||||
"$bin" daemon restart >/dev/null 2>&1 || "$bin" daemon start >/dev/null 2>&1 || true
|
"$bin" daemon restart >/dev/null 2>&1 || "$bin" daemon start >/dev/null 2>&1 || true
|
||||||
'';
|
'';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,20 +1,20 @@
|
|||||||
{
|
{
|
||||||
"rules": [
|
"rules": [
|
||||||
{
|
{
|
||||||
"when": "pure-function implementation with tests (indicators, slots, seasonal wiring, repositories)",
|
"when": "Well-specified implementation with clear acceptance criteria: pure functions, tests, repositories, adapters, or external-fetch integration.",
|
||||||
"use": [{ "harness": "pi", "model": "opencode-go/mimo-v2.5-pro" }],
|
"use": [{ "harness": "opencode", "model": "opencode-go/deepseek-v4.1-flash", "provider": "opencode-go" }],
|
||||||
"why": "MiMo V2.5 Pro (opencode-go, 1M ctx) produces clean correct code; flat-rate sub so $0 marginal cost. Pi drives it in an isolated worktree."
|
"why": "DeepSeek V4.1 Flash is the default OpenCode Go implementation worker; it is fast, economical, and strong on agentic coding tasks."
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"when": "adapter or external-fetch integration (COT, seed backfills, vendor seams)",
|
"when": "UI work where supplied screenshots or other image context materially affect the implementation or verification.",
|
||||||
"use": [{ "harness": "pi", "model": "opencode-go/mimo-v2.5-pro" }],
|
"use": [{ "harness": "opencode", "model": "opencode-go/glm-5.3-flash", "provider": "opencode-go" }],
|
||||||
"why": "Pattern-following work against existing adapter contracts; MiMo handles iterative fetch/debug loops."
|
"why": "GLM-5.3-Flash is the Go worker with image input; use it when visual context matters."
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"when": "frontend page or tRPC wiring (UI panels, router procedures, client exposure)",
|
"when": "Ambiguous investigation, difficult debugging, architectural tradeoffs, or broad changes with high uncertainty or blast radius.",
|
||||||
"use": [{ "harness": "pi", "model": "opencode-go/mimo-v2.5-pro" }],
|
"use": [{ "harness": "opencode", "model": "opencode-go/gpt-6-luna", "provider": "opencode-go" }],
|
||||||
"why": "Mechanical wiring against existing components/routers; the contract carries the specialization."
|
"why": "Reserve GPT-6 Luna for work that benefits from stronger reasoning than the fast implementation tier."
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"default": [{ "harness": "pi", "model": "opencode-go/mimo-v2.5-pro" }]
|
"default": [{ "harness": "opencode", "model": "opencode-go/deepseek-v4.1-flash", "provider": "opencode-go" }]
|
||||||
}
|
}
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"$schema": "https://opencode.ai/config.json",
|
"$schema": "https://opencode.ai/config.json",
|
||||||
"model": "opencode/muse-spark-1.2-contributor-free",
|
"model": "opencode-go/gpt-6-luna",
|
||||||
"instructions": ["AGENTS.md"],
|
"instructions": ["AGENTS.md"],
|
||||||
"provider": {
|
"provider": {
|
||||||
"omlx": {
|
"omlx": {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"$schema": "https://opencode.ai/config.json",
|
"$schema": "https://opencode.ai/config.json",
|
||||||
"model": "opencode/muse-spark-1.2-contributor-free",
|
"model": "opencode-go/gpt-6-luna",
|
||||||
"autoupdate": false,
|
"autoupdate": false,
|
||||||
"providers": {
|
"providers": {
|
||||||
"omlx": {
|
"omlx": {
|
||||||
|
|||||||
@@ -7,7 +7,8 @@ name = "xAI Official"
|
|||||||
git = "https://github.com/xai-org/plugin-marketplace.git"
|
git = "https://github.com/xai-org/plugin-marketplace.git"
|
||||||
|
|
||||||
[models]
|
[models]
|
||||||
default = "qwen"
|
default = "grok-4.5"
|
||||||
|
default_reasoning_effort = "high"
|
||||||
|
|
||||||
[model.qwen]
|
[model.qwen]
|
||||||
model = "Jundot/Qwen3.6-35B-A3B-oQ4-mtp"
|
model = "Jundot/Qwen3.6-35B-A3B-oQ4-mtp"
|
||||||
@@ -24,7 +25,7 @@ max_completion_tokens = 65536
|
|||||||
theme = "rosepine"
|
theme = "rosepine"
|
||||||
max_thoughts_width = 120
|
max_thoughts_width = 120
|
||||||
fork_secondary_model = "grok-build"
|
fork_secondary_model = "grok-build"
|
||||||
permission_mode = "always-approve"
|
permission_mode = "auto"
|
||||||
yolo = false
|
yolo = false
|
||||||
compact_mode = false
|
compact_mode = false
|
||||||
|
|
||||||
@@ -32,4 +33,4 @@ compact_mode = false
|
|||||||
installer = "internal"
|
installer = "internal"
|
||||||
|
|
||||||
[privacy]
|
[privacy]
|
||||||
privacy_banner_acked = "2026-09-21T16:02:21Z"
|
privacy_banner_acked = "2026-09-24T02:33:29Z"
|
||||||
|
|||||||
Reference in New Issue
Block a user