dotfiles

andersuno
git clone git://git.andersuno.nu/dotfiles.git
Log | Files | Refs | README

commit fb38e970672dd26ad08b1ecacf58ca062dc595a1
parent 4af7181819438edfa77a94c3745eff1588ecf991
Author: Anders Hedman <anders.hedman01@gmail.com>
Date:   Tue, 22 Sep 2026 15:26:32 +0200

chore(opencode): migrate config to V2 schema

Update opencode.jsonc to the V2 config format: providers, MCP servers,
plugins, agents, and the new ordered permission rules. Permission
semantics are preserved (secrets denied, read-only allows, mutating
commands ask).

Diffstat:
M.config/opencode/opencode.jsonc | 332++++++++++++++++++++++++++++++++++++++++----------------------------------------
1 file changed, 166 insertions(+), 166 deletions(-)

diff --git a/.config/opencode/opencode.jsonc b/.config/opencode/opencode.jsonc @@ -1,49 +1,57 @@ { "$schema": "https://opencode.ai/config.json", - "provider": { + "providers": { "ollama": { - "npm": "@ai-sdk/openai-compatible", "name": "Ollama Local", - "options": { + "package": "aisdk:@ai-sdk/openai-compatible", + "settings": { "baseURL": "http://127.0.0.1:11434/v1" }, "models": { "gemma4:e2b": { "name": "gemma4:e2b", - "reasoning": true, - "tool_call": true, - }, + "capabilities": { + "tools": true, + "input": ["text", "image"], + "output": ["text"] + } + } } - }, + } }, "mcp": { - "gitlab": { - "type": "remote", - "url": "https://gitlab.com/api/v4/mcp", - "enabled": false - }, - "brewfather": { - "type": "local", - "command": ["uv", "run", "brewfather-mcp"], - "cwd": "/home/anders/Repos/brewfather-mcp", - "enabled": false, - "timeout": 30000 + "servers": { + "gitlab": { + "type": "remote", + "url": "https://gitlab.com/api/v4/mcp", + "disabled": true + }, + "brewfather": { + "type": "local", + "command": ["uv", "run", "brewfather-mcp"], + "cwd": "/home/anders/Repos/brewfather-mcp", + "disabled": true, + "timeout": { + "catalog": 30000, + "execution": 30000 + } + } } }, // oh-my-opencode "lsp": true, - "plugin": [ + "plugins": [ "oh-my-opencode-slim" ], - "agent": { + "agents": { "explore": { - "disable": true + "disabled": true }, "general": { - "disable": true + "disabled": true }, // oh-my-opencode @@ -53,156 +61,148 @@ "slim-shady": { "description": "Slim prompt agent for general questions", "mode": "primary", - "prompt": "You are a helpful assistant", - "tools": { - "*": false - } + "system": "You are a helpful assistant", + "permissions": [ + { "action": "*", "resource": "*", "effect": "deny" } + ] } }, - "permission": { + // V2: ordered rules, last matching rule wins (broad first, exceptions after) + "permissions": [ // Read-only tools: ask for anything, but never touch .env / .envrc - "read": { - "*": "ask", - "*.env": "deny", - "*.envrc": "deny", - "cloud.conf": "deny", - "secret*": "deny", - "terraform.tfstate*": "deny" - }, - "glob": { - "*": "ask", - "*.env": "deny", - "*.envrc": "deny", - "cloud.conf": "deny", - "secret*": "deny", - "terraform.tfstate*": "deny" - }, - "grep": { - "*": "ask", - "*.env": "deny", - "*.envrc": "deny", - "cloud.conf": "deny", - "secret*": "deny", - "terraform.tfstate*": "deny" - }, - "list": "allow", - "lsp": "allow", - "task": "allow", - "skill": "allow", - "todowrite": "allow", - "question": "allow", - "webfetch": "allow", - "websearch": "allow", + { "action": "read", "resource": "*", "effect": "ask" }, + { "action": "read", "resource": "*.env", "effect": "deny" }, + { "action": "read", "resource": "*.envrc", "effect": "deny" }, + { "action": "read", "resource": "cloud.conf", "effect": "deny" }, + { "action": "read", "resource": "secret*", "effect": "deny" }, + { "action": "read", "resource": "terraform.tfstate*", "effect": "deny" }, - "edit": "ask", + { "action": "glob", "resource": "*", "effect": "ask" }, + { "action": "glob", "resource": "*.env", "effect": "deny" }, + { "action": "glob", "resource": "*.envrc", "effect": "deny" }, + { "action": "glob", "resource": "cloud.conf", "effect": "deny" }, + { "action": "glob", "resource": "secret*", "effect": "deny" }, + { "action": "glob", "resource": "terraform.tfstate*", "effect": "deny" }, - "bash": { - "*": "ask", - // basic inspection - "echo *": "ask", - "ls*": "allow", - "pwd*": "allow", - "cat*": "allow", - "head*": "allow", - "tail*": "allow", - "find*": "allow", - "grep*": "allow", - "rg*": "allow", - "diff*": "allow", - "file*": "allow", - "which*": "allow", - "command -v *": "allow", - "wc*": "allow", - "du*": "allow", - "df*": "allow", - "uname*": "allow", - "sleep *": "allow", - // read-only git - "git status*": "allow", - "git diff*": "allow", - "git log*": "allow", - "git grep*": "allow", - "git show*": "allow", - "git fetch*": "allow", - "git branch*": "allow", - "git remote*": "allow", - "git stash list*": "allow", - // test / check commands - "npm test*": "allow", - "npm run lint*": "allow", - "npm run typecheck*": "allow", - "cargo check*": "allow", - "cargo test*": "allow", - "go vet*": "allow", - "go test*": "allow", - "pytest*": "allow", - "python3 -m pytest*": "allow", - // mutating: always confirm (must come after any matching allow) - "git add*": "ask", - "git commit*": "ask", - "git push*": "ask", - "git reset*": "ask", - "git checkout*": "ask", - "git clean*": "ask", - "git rebase*": "ask", - "npm install*": "ask", - "npm run build*": "ask", - "cargo build*": "ask", - "go build*": "ask", - "pip install*": "ask", - "terraform plan*": "ask", - "terraform apply*": "ask", - "docker*": "ask", - "curl*": "ask", - "wget*": "ask", - "sudo*": "ask", - "chmod*": "ask", - "chown*": "ask", - "cp*": "ask", - "mv*": "ask", - "mkdir*": "ask", - "touch*": "ask", - "rm *": "ask", - // enivronment $VAR - "printenv *": "deny", - "env *": "deny", - // .env / .envrc via shell - "cat* .env*": "deny", - "grep* .env*": "deny", - "rg* .env*": "deny", - "head* .env*": "deny", - "tail* .env*": "deny", - // terraform.tfstate - "cat* terraform.tfstate*": "deny", - "grep* terraform.tfstate*": "deny", - "rg* terraform.tfstate*": "deny", - "head* terraform.tfstate*": "deny", - "tail* terraform.tfstate*": "deny", - // Sops - "sops*": "deny", - // destructive: never auto-run (last rules win) - "rm -rf*": "deny", - "rm -fr*": "deny", - "git push --force*": "deny", - "shutdown*": "deny", - "reboot*": "deny", - "mkfs*": "deny", - "dd *": "deny" - }, + { "action": "grep", "resource": "*", "effect": "ask" }, + { "action": "grep", "resource": "*.env", "effect": "deny" }, + { "action": "grep", "resource": "*.envrc", "effect": "deny" }, + { "action": "grep", "resource": "cloud.conf", "effect": "deny" }, + { "action": "grep", "resource": "secret*", "effect": "deny" }, + { "action": "grep", "resource": "terraform.tfstate*", "effect": "deny" }, + + { "action": "subagent", "resource": "*", "effect": "allow" }, + { "action": "skill", "resource": "*", "effect": "allow" }, + { "action": "question", "resource": "*", "effect": "allow" }, + { "action": "webfetch", "resource": "*", "effect": "allow" }, + { "action": "websearch", "resource": "*", "effect": "allow" }, + + { "action": "edit", "resource": "*", "effect": "ask" }, + + // shell (was "bash" in V1) + { "action": "shell", "resource": "*", "effect": "ask" }, + // basic inspection + { "action": "shell", "resource": "echo *", "effect": "ask" }, + { "action": "shell", "resource": "ls*", "effect": "allow" }, + { "action": "shell", "resource": "pwd*", "effect": "allow" }, + { "action": "shell", "resource": "cat*", "effect": "allow" }, + { "action": "shell", "resource": "head*", "effect": "allow" }, + { "action": "shell", "resource": "tail*", "effect": "allow" }, + { "action": "shell", "resource": "find*", "effect": "allow" }, + { "action": "shell", "resource": "grep*", "effect": "allow" }, + { "action": "shell", "resource": "rg*", "effect": "allow" }, + { "action": "shell", "resource": "diff*", "effect": "allow" }, + { "action": "shell", "resource": "file*", "effect": "allow" }, + { "action": "shell", "resource": "which*", "effect": "allow" }, + { "action": "shell", "resource": "command -v *", "effect": "allow" }, + { "action": "shell", "resource": "wc*", "effect": "allow" }, + { "action": "shell", "resource": "du*", "effect": "allow" }, + { "action": "shell", "resource": "df*", "effect": "allow" }, + { "action": "shell", "resource": "uname*", "effect": "allow" }, + { "action": "shell", "resource": "sleep *", "effect": "allow" }, + // read-only git + { "action": "shell", "resource": "git status*", "effect": "allow" }, + { "action": "shell", "resource": "git diff*", "effect": "allow" }, + { "action": "shell", "resource": "git log*", "effect": "allow" }, + { "action": "shell", "resource": "git grep*", "effect": "allow" }, + { "action": "shell", "resource": "git show*", "effect": "allow" }, + { "action": "shell", "resource": "git fetch*", "effect": "allow" }, + { "action": "shell", "resource": "git branch*", "effect": "allow" }, + { "action": "shell", "resource": "git remote*", "effect": "allow" }, + { "action": "shell", "resource": "git stash list*", "effect": "allow" }, + // test / check commands + { "action": "shell", "resource": "npm test*", "effect": "allow" }, + { "action": "shell", "resource": "npm run lint*", "effect": "allow" }, + { "action": "shell", "resource": "npm run typecheck*", "effect": "allow" }, + { "action": "shell", "resource": "cargo check*", "effect": "allow" }, + { "action": "shell", "resource": "cargo test*", "effect": "allow" }, + { "action": "shell", "resource": "go vet*", "effect": "allow" }, + { "action": "shell", "resource": "go test*", "effect": "allow" }, + { "action": "shell", "resource": "pytest*", "effect": "allow" }, + { "action": "shell", "resource": "python3 -m pytest*", "effect": "allow" }, + // mutating: always confirm (after the matching allows above) + { "action": "shell", "resource": "git add*", "effect": "ask" }, + { "action": "shell", "resource": "git commit*", "effect": "ask" }, + { "action": "shell", "resource": "git push*", "effect": "ask" }, + { "action": "shell", "resource": "git reset*", "effect": "ask" }, + { "action": "shell", "resource": "git checkout*", "effect": "ask" }, + { "action": "shell", "resource": "git clean*", "effect": "ask" }, + { "action": "shell", "resource": "git rebase*", "effect": "ask" }, + { "action": "shell", "resource": "npm install*", "effect": "ask" }, + { "action": "shell", "resource": "npm run build*", "effect": "ask" }, + { "action": "shell", "resource": "cargo build*", "effect": "ask" }, + { "action": "shell", "resource": "go build*", "effect": "ask" }, + { "action": "shell", "resource": "pip install*", "effect": "ask" }, + { "action": "shell", "resource": "terraform plan*", "effect": "ask" }, + { "action": "shell", "resource": "terraform apply*", "effect": "ask" }, + { "action": "shell", "resource": "docker*", "effect": "ask" }, + { "action": "shell", "resource": "curl*", "effect": "ask" }, + { "action": "shell", "resource": "wget*", "effect": "ask" }, + { "action": "shell", "resource": "sudo*", "effect": "ask" }, + { "action": "shell", "resource": "chmod*", "effect": "ask" }, + { "action": "shell", "resource": "chown*", "effect": "ask" }, + { "action": "shell", "resource": "cp*", "effect": "ask" }, + { "action": "shell", "resource": "mv*", "effect": "ask" }, + { "action": "shell", "resource": "mkdir*", "effect": "ask" }, + { "action": "shell", "resource": "touch*", "effect": "ask" }, + { "action": "shell", "resource": "rm *", "effect": "ask" }, + // environment $VAR + { "action": "shell", "resource": "printenv *", "effect": "deny" }, + { "action": "shell", "resource": "env *", "effect": "deny" }, + // .env / .envrc via shell + { "action": "shell", "resource": "cat* .env*", "effect": "deny" }, + { "action": "shell", "resource": "grep* .env*", "effect": "deny" }, + { "action": "shell", "resource": "rg* .env*", "effect": "deny" }, + { "action": "shell", "resource": "head* .env*", "effect": "deny" }, + { "action": "shell", "resource": "tail* .env*", "effect": "deny" }, + // terraform.tfstate + { "action": "shell", "resource": "cat* terraform.tfstate*", "effect": "deny" }, + { "action": "shell", "resource": "grep* terraform.tfstate*", "effect": "deny" }, + { "action": "shell", "resource": "rg* terraform.tfstate*", "effect": "deny" }, + { "action": "shell", "resource": "head* terraform.tfstate*", "effect": "deny" }, + { "action": "shell", "resource": "tail* terraform.tfstate*", "effect": "deny" }, + // Sops + { "action": "shell", "resource": "sops*", "effect": "deny" }, + // destructive: never auto-run (after the broader asks above) + { "action": "shell", "resource": "rm -rf*", "effect": "deny" }, + { "action": "shell", "resource": "rm -fr*", "effect": "deny" }, + { "action": "shell", "resource": "git push --force*", "effect": "deny" }, + { "action": "shell", "resource": "shutdown*", "effect": "deny" }, + { "action": "shell", "resource": "reboot*", "effect": "deny" }, + { "action": "shell", "resource": "mkfs*", "effect": "deny" }, + { "action": "shell", "resource": "dd *", "effect": "deny" }, // Files outside the workspace: confirm, but block secrets outright - "external_directory": { - "*": "ask", - "/tmp/opencode/**": "allow", - "~/.config/opencode/skills/**": "allow", - "~/.aws/**": "deny", - "~/.gnupg/**": "deny", - "~/.kube/**": "deny", - "~/.s3cfg*": "deny", - "~/.ssh/**": "deny", - "~/.vault_pass.txt*": "deny", - "~/.vault-token*": "deny" - } - } + { "action": "external_directory", "resource": "*", "effect": "ask" }, + { "action": "external_directory", "resource": "/tmp/opencode/*", "effect": "allow" }, + { "action": "external_directory", "resource": "~/.config/opencode/skills/*", "effect": "allow" }, + { "action": "external_directory", "resource": "~/.aws/*", "effect": "deny" }, + { "action": "external_directory", "resource": "~/.gnupg/*", "effect": "deny" }, + { "action": "external_directory", "resource": "~/.kube/*", "effect": "deny" }, + { "action": "external_directory", "resource": "~/.s3cfg*", "effect": "deny" }, + { "action": "external_directory", "resource": "~/.ssh/*", "effect": "deny" }, + { "action": "external_directory", "resource": "~/.vault_pass.txt*", "effect": "deny" }, + { "action": "external_directory", "resource": "~/.vault-token*", "effect": "deny" } + ] }