18 Commits
Author SHA1 Message Date
connor b4bc5e1031 opencode: SearXNG search MCP, LSP tool, Gitea MCP in oc-local
searxng-mcp.py is a stdlib-only stdio MCP server with one web_search tool
against search.rcjohnstone.com. It is in both profiles and asks first on
oc-work.

lsp: true in opencode.json, and the launcher sets
OPENCODE_EXPERIMENTAL_LSP_TOOL and OPENCODE_DISABLE_LSP_DOWNLOAD.

The launcher adds gitea-mcp to oc-local through OPENCODE_CONFIG_CONTENT when
the binary and GITEA_MCP_TOKEN exist, limited to 15 tools.
gitea_issue_write asks.
2026-11-02 11:16:08 -05:00
connor b4ced1c649 opencode: track tui.json with attention notifications and sounds off 2026-11-02 10:43:45 -05:00
connor 275a5bfb2b opencode: two profiles, per-profile permissions, shared agent prompts
oc-work: local models only on the local key, edits and most commands ask,
loads instructions/work.md. oc-local (also oc, opencode): every model,
defaults to qwen3.8-flash-next-iq3s-med, edits and commands run except
destructive and outward-facing ones. On sctfw004 oc-local presents the work
key. personal.json and work-strict.json removed.

Agents: drop variant, which has no effect on LiteLLM models. dev takes its
permissions from the profile. The read-only agents deny redirects and the
write/exec flags of allowed commands, swap find for fd, and only allow
listing forms of git branch. review defaults to the uncommitted diff.

CLAUDE.md: add the comment, process and shell-tool rules from the laptop's
AGENTS.md, and note that OpenCode reads this file.
2026-11-02 10:34:38 -05:00
Connor Johnstone 7ad155c4b2 Merge branch 'main' of ssh://git.rcjohnstone.com:2222/connor/dotfiles 2026-11-02 10:02:52 -05:00
Connor Johnstone 631987c62d Updates 2026-11-02 09:58:48 -05:00
connor 0a42f1547f Several updates at once 2026-11-02 09:58:14 -05:00
connor 6b9b1697f2 opencode: remove oh-my-openagent from all profiles
Drops the plugin entry and the agent/* model aliases, sets plain default
models, and removes the OMO roster swap from opencode.zsh.
2026-10-29 10:29:34 -04:00
connor 3fb10dd4c3 opencode: unpin the work profile's agents from gpt-5.6-terra-low 2026-10-29 10:17:39 -04:00
connor 786ce562be opencode: add qwen3.8-flash-next to the work profile
Served by a rented MI325X through mainframe's LiteLLM; only answers while
a golden_image session is up.
2026-10-28 19:53:08 -04:00
Connor Johnstone 0943d99465 Update 2026-09-29 16:24:41 -04:00
connorandClaude Opus 5 e25bb71fb7 opencode: local agents to qwen3.8-27b-gsq-s at MEDIUM reasoning
dev, architect, review, duck and brainstorm move from
litellm/muse-glimmer-30b-low to litellm/qwen3.8-27b-gsq-s-med, in both the
local-only and personal profiles. Glimmer's model entries are left in place so
reverting is a one-line change.

⚠ MEDIUM, not low -- do not "align" this with the -low convention Glimmer uses.
Qwen's own model card: "lower reasoning effort does not always reduce overall
task completion time" on multi-turn agentic work, because insufficient analysis
causes more failed actions and retries, raising latency AND total tokens. The
low-effort result that justifies muse-glimmer-30b-low was measured on Glimmer
and does not transfer.

⚠ The key is reasoning_effort, NOT Glimmer's reasoning_strength. The wrong key
is dropped by kwarg filtering before it reaches the template, returns 200, and
silently leaves the model at its default -- which for qwen3.8 is xhigh. Levels
are low / medium / xhigh; there is no `high`.

Verified the control actually moves rather than merely being accepted:
171 reasoning tokens at low against 430 at medium on one prompt.

Requires qwen3.8-27b-gsq-s-med in ~/config/litellm/config.yaml (untracked;
snapshot at config.yaml.pre-qwen38low).

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FZomrX5fYmPYLusxcXTwvq
2026-09-29 11:32:37 -04:00
connor 14aee0c1e4 opencode: cap the ChatGPT route at 272k and run work agents at low effort
The ChatGPT subscription meters on TOKENS, not messages. OpenAI moved to
token-based accounting and states plainly that "a longer task can use more of
your allowance than a short task, so a fixed number of messages is not a
reliable measure of remaining usage". On that plan the declared context IS
the budget.

Reverts chatgpt/* and agent/*-gpt-5.x from 1,050,000 back to 272,000 in all
three profiles. Raising them to the API's published figure was correct for
capability and wrong for cost: measured over 450 requests, chatgpt/gpt-5.6-
terra averaged 128,395 prompt tokens against 374 completion -- a 343:1 ratio
-- and peaked at 249,647, i.e. sessions grew until they hit the declared
ceiling and compacted there. Quadrupling the ceiling quadruples the room they
grow into, and every turn re-sends the whole context. 272,000 also matches
Codex's own documented context.

⚠ THE LESSON FROM THE LOCAL TIER DOES NOT TRANSFER. Declaring the true
context is strictly right for a local model, where context is free -- that
fix took muse-glimmer-30b from 15/24 to 21/24. On a metered subscription the
same change is a bill. Same edit, opposite sign, and the distinguishing
question is who pays per token.

Also points dev/architect/review/duck/brainstorm at a new
chatgpt/gpt-5.6-terra-low alias, which pins reasoning_effort server-side.
GPT-5.6 defaults to MEDIUM when effort is omitted, and nothing anywhere in
these configs set it, so every work agent has been running at medium. The
hypothesis being tested is not that this saves the ~374 completion tokens
directly, but that less reasoning means fewer tool calls, fewer turns, and
therefore less context re-transmission -- which is where the tokens actually
go.

⚠ THAT HYPOTHESIS IS UNVERIFIED, and so is whether the parameter arrives at
all. LiteLLM documents dropping reasoning_effort from gpt-5.4-and-newer
requests that carry tools, which is every agentic request; this route goes
through the Responses transformer, which may exempt it. A dropped param
returns a normal 200 and changes nothing. A synthetic A/B was run and was
INCONCLUSIVE: the fixture was too easy, reasoning came back 11 tokens and 0
in the two arms, so there was no signal to compare, and low made MORE tool
calls (9 vs 8) at n=1. Real sessions will settle it -- watch completion_
tokens in the spend log against the 374 baseline.

OMO agents are untouched: they are defined in ~/.omo/omo.jsonc, not here.
personal.json's five stay on muse-glimmer-30b-low from the local trial.
2026-09-23 10:14:16 -04:00
connor 40f6cba599 opencode: dev/architect/review/duck/brainstorm on Muse Glimmer
Adds muse-glimmer-30b and muse-glimmer-30b-low to the local and personal
profiles, and points the five named agents at the -low alias.

-low, not the bare alias, because that is the configuration llmbench
actually measured: 15/24 tests_pass on the real suite at reasoning_strength
low, the best any local model has scored there. The bare alias runs at
Glimmer's default, which is its HIGHEST reasoning setting and cannot be
turned off -- measured 906 completion tokens for a one-line riddle against
360 at low. Both are declared, so switching is a model change, not an edit.

Context is 131072, from llama-swap's own `-c`.

These agents already exist in work.json/work-strict.json on gpt-5.6-terra
and are untouched there; local and personal had no agent block at all, so
this is additive.
2026-09-22 10:10:55 -04:00
connorandClaude Opus 5 89c6db1cfb opencode: link the guard config, and turn off native Plan Mode
Two things, one of them overdue.

1. ~/.config/opencode/opencode.json is now dotbot-linked on mainframe and
   sctfw004. It has lived in the repo since August while being linked
   NOWHERE -- each machine had a hand-placed copy and nothing checked they
   agreed, or that the Zen guard was there at all. That file is what stops a
   bare `opencode` falling back to built-in providers including OpenCode Zen,
   which is under a ToS block. An unverified guard is not a guard.

2. It carries `agent.plan.disable: true` and `permission.plan_enter: deny`.
   opencode's native Plan Mode was activating unbidden and taking sessions
   read-only with "Plan mode is active ... This supersedes any other
   instructions you have received."

⚠ (2) IS A PREFERENCE, NOT A FIX. Remove those two keys to restore Plan Mode.

⚠ This is NOT OMO, despite looking like it. OMO's agents carry only
description/model/tools -- there is no keyword or prompt-text trigger
anywhere in ~/.omo/omo.jsonc. `plan` is native to opencode. Verified:
`agent list` shows plan gone under the local profile, and plan_enter
resolving to deny on `build` under personal, where the OMO plugin re-adds
plan as a subagent.

⚠ Turning OMO off would NOT have fixed this and WOULD have broken the
default model. personal.json defaults to litellm/agent/atlas-glm-5.3, and
that alias does not exist in LiteLLM -- measured, it returns 400, while
local/librarian returns 200. The agent/* names live only in the opencode
config and the OMO plugin rewrites them at request time. Disabling OMO needs
`model`/`small_model` repointed in the same change. `"plugin": []` in the
base does not disable it either; the profile wins on that key.

Applies to mainframe and sctfw004 only -- system76 and nas link no opencode
config at all.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01E9UH1zGZZtA9yhohmQrcT6
2026-09-21 22:13:40 -04:00
connorandClaude Opus 5 4e3a0d6ccc opencode: context limits from vendor docs, not inherited guesses
Checked every hosted entry against published documentation 2026-09-21. There
were errors in BOTH directions, and the overstatements are the dangerous
half -- an understated limit wastes tokens, an overstated one is a hard API
rejection partway through a session.

  anthropic/claude-haiku-4-5   1,000,000 ->   200,000   OVERSTATED 5x
  openai/gpt-5.6-sol             200,000 -> 1,050,000
  openai/gpt-5.5                 200,000 -> 1,050,000
  openai/gpt-5.4                 200,000 -> 1,050,000
  openai/gpt-5.4-mini            200,000 -> 1,050,000
  chatgpt/* (4 aliases)          272,000 -> 1,050,000
  agent/*-gpt-5.x (11 aliases)   272,000 -> 1,050,000
  agent/*-glm-5.3 (4 aliases)    150,000 ->   200,000   deliberate cap
  anthropic/claude-{opus,sonnet}-5           unchanged, already correct

Haiku is the one that mattered. Opus 5 and Sonnet 5 really are 1M, the whole
Anthropic block was set to 1M, and Haiku inherited a limit five times its
real 200k. Opencode would have grown a session past the ceiling and the API
would have refused it.

⚠ glm-5.3 is capped at 200,000 BY CHOICE. Its real maximum is 1M. GLM bills
per input token and cost on this stack tracks context size and cache-read
volume more than model choice, so the cap is budget control, not ignorance.
Do not "correct" it upward against the docs. This is the one place where a
declared limit below the vendor maximum is intentional.

⚠ chatgpt/* now carries the API's 1,050,000, but OpenAI does not publish a
context limit for ChatGPT-plan routing and it has historically been far
below the API's. This is deliberately optimistic and being watched for a
crash; if long sessions start failing, that is the first thing to lower.

Left alone for want of evidence, not because they are right:
openai/gpt-5.3-codex (200,000), agent/librarian-glm-5.3-flash (128,000),
agent/sisyphus-junior-glm-5.3-flash (150,000). Raising an unconfirmed limit
risks the Haiku failure mode, so these stay until measured.

Unrelated but found while checking: LiteLLM declares kimi/kimi-k2.7-code at
272,000 against a published 262,144. Overstated by ~10k.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01E9UH1zGZZtA9yhohmQrcT6
2026-09-21 22:01:33 -04:00
connorandClaude Opus 5 f9cfab6221 opencode: declare the context these models actually serve
Every local model was declared at 32768 (16384 for the OMO local aliases)
regardless of what llama-swap is configured to serve. gpt-oss-20b runs with
`-c 65536`, so opencode was compacting at half the real window -- and
local/librarian and local/explore, which both route to gpt-oss-20b, at a
quarter of it.

Compaction is not free and it is not neutral. Measured on mainframe
2026-09-21, one agent session against a model told it had 32k when it had
131k: four cache-cold prefills, and 780 seconds spent after a working fix
re-reading the same forty lines, because each compaction discarded the memory
of having already verified it. Reasoning spend per step went from 2-5 tokens
to 1739. The model was not confused; it had been made to forget.

Values are llama-swap's own `-c`:

  gpt-oss-20b       65536    (was 32768)
  local/librarian   65536    (was 16384 / 32768)
  local/explore     65536    (was 16384 / 32768)
  qwen3-coder-30b   32768    unchanged, already correct
  gemma3-12b        32768    unchanged, already correct

The hosted entries were already right and are untouched.

⚠ These are hand-maintained and llama-swap's config is the source of truth.
If a `-c` changes there, change it here. llmbench now derives the same
numbers by parsing that file, and raises rather than guessing when an alias
is unknown -- a wrong context limit produces plausible numbers instead of an
error, which is how this went unnoticed.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01E9UH1zGZZtA9yhohmQrcT6
2026-09-21 21:51:51 -04:00
Connor Johnstone f38ffc6dbd some updates for the laptop paths, mostly 2026-09-15 15:27:53 -04:00
connor e6644d0616 Rebuild dotfiles as one branch with per-host layers
Replaces the previous repo, which had split into two histories that never
met (mainframe on a dead GitLab remote, the laptops on Gitea) with 146
dirty files across three machines and the NAS never enrolled at all.

Branch-per-machine is gone. One main, with host differences expressed as
small files under hosts/<hostname>/ rather than as branches, so there is
nothing to merge. The reconciled zsh layer reduces 15-33 line forks to
1-7 effective lines per host; distro differences (oh-my-zsh prefix,
syntax-highlighting path, fd vs fdfind) are probed in common/ instead.

Fresh history: the old one carried six plaintext credentials, 45 MB of
mail caches, browser caches and vendored binaries. 5,096 tracked files
and 144 MB become 462 files and 2.6 MB. The .gitignore is now an
allowlist, which is what keeps that true.

Root cause of the rot: ~/.local/bin was a symlink to scripts/ with GOPATH
inside it, so every go install wrote into version control (2.2 GB on the
work laptop). PATH now points at the repo instead of the reverse.

Also: Hyprland replaces sway and is sourced in two halves so $browser is
defined before use; singleton automations carry ConditionHost= alongside
host-layer-only placement; ddns moves from cron to a guarded timer;
package manifests and pkg-snapshot/pkg-restore replace the X11-era
install_scripts/; networkmanager-dmenu added to system76 (the binding
always existed, the package never did).
2026-09-14 14:24:37 -04:00