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.
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.
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
copilot has been commented out on every machine with "deliberately off". This
is what replaces it: minuet-ai in virtual-text mode against qwen3-coder-30b on
mainframe's 3060. Nothing leaves the LAN -- llm.rcjohnstone.com has no public
A record, uses the internal CA, and Caddy source-IP gates it.
⚠ Route is /v1/completions, NOT /infill. Measured through the proxy:
/v1/completions returns 200 with FIM tokens in a raw prompt, /infill is 404
because LiteLLM does not expose it. llama.vim wants /infill, which would mean
talking to llama-server directly and bypassing the virtual key -- and on the
work laptop that key IS the policy boundary making Anthropic and PRC models
403. Not worth routing around for an editor plugin.
⚠ max_tokens is 32 on purpose. Measured on the real path at 48: `def add` came
back with `sub` and `mul` attached, so most of the latency was spent generating
text that would be discarded. Stop tokens include a blank line for the same
reason.
⚠ Expect occasional multi-second pauses: llama-swap is -np 1 with a ttl, so a
completion after another model was used pays a full reload. ~10 s cold,
0.7-1.3 s warm, measured end to end through the work key. Accepted because
concurrent agentic work is not viable on this hardware anyway.
Virtual text rather than a cmp source because there is no completion engine
installed here, and ghost text is the copilot-shaped one. Silent no-op when
LITELLM_KEY_NVIM is unset, so the headless NAS is unaffected.
zshenv is read by every zsh, so a nested shell prepended the repo's bin
directories a second time. The NAS showed each of them twice after one
`zsh -l -i`. typeset -U keeps the first occurrence, which is also the
ordering this file intends.
The NAS is a minimal Arch install with no inetutils, so hostname(1) does
not exist and install died on its first line of real work. uname -n is
POSIX and always present. The same assumption was in dots, pkg-snapshot,
pkg-restore and zshenv's fallback.
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).