Compare commits

..

10 Commits

Author SHA1 Message Date
colem 57821ba227 build(opencode): add playwright mcp server configuration
Register the @playwright/mcp server in opencode.jsonc and reformat
the watcher ignore list across multiple lines for readability.
2026-07-31 11:00:46 -05:00
colem 4f6136e88c fix(opencode): load global rules by renaming RULES.md to AGENTS.md
RULES.md was not an opencode-recognized rules filename, so global
rules (including the "no AI co-author" Git rule) were never loaded;
only the stale, un-version-controlled ~/.claude/CLAUDE.md fallback
applied, which lacked that rule. Rename to AGENTS.md so opencode
loads it natively as the global rules file.

Also add watcher.ignore for node_modules/.git/dist/.venv/target dirs.
2026-07-31 09:37:17 -05:00
colem e94d6b3c14 feat(opencode): add ibmi column-info tool and harden permissions
- add the get_column_info custom tool for the ibmi-mcp-server and
  relocate its --tools path from a hardcoded absolute path into the
  version-controlled tree via {env:HOME} interpolation
- reorder permission rules so "rm -rf *" (deny) is no longer shadowed
  by "rm *" (ask); last-match-wins now resolves rm -rf to deny
- add allow rules for the Python toolchain (unittest, py_compile,
  venv activation, ruff check/format)
- rename plugin/ to plugins/ to match the documented plural convention
- commit package.json and package-lock.json so the ibmi-gate plugin
  resolves @opencode-ai/plugin on a fresh stow
- correct the README opencode directory description
2026-07-31 09:14:29 -05:00
colem 4038a5ccbe feat(opencode): add git-message command for conventional commit generation 2026-07-31 08:39:30 -05:00
cole-maxwell1 c65b1272e2 Update README.md 2026-07-29 21:26:53 -05:00
cole-maxwell1 13e26f720d Add: allow which and find.
- Removes "opencode.jsonc": "deny"
2026-07-29 21:18:20 -05:00
cole-maxwell1 a80e6df2b5 Swap opencode-glm-quota for @slkiser/opencode-quota 2026-07-29 21:09:57 -05:00
cole-maxwell1 28582d56c0 Add: gate ibmi-server MCP on required env vars
opencode's config schema types mcp.<name>.enabled as a static boolean and only interpolates {env:VAR} for string values, so conditional enablement is not expressible in opencode.jsonc alone.

Add a config-hook plugin that flips ibmi-server.enabled to true only when DB2i_HOST, DB2i_USER, and DB2i_PASS are all set. The config retains enabled: false as a fallback if the plugin fails to load.
2026-07-29 20:39:24 -05:00
colem bfb6dcd4df Add: opencode PATH and WSL keyring/dbus setup 2026-07-29 10:45:23 -05:00
colem 892aca56df Add opencode config 2026-07-29 10:38:06 -05:00
12 changed files with 784 additions and 24 deletions
+1
View File
@@ -0,0 +1 @@
../.config/opencode/AGENTS.md
+16
View File
@@ -0,0 +1,16 @@
# Response Tone
1. **Accuracy over agreeableness:** Do not open with compliments, validation, or social pleasantries. Begin every response with the substance of the answer. Praise is noise; signal is the goal.
2. **Default to skepticism:** Treat every user claim as potentially flawed until verified. If a statement is wrong, say so immediately and state the correction. Do not use hedging language like "You might want to consider...". Say "That is incorrect" and explain why.
3. **Never apologize for correcting the user:** Corrections are the primary value. Phrases like "I'm sorry, but..." or "With all due respect..." are forbidden. State the correction directly.
4. **Be blunt and argumentative when warranted:** If reasoning is unsound, challenge it. Name the flaw in the logic explicitly. You have standing permission to disagree and hold your position if reasoning is stronger.
5. **Do not mirror the user's confidence:** Evaluate claims on merits alone. A confidently stated falsehood receives the same direct correction as a tentative one.
6. **Distinguish certainty levels honestly:** When certain, be assertive. When genuinely ambiguous, say so plainly without manufacturing false uncertainty.
# Style & Formatting Constraints
1. **Code Comment Tone:** Keep all comments objective or imperative. It is strictly forbidden to use words like "we", "us", or any first-person plural personal pronouns in code comments or explanations.
2. **No Emojis:** NEVER use emojis in code comments, `README.md` files, or any other Markdown documentation. Maintain a purely professional, text-only formatting style.
# Git
When asked, write professional Git commit messages for requested changes. NEVER add an AI co-author tag to commit messages.
+30
View File
@@ -0,0 +1,30 @@
---
description: Generate a Conventional Commit message based on staged changes
---
Inspect the current workspace git status and staged diff (`git diff --staged`). Generate a professional commit message for my approval.
Strictly adhere to the following Conventional Commit specification rules:
### Formatting Rules
- **Format:** `<type>(<optional scope>): <description>` followed by an optional `<body>` and `<footer` separated by blank lines.
- **Subject Case:** The description MUST start with a lowercase letter.
- **No Ending Punctuation:** Do NOT end the subject line with a period.
- **Imperative Mood:** Use imperative, present tense ("add" not "added" or "adds").
- **Breaking Changes:** Append `!` before the colon in the header for breaking changes (e.g., `feat(api)!: drop v1 endpoints`) and include a `BREAKING CHANGE:` footer.
### Allowed Types
- `feat`: Add, adjust, or remove API/UI functionality.
- `fix`: Fix a bug in existing API/UI functionality.
- `refactor`: Structural changes without altering public API/UI behavior.
- `perf`: Special refactor that explicitly improves performance.
- `style`: Formatting, missing semi-colons, whitespace adjustments.
- `test`: Adding or correcting tests.
- `docs`: Documentation updates only.
- `build`: Build tool, dependency, or project version updates.
- `ops`: Infrastructure, CI/CD pipelines, deployment, or operational scripts.
- `chore`: Maintenance tasks (e.g., updating `.gitignore`, repo setup).
Provide ONLY the proposed commit message inside a raw code block, followed by a request for my approval.
@@ -0,0 +1,43 @@
sources:
ibmi-system:
host: ${DB2i_HOST}
user: ${DB2i_USER}
password: ${DB2i_PASS}
tools:
get_column_info:
source: ibmi-system
description: >-
Retrieve a table's column details like TABLE_NAME, SYSTEM_TABLE_NAME,
COLUMN_NAME, SYSTEM_COLUMN_NAME, DATA_TYPE, LENGTH, NUMERIC_SCALE,
IS_NULLABLE, COLUMN_HEADING, COLUMN_TEXT from the system catalog for the
specified table.
parameters:
- name: table_name
type: string
description: "The name of the table to retrieve columns for."
required: true
statement: |
SELECT
TABLE_NAME,
SYSTEM_TABLE_NAME,
COLUMN_NAME,
SYSTEM_COLUMN_NAME,
DATA_TYPE,
LENGTH,
NUMERIC_SCALE,
IS_NULLABLE,
COLUMN_HEADING,
COLUMN_TEXT
FROM
QSYS2.SYSCOLUMNS
WHERE
TABLE_NAME = UPPER(:table_name)
ORDER BY
TABLE_NAME,
ORDINAL_POSITION
toolsets:
custom_tools:
tools:
- get_column_info
@@ -0,0 +1,23 @@
{
// Automatic quota surfaces. Slash commands remain available when these are disabled.
"enableToast": false,
"tuiCommandDisplay": "inline",
// Include or hide session input and output token totals.
"showSessionTokens": true,
// Session token totals: "current" session only, or "tree" including descendants.
"sessionTokenScope": "current",
// Provider selection: "auto" detects providers; an array tracks only listed providers.
"enabledProviders": "auto",
// Quota presentation and reset-period choices.
"formatStyle": "allWindows",
"percentDisplayMode": "used",
// TUI-only surfaces.
"tuiSidebarPanel": {
"enabled": true,
},
// Optional bundled maintainer Home announcements.
"maintainerAnnouncements": {
"enabled": true,
"home": true,
},
}
+150
View File
@@ -0,0 +1,150 @@
{
"$schema": "https://opencode.ai/config.json",
"permission": {
"bash": {
"*": "ask",
// Git
"git log *": "allow",
"git commit *": "ask",
"git status *": "allow",
"git diff *": "allow",
"git show *": "allow",
"git push *": "ask",
// GNU Utils
"sudo *": "deny",
"curl *": "ask",
"wget *": "ask",
"diff *": "allow",
"npm *": "allow",
"rm *": "ask",
"rm -rf *": "deny",
"grep *": "allow",
"sort *": "allow",
"head *": "allow",
"tail *": "allow",
"echo *": "allow",
"which *": "allow",
"find *": "allow",
"ls *": "allow",
"wc *": "allow",
// Go
"go build *": "allow",
"go test *": "allow",
"go vet *": "allow",
"go mod tidy": "allow",
"go mod download": "allow",
// Python
"python -m unittest *": "allow",
"python -m py_compile": "allow",
"python3 -m venv .venv": "allow",
"source .venv/bin/activate": "allow",
"ruff check *": "allow",
"ruff format --check *": "allow",
// Dotnet
"dotnet *": "allow",
// Docker
"docker ps *": "allow",
"docker logs *": "allow",
"docker compose logs *": "allow",
},
"read": {
".env": "deny",
".secrets": "deny",
"*.key": "deny",
"*.pem": "deny",
"id_rsa": "deny",
"id_ed25519": "deny",
".aws/credentials": "deny",
"~/.ssh/known_hosts": "allow",
},
"grep": "allow",
"glob": "allow",
"question": "allow",
"lsp": "allow",
"websearch": "allow",
},
"mcp": {
"zai-mcp-server": {
"type": "local",
"command": ["npx", "-y", "@z_ai/mcp-server"],
"environment": {
"Z_AI_API_KEY": "{env:ZAI_API_KEY}",
"Z_AI_MODE": "ZAI",
},
},
"web-search-prime": {
"type": "remote",
"url": "https://api.z.ai/api/mcp/web_search_prime/mcp",
"headers": {
"Authorization": "Bearer {env:ZAI_API_KEY}",
},
},
"web-reader": {
"type": "remote",
"url": "https://api.z.ai/api/mcp/web_reader/mcp",
"headers": {
"Authorization": "Bearer {env:ZAI_API_KEY}",
},
},
"zread": {
"type": "remote",
"url": "https://api.z.ai/api/mcp/zread/mcp",
"headers": {
"Authorization": "Bearer {env:ZAI_API_KEY}",
},
},
"playwright": {
"type": "local",
"command": ["npx", "@playwright/mcp@latest"],
"enabled": true,
},
"ibmi-server": {
"type": "local",
"command": [
"npx",
"-y",
"@ibm/ibmi-mcp-server@latest",
"--tools",
"{env:HOME}/.config/opencode/mcp/ibmi-mcp-server/tools/custom-tools.yaml",
],
"enabled": false,
"environment": {
"DB2i_HOST": "{env:DB2i_HOST}",
"DB2i_USER": "{env:DB2i_USER}",
"DB2i_PASS": "{env:DB2i_PASS}",
"DB2i_PORT": "8076",
"DB2i_IGNORE_UNAUTHORIZED": "true",
},
},
},
"watcher": {
"ignore": [
"node_modules/**",
".git/**",
"dist/**",
"**/.venv/**",
"**/target/**",
],
},
"lsp": true,
"formatter": true,
"model": "zai-coding-plan/glm-5.2",
"small_model": "zai-coding-plan/glm-4.5-air",
"agent": {
"explore": {
"model": "zai-coding-plan/glm-4.5-air",
},
"scout": {
"model": "zai-coding-plan/glm-4.5-air",
},
},
"share": "disabled",
"snapshot": true,
// OpenCode Quota: tuiCommandDisplay chooses whether native TUI command output appears in the session transcript or a local popup dialog.
// OpenCode Quota: loads the server plugin for slash commands and quota checks.
"plugin": ["./plugins/ibmi-gate.ts", "@slkiser/opencode-quota@latest"],
"provider": {
// Detected zai authentication; opencode-quota added this global provider declaration.
"zai": {},
},
}
+401
View File
@@ -0,0 +1,401 @@
{
"name": "opencode",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"dependencies": {
"@opencode-ai/plugin": "1.18.7"
}
},
"node_modules/@ai-sdk/provider": {
"version": "3.0.8",
"resolved": "https://registry.npmjs.org/@ai-sdk/provider/-/provider-3.0.8.tgz",
"integrity": "sha512-oGMAgGoQdBXbZqNG0Ze56CHjDZ1IDYOwGYxYjO5KLSlz5HiNQ9udIXsPZ61VWaHGZ5XW/jyjmr6t2xz2jGVwbQ==",
"license": "Apache-2.0",
"dependencies": {
"json-schema": "^0.4.0"
},
"engines": {
"node": ">=18"
}
},
"node_modules/@msgpackr-extract/msgpackr-extract-darwin-arm64": {
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-darwin-arm64/-/msgpackr-extract-darwin-arm64-3.0.4.tgz",
"integrity": "sha512-LCkGo6JDfaBhgST7UpPWgNgLINpcpabaHfyz5OBx75nUYxBsaEPxjnyNjWpeb/xBup/682QnBfRBy2/LvPutZQ==",
"cpu": [
"arm64"
],
"license": "MIT",
"optional": true,
"os": [
"darwin"
]
},
"node_modules/@msgpackr-extract/msgpackr-extract-darwin-x64": {
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-darwin-x64/-/msgpackr-extract-darwin-x64-3.0.4.tgz",
"integrity": "sha512-zExlW9zUJKZH/tOtVMttwjKa4Xm/3KcNjnE3dPN92uCktwavMxpgCA3MoJK/DOnTWsQgo224OaST27/mPNAf+w==",
"cpu": [
"x64"
],
"license": "MIT",
"optional": true,
"os": [
"darwin"
]
},
"node_modules/@msgpackr-extract/msgpackr-extract-linux-arm": {
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-linux-arm/-/msgpackr-extract-linux-arm-3.0.4.tgz",
"integrity": "sha512-Tg3yX65f5GbtXLkrYEHE5oibZG9epyYWas7FogTTEJeDEF9JlXJzKgXaNhT3UXlTOeA+AfZpYZYZ0uPj7Cfquw==",
"cpu": [
"arm"
],
"license": "MIT",
"optional": true,
"os": [
"linux"
]
},
"node_modules/@msgpackr-extract/msgpackr-extract-linux-arm64": {
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-linux-arm64/-/msgpackr-extract-linux-arm64-3.0.4.tgz",
"integrity": "sha512-dgX0P/9wGPJeHFBG+ZmhgE6bmtMt7NP5CRBGyyktpopdk/mW4POnrpQsSLtKI1dwpc+pPLuXHDh6vvskyQE/sw==",
"cpu": [
"arm64"
],
"license": "MIT",
"optional": true,
"os": [
"linux"
]
},
"node_modules/@msgpackr-extract/msgpackr-extract-linux-x64": {
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-linux-x64/-/msgpackr-extract-linux-x64-3.0.4.tgz",
"integrity": "sha512-8TNXMEjJc3QEy7R/x1INhgiU+XakDAFUzBhaz7+Rbrs8NH5UQeHQxxmzsSBJGyV6I1jW79undiQm8tOI+D+8FQ==",
"cpu": [
"x64"
],
"license": "MIT",
"optional": true,
"os": [
"linux"
]
},
"node_modules/@msgpackr-extract/msgpackr-extract-win32-x64": {
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-win32-x64/-/msgpackr-extract-win32-x64-3.0.4.tgz",
"integrity": "sha512-CmCXPQrkbwExx3j946/PtHWHbYJiCRBRDl4BlkRQcJB/YOwQxJRTpoo7aTsortjgoJ1x7opzTSxn7C+ASSLVjQ==",
"cpu": [
"x64"
],
"license": "MIT",
"optional": true,
"os": [
"win32"
]
},
"node_modules/@opencode-ai/plugin": {
"version": "1.18.7",
"resolved": "https://registry.npmjs.org/@opencode-ai/plugin/-/plugin-1.18.7.tgz",
"integrity": "sha512-kXm5hqur5JiF/xJPaQYkuNn7vSl4ya09YgL/pIvIrggWCLFsfo1gXqNbONRcGW7m5Ih2k6kgMXFyjB9or1+dEg==",
"license": "MIT",
"dependencies": {
"@ai-sdk/provider": "3.0.8",
"@opencode-ai/sdk": "1.18.7",
"effect": "4.0.0-beta.83",
"zod": "4.1.8"
},
"peerDependencies": {
"@opentui/core": ">=0.4.5",
"@opentui/keymap": ">=0.4.5",
"@opentui/solid": ">=0.4.5"
},
"peerDependenciesMeta": {
"@opentui/core": {
"optional": true
},
"@opentui/keymap": {
"optional": true
},
"@opentui/solid": {
"optional": true
}
}
},
"node_modules/@opencode-ai/sdk": {
"version": "1.18.7",
"resolved": "https://registry.npmjs.org/@opencode-ai/sdk/-/sdk-1.18.7.tgz",
"integrity": "sha512-5txVELvCxzC3O/MYnRKdTvBN3TqQjE3PaEks3kDRA/moWzMSUhdm15xCth/Mz/NPYyGTn2u4IdScdV9vLTfLRg==",
"license": "MIT",
"dependencies": {
"cross-spawn": "7.0.6"
}
},
"node_modules/@standard-schema/spec": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/@standard-schema/spec/-/spec-1.1.0.tgz",
"integrity": "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==",
"license": "MIT"
},
"node_modules/cross-spawn": {
"version": "7.0.6",
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz",
"integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==",
"license": "MIT",
"dependencies": {
"path-key": "^3.1.0",
"shebang-command": "^2.0.0",
"which": "^2.0.1"
},
"engines": {
"node": ">= 8"
}
},
"node_modules/detect-libc": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz",
"integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==",
"license": "Apache-2.0",
"optional": true,
"engines": {
"node": ">=8"
}
},
"node_modules/effect": {
"version": "4.0.0-beta.83",
"resolved": "https://registry.npmjs.org/effect/-/effect-4.0.0-beta.83.tgz",
"integrity": "sha512-0wsak8RtgGAr9UWSbVDgJHZcUqMSvicHcvaZv1MbMM7MCGgW4Rn/137J1MHQbwYPcwYGxT/IqehFd+UbYuj78w==",
"license": "MIT",
"dependencies": {
"@standard-schema/spec": "^1.1.0",
"fast-check": "^4.8.0",
"find-my-way-ts": "^0.1.6",
"ini": "^7.0.0",
"kubernetes-types": "^1.30.0",
"msgpackr": "^2.0.1",
"multipasta": "^0.2.7",
"toml": "^4.1.1",
"uuid": "^14.0.0",
"yaml": "^2.9.0"
}
},
"node_modules/fast-check": {
"version": "4.9.0",
"resolved": "https://registry.npmjs.org/fast-check/-/fast-check-4.9.0.tgz",
"integrity": "sha512-7ms6T7SybUev/PQITciI0yLM2pOSFy5zpG8Ty7tQofcVaQUvrMXp6CBwqF6fThLCLOrfBtuHAtwq6Yu4XPCllg==",
"funding": [
{
"type": "individual",
"url": "https://github.com/sponsors/dubzzz"
},
{
"type": "opencollective",
"url": "https://opencollective.com/fast-check"
}
],
"license": "MIT",
"dependencies": {
"pure-rand": "^8.0.0"
},
"engines": {
"node": ">=12.17.0"
}
},
"node_modules/find-my-way-ts": {
"version": "0.1.6",
"resolved": "https://registry.npmjs.org/find-my-way-ts/-/find-my-way-ts-0.1.6.tgz",
"integrity": "sha512-a85L9ZoXtNAey3Y6Z+eBWW658kO/MwR7zIafkIUPUMf3isZG0NCs2pjW2wtjxAKuJPxMAsHUIP4ZPGv0o5gyTA==",
"license": "MIT"
},
"node_modules/ini": {
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/ini/-/ini-7.0.0.tgz",
"integrity": "sha512-ifK0CgjALofS5bkrcTy4RaQ9Vx2Knf/eLeIO+NaswQEpH1UblrtTSCIvN71qQDMq0PeQ/SSPojvEJp9vvvfr+w==",
"license": "ISC",
"engines": {
"node": "^22.22.2 || ^24.15.0 || >=26.0.0"
}
},
"node_modules/isexe": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
"integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==",
"license": "ISC"
},
"node_modules/json-schema": {
"version": "0.4.0",
"resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz",
"integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==",
"license": "(AFL-2.1 OR BSD-3-Clause)"
},
"node_modules/kubernetes-types": {
"version": "1.30.0",
"resolved": "https://registry.npmjs.org/kubernetes-types/-/kubernetes-types-1.30.0.tgz",
"integrity": "sha512-Dew1okvhM/SQcIa2rcgujNndZwU8VnSapDgdxlYoB84ZlpAD43U6KLAFqYo17ykSFGHNPrg0qry0bP+GJd9v7Q==",
"license": "Apache-2.0"
},
"node_modules/msgpackr": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/msgpackr/-/msgpackr-2.0.4.tgz",
"integrity": "sha512-o1C5KRmuRt+apqMr1HuGSqWStZoRBUpEsCsl15uM9VdAF1qHLtvMOU2En747EnTyEl6c4pzPewRMFF31s1CNbA==",
"license": "MIT",
"optionalDependencies": {
"msgpackr-extract": "^3.0.4"
}
},
"node_modules/msgpackr-extract": {
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/msgpackr-extract/-/msgpackr-extract-3.0.4.tgz",
"integrity": "sha512-4kmO/MdyUIkLIvTPr8VHLil4AtoKIoniWPIEk5+CDy0xnWC84azhSFmuJ7PxZdsYtiP5kEeQsORAVIeMgxT+Hw==",
"hasInstallScript": true,
"license": "MIT",
"optional": true,
"dependencies": {
"node-gyp-build-optional-packages": "5.2.2"
},
"bin": {
"download-msgpackr-prebuilds": "bin/download-prebuilds.js"
},
"optionalDependencies": {
"@msgpackr-extract/msgpackr-extract-darwin-arm64": "3.0.4",
"@msgpackr-extract/msgpackr-extract-darwin-x64": "3.0.4",
"@msgpackr-extract/msgpackr-extract-linux-arm": "3.0.4",
"@msgpackr-extract/msgpackr-extract-linux-arm64": "3.0.4",
"@msgpackr-extract/msgpackr-extract-linux-x64": "3.0.4",
"@msgpackr-extract/msgpackr-extract-win32-x64": "3.0.4"
}
},
"node_modules/multipasta": {
"version": "0.2.8",
"resolved": "https://registry.npmjs.org/multipasta/-/multipasta-0.2.8.tgz",
"integrity": "sha512-ZPWuMKyv0cSO29f7hozp+k6+crZbQijV8ipMvxNxRf2SwtYGTX1ZX89Kd20VV4H9Znonx+EQn+iy1wGQsJ+b+Q==",
"license": "MIT"
},
"node_modules/node-gyp-build-optional-packages": {
"version": "5.2.2",
"resolved": "https://registry.npmjs.org/node-gyp-build-optional-packages/-/node-gyp-build-optional-packages-5.2.2.tgz",
"integrity": "sha512-s+w+rBWnpTMwSFbaE0UXsRlg7hU4FjekKU4eyAih5T8nJuNZT1nNsskXpxmeqSK9UzkBl6UgRlnKc8hz8IEqOw==",
"license": "MIT",
"optional": true,
"dependencies": {
"detect-libc": "^2.0.1"
},
"bin": {
"node-gyp-build-optional-packages": "bin.js",
"node-gyp-build-optional-packages-optional": "optional.js",
"node-gyp-build-optional-packages-test": "build-test.js"
}
},
"node_modules/path-key": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
"integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
"license": "MIT",
"engines": {
"node": ">=8"
}
},
"node_modules/pure-rand": {
"version": "8.4.2",
"resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-8.4.2.tgz",
"integrity": "sha512-vvuOGgcuPJAirlHvuQw1TrOiw7ptaIXXmIbNuiNOY6lNGJJH49PQ1Kj4nd783nPdQhQdicgOjVI2yI/9BD6/Ng==",
"funding": [
{
"type": "individual",
"url": "https://github.com/sponsors/dubzzz"
},
{
"type": "opencollective",
"url": "https://opencollective.com/fast-check"
}
],
"license": "MIT"
},
"node_modules/shebang-command": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
"integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
"license": "MIT",
"dependencies": {
"shebang-regex": "^3.0.0"
},
"engines": {
"node": ">=8"
}
},
"node_modules/shebang-regex": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
"integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
"license": "MIT",
"engines": {
"node": ">=8"
}
},
"node_modules/toml": {
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/toml/-/toml-4.3.0.tgz",
"integrity": "sha512-lVb8X9BsPVuH0M4BKeS91tXAmJvCjQ5UIyAbQFaxkKGyUFK2RPkhwaFSQH8vbpl1d23eu/IBH+dwVMHWaq9A5A==",
"license": "MIT",
"engines": {
"node": ">=20"
}
},
"node_modules/uuid": {
"version": "14.0.1",
"resolved": "https://registry.npmjs.org/uuid/-/uuid-14.0.1.tgz",
"integrity": "sha512-6ZxzVpzDXDa3bJWaHilVayA+BH/1zmxCJoVgvmqJnid/gPoKHxUrS/aC/T6LGQtNHT+XHG9fXPJB4d+IrU30Ew==",
"funding": [
"https://github.com/sponsors/broofa",
"https://github.com/sponsors/ctavan"
],
"license": "MIT",
"bin": {
"uuid": "dist-node/bin/uuid"
}
},
"node_modules/which": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
"integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
"license": "ISC",
"dependencies": {
"isexe": "^2.0.0"
},
"bin": {
"node-which": "bin/node-which"
},
"engines": {
"node": ">= 8"
}
},
"node_modules/yaml": {
"version": "2.9.0",
"resolved": "https://registry.npmjs.org/yaml/-/yaml-2.9.0.tgz",
"integrity": "sha512-2AvhNX3mb8zd6Zy7INTtSpl1F15HW6Wnqj0srWlkKLcpYl/gMIMJiyuGq2KeI2YFxUPjdlB+3Lc10seMLtL4cA==",
"license": "ISC",
"bin": {
"yaml": "bin.mjs"
},
"engines": {
"node": ">= 14.6"
},
"funding": {
"url": "https://github.com/sponsors/eemeli"
}
},
"node_modules/zod": {
"version": "4.1.8",
"resolved": "https://registry.npmjs.org/zod/-/zod-4.1.8.tgz",
"integrity": "sha512-5R1P+WwQqmmMIEACyzSvo4JXHY5WiAFHRMg+zBZKgKS+Q1viRa0C1hmUKtHltoIFKtIdki3pRxkmpP74jnNYHQ==",
"license": "MIT",
"funding": {
"url": "https://github.com/sponsors/colinhacks"
}
}
}
}
+5
View File
@@ -0,0 +1,5 @@
{
"dependencies": {
"@opencode-ai/plugin": "1.18.7"
}
}
+35
View File
@@ -0,0 +1,35 @@
/*
Gate the ibmi-mcp-server on its required environment variables.
opencode's config schema types `mcp.<name>.enabled` as a static boolean and
only interpolates `{env:VAR}` for string values (headers, environment
entries), never for the `enabled` flag. Conditionally enabling a server is
therefore not expressible in opencode.jsonc alone.
This plugin uses the `config` hook, which runs once at startup with the live
merged config (before MCP servers spawn), to flip `ibmi-server.enabled` to
`true` only when every required credential is present. The config keeps
`enabled: false` as a fallback default, so the server stays off if this
plugin fails to load.
*/
import type { Plugin } from "@opencode-ai/plugin";
// Credentials the ibmi-server MCP needs to connect. All must be non-empty.
const REQUIRED_ENV = ["DB2i_HOST", "DB2i_USER", "DB2i_PASS"] as const;
const SERVER = "ibmi-server";
export default (async () => {
return {
config: (cfg) => {
const ready = REQUIRED_ENV.every((name) => {
const value = process.env[name];
return typeof value === "string" && value.length > 0;
});
const server = cfg.mcp?.[SERVER];
if (server && typeof server === "object") {
(server as { enabled?: boolean }).enabled = ready;
}
},
};
}) satisfies Plugin;
+8
View File
@@ -0,0 +1,8 @@
{
"$schema": "https://opencode.ai/tui.json",
// OpenCode Quota: tuiCommandDisplay chooses whether native TUI command output appears in the session transcript or a local popup dialog.
// OpenCode Quota: loads the TUI sidebar, compact status, and local commands.
"plugin": [
"@slkiser/opencode-quota@latest"
]
}
+15 -2
View File
@@ -5,7 +5,7 @@ fi
# Load local environment secrets if the file exists
if [ -f "$HOME/.secrets" ]; then
set -a
set -a
source "$HOME/.secrets"
set +a
fi
@@ -29,11 +29,24 @@ if [[ -d $HOME/.scripts && ":$PATH:" != *":$PATH:"* ]]; then
export PATH=$PATH:$HOME/.scripts
fi
# Add opencode binaries to $PATH if they exist
if [[ -d $HOME/.opencode/bin && ":$PATH:" != *":$HOME/.opencode/bin:"* ]]; then
export PATH=$PATH:$HOME/.opencode/bin
fi
# Linux specific
# if [[ "$(uname -s)" == "Linux" ]]; then
# fi
# WSL specific
if [ -n "$IS_WSL" ] || [ -n "$WSL_DISTRO_NAME" ]; then
eval $(dbus-launch --sh-syntax 2>/dev/null) 2>/dev/null || true
eval $(printf '' | gnome-keyring-daemon --unlock 2>/dev/null) 2>/dev/null || true
export SSH_AUTH_SOCK
export SECRET_SERVICE_BUS_ADDRESS="unix:path=/run/user/$(id -u)/keyring/control"
fi
# MacOS specific
if [[ "$(uname -s)" == "Darwin" ]]; then
# Add python3.8 $PATH if installed and not already in $PATH
+57 -22
View File
@@ -1,38 +1,73 @@
# ZSH Plugin and Theme
The key to this setup is [GNU `stow`](https://www.gnu.org/software/stow/) a symlink manager. `stow` allows you to easily link the files in the repo directly to where these files would be in your home directory originally.
# Cole's Dotfiles
I prefer to manually install the my zsh theme and plugins. I like to the `~/.zsh` directory to store the repos of any dependencies I bring into my config.
Personal dotfiles for zsh, Neovim, and opencode, plus a few shell scripts. The setup is managed with [GNU `stow`](https://www.gnu.org/software/stow/), a symlink manager that links the files in this repo to their corresponding locations under the home directory.
# Prerequisites
The zsh theme and plugins are installed manually rather than through a plugin manager. The `~/.zsh` directory is used to hold the git repos of any shell dependencies.
## GNU `stow`
Install `stow` with your system's package manager.
## Repository layout
## Nerd Fonts
Make sure you get a nerd font [installed](https://github.com/ryanoasis/nerd-fonts) and [configured](https://github.com/romkatv/powerlevel10k?tab=readme-ov-file#meslo-nerd-font-patched-for-powerlevel10k) for your terminal emulators, text editors, and IDEs of choice.
## Powerlevel10k
```sh
git clone --depth=1 https://github.com/romkatv/powerlevel10k.git ~/.zsh/powerlevel10k
```text
.
├── .zshrc # zsh config: PATH, history, completions, prompt, aliases
├── .config/
│ ├── nvim/ # Neovim config (init.lua, lua/, after/, queries/)
│ └── opencode/ # opencode config (commands, plugins, MCP tools, rules)
└── .scripts/ # Standalone shell scripts (on $PATH)
└── hello.sh
```
## zsh-autosuggestions
Everything above is relative to the home directory, which is exactly what `stow .` expects.
## Prerequisites
### Required
- **GNU `stow`** — install with the system package manager (`brew install stow`, `apt install stow`, etc.).
- **A Nerd Font** — [install](https://github.com/ryanoasis/nerd-fonts) one and [configure](https://github.com/romkatv/powerlevel10k?tab=readme-ov-file#meslo-nerd-font-patched-for-powerlevel10k) it in the terminal, editor, and IDE of choice. Required for icons in the prompt and `lsd`.
### Shell theme and plugins
Clone into `~/.zsh/` so `.zshrc` picks them up automatically:
```sh
git clone --depth=1 https://github.com/zsh-users/zsh-autosuggestions ~/.zsh/zsh-autosuggestions
git clone --depth=1 https://github.com/romkatv/powerlevel10k.git ~/.zsh/powerlevel10k
git clone --depth=1 https://github.com/zsh-users/zsh-autosuggestions ~/.zsh/zsh-autosuggestions
```
# Configure a New Machine
1. Clone this repository to your home directory
### Optional
- **`lsd`** — drives the `ls`/`ll`/`lt` aliases in `.zshrc`. Without it, the aliases fall back to the system `ls`. ([github.com/lsd-rs/lsd](https://github.com/lsd-rs/lsd))
## Configure a new machine
1. Clone into the home directory:
```sh
git clone https://github.com/cole-maxwell1/dotfiles.git
git clone https://github.com/cole-maxwell1/dotfiles.git ~/dotfiles
```
2. Run GNU stow
2. Symlink the dotfiles into place with stow:
```sh
cd dotfiles && stow .
cd ~/dotfiles && stow .
```
3. Make scripts executable for current user
3. Make the scripts executable:
```sh
chmod -R u+x ~/dotfiles/.scripts/
```
```
4. If this is the first run with Powerlevel10k, generate the prompt config:
```sh
p10k configure
```
5. Restart the shell (or `exec zsh`) to load the new config.
## Unlink or uninstall
To remove the symlinks without deleting the repo:
```sh
cd ~/dotfiles && stow -D .
```
Running `stow .` again re-creates them.
## Secrets
If `~/.secrets` exists, `.zshrc` sources it near the top of the file so environment variables (API keys, tokens, etc.) are exported into the shell. This file is intentionally **not** part of the repo — create it locally and keep it out of version control.