mirror of
https://github.com/cole-maxwell1/dotfiles.git
synced 2026-10-27 16:32:49 -05:00
Compare commits
13
Commits
57821ba227
..
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0d4ba3e291 | ||
|
|
12a524a6c8 | ||
|
|
3b797f3be1 | ||
|
|
3a05a40cfd | ||
|
|
6c7604b218 | ||
|
|
2c4e6dbf95 | ||
|
|
8e91bb9945 | ||
|
|
dfbb071b35 | ||
|
|
a4fc747df2 | ||
|
|
71f73fccbc | ||
|
|
3fbf0ea3c8 | ||
|
|
0729882658 | ||
|
|
5025257893 |
@@ -1,3 +1,20 @@
|
|||||||
|
## Tool Preference: File Operations
|
||||||
|
|
||||||
|
Use the following tools instead of their bash equivalents. This is a hard rule, not a suggestion.
|
||||||
|
|
||||||
|
| Instead of | Use |
|
||||||
|
| ----------------------- | ---------------------------------- |
|
||||||
|
| `cat file` | Read tool |
|
||||||
|
| `sed -n '10,20p' file` | Read tool with line range |
|
||||||
|
| `grep pattern file` | Grep tool |
|
||||||
|
| `find . -name "*.go"` | Glob tool |
|
||||||
|
| `sed -i 's/x/y/' file` | Edit tool |
|
||||||
|
| `awk '{print $1}' file` | Read tool, then process in-context |
|
||||||
|
| `head` / `tail` file | Read tool with line range |
|
||||||
|
| `ls`, `wc`, `sort` file | Read / Glob / List tool |
|
||||||
|
|
||||||
|
Only fall back to bash text-processing utilities (`awk`, `sed`, piped `grep`) when the operation genuinely requires shell composition the native tools cannot express — e.g., multi-stage pipelines, process substitution, or operating on command output rather than files. Do not use `cat`/`head`/`tail` to inspect file contents under any circumstance; the Read tool is strictly better for this and does not require permission approval. Note that these bash commands now require permission approval in the config — prefer the native tools to avoid the prompt.
|
||||||
|
|
||||||
# Response Tone
|
# 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.
|
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.
|
||||||
@@ -13,4 +30,9 @@
|
|||||||
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.
|
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
|
# Git
|
||||||
|
|
||||||
When asked, write professional Git commit messages for requested changes. NEVER add an AI co-author tag to commit messages.
|
When asked, write professional Git commit messages for requested changes. NEVER add an AI co-author tag to commit messages.
|
||||||
|
|
||||||
|
# Scratch Workspace
|
||||||
|
|
||||||
|
`/tmp/opencode` is the designated scratch directory for temporary files, downloaded artifacts, intermediate build outputs, logs, and similar transient data. Default to this location for any file that does not belong in the working tree. Avoid polluting the repository with throwaway scripts, fixtures, or downloads.
|
||||||
|
|||||||
@@ -27,4 +27,8 @@ Strictly adhere to the following Conventional Commit specification rules:
|
|||||||
- `ops`: Infrastructure, CI/CD pipelines, deployment, or operational scripts.
|
- `ops`: Infrastructure, CI/CD pipelines, deployment, or operational scripts.
|
||||||
- `chore`: Maintenance tasks (e.g., updating `.gitignore`, repo setup).
|
- `chore`: Maintenance tasks (e.g., updating `.gitignore`, repo setup).
|
||||||
|
|
||||||
|
### Message Body
|
||||||
|
|
||||||
|
The message body should provide a detailed description of the changes, including any relevant context or reasoning.
|
||||||
|
|
||||||
Provide ONLY the proposed commit message inside a raw code block, followed by a request for my approval.
|
Provide ONLY the proposed commit message inside a raw code block, followed by a request for my approval.
|
||||||
|
|||||||
@@ -0,0 +1,77 @@
|
|||||||
|
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
|
||||||
|
|
||||||
|
count_total_records:
|
||||||
|
source: ibmi-system
|
||||||
|
description: >-
|
||||||
|
Return the total row count for a table by reading the Db2 for i
|
||||||
|
catalog statistic QSYS2.SYSTABLESTAT.NUMBER_ROWS. Optionally
|
||||||
|
provide table_schema to disambiguate tables that share a name
|
||||||
|
across libraries.
|
||||||
|
parameters:
|
||||||
|
- name: table_name
|
||||||
|
type: string
|
||||||
|
description: "The name of the table to count records for."
|
||||||
|
required: true
|
||||||
|
- name: table_schema
|
||||||
|
type: string
|
||||||
|
description: "Schema/library holding the table. Example: 'MYLIB'."
|
||||||
|
required: true
|
||||||
|
statement: |
|
||||||
|
SELECT
|
||||||
|
TABLE_SCHEMA,
|
||||||
|
TABLE_NAME,
|
||||||
|
NUMBER_ROWS AS TOTAL_RECORDS,
|
||||||
|
LAST_USED_TIMESTAMP
|
||||||
|
FROM
|
||||||
|
QSYS2.SYSTABLESTAT
|
||||||
|
WHERE
|
||||||
|
TABLE_NAME = UPPER(:table_name)
|
||||||
|
AND (:table_schema IS NULL OR TABLE_SCHEMA = UPPER(:table_schema))
|
||||||
|
ORDER BY
|
||||||
|
TABLE_SCHEMA
|
||||||
|
|
||||||
|
toolsets:
|
||||||
|
catalog:
|
||||||
|
title: "Catalog Tools"
|
||||||
|
description: >-
|
||||||
|
System catalog introspection tools (QSYS2.SYSCOLUMNS, QSYS2.SYSTABLESTAT).
|
||||||
|
tools:
|
||||||
|
- get_column_info
|
||||||
|
- count_total_records
|
||||||
@@ -1,43 +0,0 @@
|
|||||||
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
|
|
||||||
+114
-20
@@ -10,58 +10,142 @@
|
|||||||
"git diff *": "allow",
|
"git diff *": "allow",
|
||||||
"git show *": "allow",
|
"git show *": "allow",
|
||||||
"git push *": "ask",
|
"git push *": "ask",
|
||||||
// GNU Utils
|
// Privilege escalation
|
||||||
"sudo *": "deny",
|
"sudo *": "deny",
|
||||||
|
"su *": "deny",
|
||||||
|
"doas *": "deny",
|
||||||
|
// GNU Util
|
||||||
"curl *": "ask",
|
"curl *": "ask",
|
||||||
"wget *": "ask",
|
"wget *": "ask",
|
||||||
"diff *": "allow",
|
"diff *": "allow",
|
||||||
"npm *": "allow",
|
|
||||||
"rm *": "ask",
|
"rm *": "ask",
|
||||||
"rm -rf *": "deny",
|
"rm -rf *": "deny",
|
||||||
"grep *": "allow",
|
|
||||||
"sort *": "allow",
|
"sort *": "allow",
|
||||||
"head *": "allow",
|
|
||||||
"tail *": "allow",
|
|
||||||
"echo *": "allow",
|
|
||||||
"which *": "allow",
|
"which *": "allow",
|
||||||
"find *": "allow",
|
|
||||||
"ls *": "allow",
|
"ls *": "allow",
|
||||||
"wc *": "allow",
|
"wc *": "allow",
|
||||||
|
"head *": "allow",
|
||||||
|
"tail *": "allow",
|
||||||
// Go
|
// Go
|
||||||
"go build *": "allow",
|
"go build *": "allow",
|
||||||
"go test *": "allow",
|
"go test *": "allow",
|
||||||
"go vet *": "allow",
|
"go vet *": "allow",
|
||||||
"go mod tidy": "allow",
|
"go mod tidy": "allow",
|
||||||
"go mod download": "allow",
|
"go mod download": "allow",
|
||||||
|
"gofmt *": "allow",
|
||||||
|
// Node.js
|
||||||
|
"npm ci": "allow",
|
||||||
|
"npm test": "allow",
|
||||||
|
"npm run build": "allow",
|
||||||
|
"npm run lint": "allow",
|
||||||
|
"npm run typecheck": "allow",
|
||||||
|
"npm run check": "allow",
|
||||||
|
"npm ls *": "allow",
|
||||||
|
"npm outdated": "allow",
|
||||||
|
"npm audit *": "allow",
|
||||||
|
"npm run test:unit": "allow",
|
||||||
|
"npm run test:integration": "allow",
|
||||||
|
"npm run test:e2e": "allow",
|
||||||
|
"npm run type-check": "allow",
|
||||||
|
"npm run package:dev": "allow",
|
||||||
|
"npx vitest run *": "allow",
|
||||||
|
"npx *": "ask",
|
||||||
// Python
|
// Python
|
||||||
"python -m unittest *": "allow",
|
"python -m unittest *": "allow",
|
||||||
"python -m py_compile": "allow",
|
"python -m py_compile": "allow",
|
||||||
|
"python3 -m unittest *": "allow",
|
||||||
|
"python3 -m py_compile": "allow",
|
||||||
|
"python -m venv .venv": "allow",
|
||||||
"python3 -m venv .venv": "allow",
|
"python3 -m venv .venv": "allow",
|
||||||
"source .venv/bin/activate": "allow",
|
"source .venv/bin/activate": "allow",
|
||||||
"ruff check *": "allow",
|
"ruff check *": "allow",
|
||||||
"ruff format --check *": "allow",
|
"ruff format --check *": "allow",
|
||||||
|
"ruff format *": "ask",
|
||||||
// Dotnet
|
// Dotnet
|
||||||
"dotnet *": "allow",
|
"dotnet build *": "allow",
|
||||||
|
"dotnet test *": "allow",
|
||||||
|
"dotnet restore *": "allow",
|
||||||
|
"dotnet format *": "allow",
|
||||||
|
"dotnet vet *": "allow",
|
||||||
|
"dotnet workload *": "ask",
|
||||||
|
"dotnet run *": "allow",
|
||||||
// Docker
|
// Docker
|
||||||
"docker ps *": "allow",
|
"docker ps *": "allow",
|
||||||
"docker logs *": "allow",
|
"docker logs *": "allow",
|
||||||
"docker compose logs *": "allow",
|
"docker compose logs *": "allow",
|
||||||
|
"docker manifest inspect": "allow",
|
||||||
|
// Ansible
|
||||||
|
"ansible-playbook --version": "allow",
|
||||||
|
"ansible-playbook --syntax-check *": "allow",
|
||||||
|
"ansible-lint --version": "allow",
|
||||||
|
// OpenTofu
|
||||||
|
"tofu version": "allow",
|
||||||
|
"tofu init -backend=false": "allow",
|
||||||
|
"tofu validate *": "allow",
|
||||||
|
"tofu fmt -check *": "allow",
|
||||||
|
"tofu plan *": "allow",
|
||||||
},
|
},
|
||||||
"read": {
|
"read": {
|
||||||
|
"/tmp/opencode": "allow",
|
||||||
|
"/tmp/opencode/*": "allow",
|
||||||
|
"~/.ssh/known_hosts": "allow",
|
||||||
|
// Env / secrets — recursive + variants
|
||||||
".env": "deny",
|
".env": "deny",
|
||||||
|
".env.*": "deny",
|
||||||
|
"**/.env": "deny",
|
||||||
|
"**/.env.*": "deny",
|
||||||
".secrets": "deny",
|
".secrets": "deny",
|
||||||
|
"**/.secrets": "deny",
|
||||||
|
".secrets.*": "deny",
|
||||||
|
// Key material
|
||||||
"*.key": "deny",
|
"*.key": "deny",
|
||||||
"*.pem": "deny",
|
"*.pem": "deny",
|
||||||
|
"*.p12": "deny",
|
||||||
|
"*.pfx": "deny",
|
||||||
|
"*.keystore": "deny",
|
||||||
|
"*.jks": "deny",
|
||||||
|
"*.kdbx": "deny", // KeePass
|
||||||
|
// SSH keys — all algorithms incl. FIDO
|
||||||
"id_rsa": "deny",
|
"id_rsa": "deny",
|
||||||
|
"id_ecdsa": "deny",
|
||||||
"id_ed25519": "deny",
|
"id_ed25519": "deny",
|
||||||
|
"id_dsa": "deny",
|
||||||
|
"id_ecdsa_sk": "deny",
|
||||||
|
"id_ed25519_sk": "deny",
|
||||||
|
"~/.ssh/id_*": "deny", // catch-all absolute
|
||||||
|
"~/.ssh/config": "deny", // may contain HostName + IdentityFile
|
||||||
|
// Cloud / service credentials
|
||||||
".aws/credentials": "deny",
|
".aws/credentials": "deny",
|
||||||
"~/.ssh/known_hosts": "allow",
|
"~/.aws/credentials": "deny",
|
||||||
|
"~/.aws/config": "deny",
|
||||||
|
"~/.config/gcloud/*": "deny",
|
||||||
|
"~/.kube/config": "deny",
|
||||||
|
"~/.npmrc": "deny", // often contains _authToken
|
||||||
|
"~/.pypirc": "deny",
|
||||||
|
"~/.netrc": "deny",
|
||||||
|
"~/.docker/config.json": "deny",
|
||||||
|
// Misc
|
||||||
|
".npmrc": "deny", // project-local tokens
|
||||||
|
"**/.npmrc": "deny",
|
||||||
|
},
|
||||||
|
"edit": {
|
||||||
|
"/tmp/opencode": "allow",
|
||||||
|
"/tmp/opencode/*": "allow",
|
||||||
|
// Explicit deny for dotfiles reduces accidental writes
|
||||||
|
".env*": "deny",
|
||||||
|
".git/*": "deny",
|
||||||
|
"**/.git/*": "deny",
|
||||||
|
".hooks/*": "ask", // git hook injection
|
||||||
},
|
},
|
||||||
"grep": "allow",
|
"grep": "allow",
|
||||||
"glob": "allow",
|
"glob": "allow",
|
||||||
"question": "allow",
|
"question": "allow",
|
||||||
"lsp": "allow",
|
"lsp": "allow",
|
||||||
"websearch": "allow",
|
"websearch": "allow",
|
||||||
|
"webfetch": "allow",
|
||||||
|
"task": "allow",
|
||||||
|
"todowrite": "allow",
|
||||||
|
"skill": "allow",
|
||||||
},
|
},
|
||||||
"mcp": {
|
"mcp": {
|
||||||
"zai-mcp-server": {
|
"zai-mcp-server": {
|
||||||
@@ -95,8 +179,18 @@
|
|||||||
},
|
},
|
||||||
"playwright": {
|
"playwright": {
|
||||||
"type": "local",
|
"type": "local",
|
||||||
|
"enabled": false,
|
||||||
"command": ["npx", "@playwright/mcp@latest"],
|
"command": ["npx", "@playwright/mcp@latest"],
|
||||||
|
},
|
||||||
|
"chrome-devtools": {
|
||||||
|
"type": "local",
|
||||||
|
"enabled": false,
|
||||||
|
"command": ["npx", "-y", "chrome-devtools-mcp@latest"],
|
||||||
|
},
|
||||||
|
"primevue": {
|
||||||
|
"type": "local",
|
||||||
"enabled": true,
|
"enabled": true,
|
||||||
|
"command": ["npx", "-y", "@primevue/mcp"],
|
||||||
},
|
},
|
||||||
"ibmi-server": {
|
"ibmi-server": {
|
||||||
"type": "local",
|
"type": "local",
|
||||||
@@ -104,8 +198,9 @@
|
|||||||
"npx",
|
"npx",
|
||||||
"-y",
|
"-y",
|
||||||
"@ibm/ibmi-mcp-server@latest",
|
"@ibm/ibmi-mcp-server@latest",
|
||||||
|
"--builtin-tools",
|
||||||
"--tools",
|
"--tools",
|
||||||
"{env:HOME}/.config/opencode/mcp/ibmi-mcp-server/tools/custom-tools.yaml",
|
"{env:HOME}/.config/opencode/mcp/ibmi-mcp-server/tools",
|
||||||
],
|
],
|
||||||
"enabled": false,
|
"enabled": false,
|
||||||
"environment": {
|
"environment": {
|
||||||
@@ -113,7 +208,8 @@
|
|||||||
"DB2i_USER": "{env:DB2i_USER}",
|
"DB2i_USER": "{env:DB2i_USER}",
|
||||||
"DB2i_PASS": "{env:DB2i_PASS}",
|
"DB2i_PASS": "{env:DB2i_PASS}",
|
||||||
"DB2i_PORT": "8076",
|
"DB2i_PORT": "8076",
|
||||||
"DB2i_IGNORE_UNAUTHORIZED": "true",
|
"YAML_ALLOW_DUPLICATE_SOURCES": "true",
|
||||||
|
"SELECTED_TOOLSETS": "catalog",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -128,23 +224,21 @@
|
|||||||
},
|
},
|
||||||
"lsp": true,
|
"lsp": true,
|
||||||
"formatter": true,
|
"formatter": true,
|
||||||
"model": "zai-coding-plan/glm-5.2",
|
"model": "openai/gpt-5.6-sol",
|
||||||
"small_model": "zai-coding-plan/glm-4.5-air",
|
"small_model": "openai/gpt-5.6-luna",
|
||||||
"agent": {
|
"agent": {
|
||||||
"explore": {
|
"explore": {
|
||||||
"model": "zai-coding-plan/glm-4.5-air",
|
"model": "openai/gpt-5.6-luna",
|
||||||
},
|
|
||||||
"scout": {
|
|
||||||
"model": "zai-coding-plan/glm-4.5-air",
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"share": "disabled",
|
"share": "disabled",
|
||||||
"snapshot": true,
|
"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"],
|
"plugin": ["./plugins/ibmi-gate.ts", "@slkiser/opencode-quota@latest"],
|
||||||
"provider": {
|
"provider": {
|
||||||
// Detected zai authentication; opencode-quota added this global provider declaration.
|
|
||||||
"zai": {},
|
"zai": {},
|
||||||
|
"openai": {},
|
||||||
|
},
|
||||||
|
"experimental": {
|
||||||
|
"disable_paste_summary": true,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,21 @@
|
|||||||
|
---
|
||||||
|
name: bash
|
||||||
|
description: Shell scripting conventions (set -euo pipefail, quoting, shellcheck). Use when editing .sh or .bash files.
|
||||||
|
---
|
||||||
|
|
||||||
|
# Bash Conventions
|
||||||
|
|
||||||
|
## Robustness
|
||||||
|
- Begin scripts with `#!/usr/bin/env bash` and `set -euo pipefail`.
|
||||||
|
- Pass `shellcheck` cleanly; treat its warnings as bugs.
|
||||||
|
|
||||||
|
## Quoting and expansion
|
||||||
|
- Double-quote all variable expansions (`"$var"`, `"${array[@]}"`).
|
||||||
|
- Prefer `[[ ]]` over `[ ]`; use arrays for argument lists rather than space-separated strings.
|
||||||
|
- Avoid `eval`; do not parse `ls` output.
|
||||||
|
|
||||||
|
## Structure
|
||||||
|
- Declare function-local variables with `local`.
|
||||||
|
- Use `trap` to clean up temporary files and directories.
|
||||||
|
- Use `printf` over `echo` for predictable output.
|
||||||
|
- Prefer a `$TMPDIR`-based path over hardcoded `/tmp` literals.
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
---
|
||||||
|
name: csharp
|
||||||
|
description: C# and .NET coding conventions. Use when reading, writing, or reviewing .cs, .razor, .csproj, or .sln files, or any .NET (C#) code.
|
||||||
|
---
|
||||||
|
|
||||||
|
# C# / .NET Conventions
|
||||||
|
|
||||||
|
Follow the Microsoft [Common C# code conventions](https://learn.microsoft.com/en-us/dotnet/csharp/fundamentals/coding-style/coding-conventions) and [.NET naming guidelines](https://learn.microsoft.com/en-us/dotnet/standard/design-guidelines/naming-guidelines). Match patterns already established in the target codebase.
|
||||||
|
|
||||||
|
## Structure
|
||||||
|
- Use file-scoped namespaces (`namespace Example.Services;`).
|
||||||
|
- Nullable reference types are enabled solution-wide; do not suppress warnings without cause.
|
||||||
|
- Use `record` types for DTOs and data carriers.
|
||||||
|
- Use `required` / `init`-only properties for immutable domain models.
|
||||||
|
- Use primary constructors for services and repositories that take injected dependencies.
|
||||||
|
- Mark classes `sealed` by default unless inheritance is intended.
|
||||||
|
- Prefix interfaces with `I` (`IRenderer`, `IRepository`).
|
||||||
|
|
||||||
|
## Expressions
|
||||||
|
- Use raw string literals (`""" ... """`) for multi-line SQL.
|
||||||
|
- Use `[GeneratedRegex]` partial methods for regex.
|
||||||
|
- Use collection expressions (`[]`, `[a, b]`).
|
||||||
|
|
||||||
|
## Async and cancellation
|
||||||
|
- Every async method takes `CancellationToken ct = default` and honors it cooperatively (`ct.ThrowIfCancellationRequested()` in long loops).
|
||||||
|
- Never drop the token when calling downstream async APIs.
|
||||||
|
|
||||||
|
## Logging
|
||||||
|
- Inject `ILogger<T>` and use structured logging with named parameters:
|
||||||
|
`_logger.LogInformation("Generated {Count} transactions", count);`
|
||||||
|
|
||||||
|
## Naming
|
||||||
|
- `PascalCase` for types and members.
|
||||||
|
- `_camelCase` for private fields.
|
||||||
|
|
||||||
|
## Testing
|
||||||
|
- Use xUnit. Mirror the source structure under a `Tests/` directory with a `Tests` suffix on file names.
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
---
|
||||||
|
name: go
|
||||||
|
description: Idiomatic Go conventions. Use when editing .go files or go.mod/go.sum.
|
||||||
|
---
|
||||||
|
|
||||||
|
# Go Conventions
|
||||||
|
|
||||||
|
Write strictly idiomatic Go following standard formatting and best practices.
|
||||||
|
|
||||||
|
## Formatting and style
|
||||||
|
- `gofmt` / `goimports` formatting is mandatory.
|
||||||
|
- Follow [Effective Go](https://go.dev/doc/effective_go) and the [Go Code Review Comments](https://github.com/golang/go/wiki/CodeReviewComments).
|
||||||
|
|
||||||
|
## Design
|
||||||
|
- Accept `context.Context` as the first parameter on functions doing I/O or long work; honor cancellation.
|
||||||
|
- Compose via small interfaces; accept interfaces, return structs.
|
||||||
|
- Wire dependencies explicitly via constructor injection; avoid package-level mutable globals and DI frameworks.
|
||||||
|
- Return errors explicitly; wrap with `%w` (`fmt.Errorf("do thing: %w", err)`); classify with `errors.Is` / `errors.As`; never discard errors.
|
||||||
|
|
||||||
|
## Testing
|
||||||
|
- Write table-driven tests in `_test.go` using the standard `testing` package.
|
||||||
|
- Use `t.Run` for subtests; report failures with `t.Errorf` / `t.Fatalf`.
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
---
|
||||||
|
name: htmx
|
||||||
|
description: HTMX v2 progressive-enhancement and hypermedia patterns.
|
||||||
|
---
|
||||||
|
|
||||||
|
# HTMX Conventions
|
||||||
|
|
||||||
|
Follow [HTMX](https://htmx.org) v2 and [Hypermedia Systems](https://hypermedia.systems/book/contents/) best practices.
|
||||||
|
|
||||||
|
## Philosophy
|
||||||
|
- Treat the server as the source of truth; return HTML fragments, not JSON, for hypermedia interactions.
|
||||||
|
- Prefer `hx-*` attributes over client-side JavaScript; reach for client JavaScript only when htmx cannot express the interaction.
|
||||||
|
- Build progressively: ensure pages function without JavaScript, then enhance with htmx.
|
||||||
|
|
||||||
|
## Patterns
|
||||||
|
- Target fragments with `hx-target` and swap with `hx-swap` (prefer `outerHTML` or `innerHTML` as appropriate).
|
||||||
|
- Return partial templates or fragments from endpoints; treat partials as isolated components that receive data via the page model.
|
||||||
|
- Use Out-of-Band Swaps (`hx-swap-oob`) to update multiple regions from a single response.
|
||||||
|
- Handle errors with a 4xx/5xx partial or `hx-on::responseError`.
|
||||||
|
|
||||||
|
## Keep clean
|
||||||
|
- Return semantic HTML from endpoints; avoid mixing `hx-*` attributes with conflicting client-side handlers.
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
---
|
||||||
|
name: primevue
|
||||||
|
description: PrimeVue v4 component patterns and Tailwind integration. Use when writing or styling PrimeVue components.
|
||||||
|
---
|
||||||
|
|
||||||
|
# PrimeVue v4 Conventions
|
||||||
|
|
||||||
|
Assume PrimeVue v4 is installed when answering Vue questions. Use the Composition API with `<script setup>`.
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
- Register components via the PrimeVue plugin or import per component.
|
||||||
|
- Prefer official presets and theming over hand-rolled overrides.
|
||||||
|
|
||||||
|
## Tailwind integration
|
||||||
|
- TailwindCSS is available; when needed, apply utility classes through the component passthrough (`pt`) or the unstyled/preset mechanism rather than overriding internal DOM.
|
||||||
|
- Keep utility usage consistent with the project's styling layer.
|
||||||
|
|
||||||
|
## API detail
|
||||||
|
- For component props, events, slots, and passthrough (`pt`) keys, fetch the PrimeVue LLM docs index on demand: `https://v4.primevue.org/llms/llms.txt`. Follow the relevant component link for the exact signature.
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
---
|
||||||
|
name: python
|
||||||
|
description: Python conventions (PEP 8, ruff, type hints). Use when editing .py files.
|
||||||
|
---
|
||||||
|
|
||||||
|
# Python Conventions
|
||||||
|
|
||||||
|
## Style
|
||||||
|
- Follow PEP 8; run `ruff check` and `ruff format` for linting and formatting.
|
||||||
|
- Let ruff manage line length and import ordering; do not hand-format against it.
|
||||||
|
|
||||||
|
## Typing
|
||||||
|
- Add type hints on all function signatures; prefer modern syntax (`list[int]`, `X | None`) on supported Python versions.
|
||||||
|
- Use `dataclasses` (or Pydantic where validation is required) for structured data.
|
||||||
|
- Prefer an explicit exception hierarchy over bare `except:`.
|
||||||
|
|
||||||
|
## Idioms
|
||||||
|
- Prefer `pathlib.Path` over `os.path`.
|
||||||
|
- Use f-strings for interpolation; use the `logging` module with structured handlers instead of `print` in libraries.
|
||||||
|
- Prefer comprehensions and generator expressions over manual loops where readability is preserved.
|
||||||
|
|
||||||
|
## Testing
|
||||||
|
- Use `unittest` (or `pytest` if the project adopts it); mirror the source layout under a `tests/` directory.
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
---
|
||||||
|
name: typescript
|
||||||
|
description: TypeScript conventions (Google style, strict mode, no any). Use when editing .ts or .tsx files, or tsconfig/jsconfig files.
|
||||||
|
---
|
||||||
|
|
||||||
|
# TypeScript Conventions
|
||||||
|
|
||||||
|
Follow the [Google TypeScript Style Guide](https://google.github.io/styleguide/tsguide.html).
|
||||||
|
|
||||||
|
## Typing
|
||||||
|
- `strict: true` in tsconfig; no implicit or explicit `any`.
|
||||||
|
- Strictly type all variables, functions, and interfaces.
|
||||||
|
- Prefer `unknown` over `any` when the type is genuinely unknown, then narrow.
|
||||||
|
- Prefer discriminated unions and type narrowing over runtime checks.
|
||||||
|
- Declare explicit return types on public and shared APIs.
|
||||||
|
|
||||||
|
## Style
|
||||||
|
- Prefer `interface` for object shapes; use `type` for unions and mapped types.
|
||||||
|
- Use `const` by default; `let` only when reassignment is required; never `var`.
|
||||||
|
- Prefer async/await over raw `.then`/`.catch` chains.
|
||||||
|
|
||||||
|
## Project overrides
|
||||||
|
A project's tsconfig or eslint config may relax rules (for example, disable `@typescript-eslint/no-explicit-any`); project configuration overrides these defaults.
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
---
|
||||||
|
name: vue
|
||||||
|
description: Vue 3 (Composition API, script setup, Pinia, Vue Router) conventions. Use when editing .vue files.
|
||||||
|
---
|
||||||
|
|
||||||
|
# Vue 3 Conventions
|
||||||
|
|
||||||
|
Use Vue 3 with the Composition API exclusively.
|
||||||
|
|
||||||
|
## Components
|
||||||
|
- Use `<script setup lang="ts">`; avoid the Options API.
|
||||||
|
- Type props with `defineProps<T>()` and emits with `defineEmits<T>()`.
|
||||||
|
- Keep components focused and small; organize by feature directory.
|
||||||
|
|
||||||
|
## State and routing
|
||||||
|
- Use Pinia setup stores (`defineStore('name', () => { ... })`) for shared state.
|
||||||
|
- Cancel superseded fetches with `AbortController`; expose loading and error state from stores.
|
||||||
|
- Use Vue Router with route guards for protected views.
|
||||||
|
|
||||||
|
## Reactivity
|
||||||
|
- Prefer `ref` / `reactive` and `computed` over manual watchers.
|
||||||
|
- Clean up side effects (timers, listeners, observers) in `onScopeDispose` or `onUnmounted`.
|
||||||
|
|
||||||
|
## API detail
|
||||||
|
- For exact reactivity, built-in component, and compiler behavior, fetch the Vue LLM docs index on demand: `https://vuejs.org/llms.txt`. Follow the relevant guide link for the specific API.
|
||||||
Executable
+135
@@ -0,0 +1,135 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
#
|
||||||
|
# iso2usb-macos.sh - Write an ISO image to a USB drive on macOS.
|
||||||
|
#
|
||||||
|
# Usage:
|
||||||
|
# ./iso2usb-macos.sh [--prompt|-p] /path/to/input.iso
|
||||||
|
#
|
||||||
|
# Options:
|
||||||
|
# -p, --prompt Skip El Torito auto-detection and go straight to the
|
||||||
|
# direct-write Y/N prompt with no pre-selected default.
|
||||||
|
#
|
||||||
|
# Requires: hdiutil, diskutil, dd (all built into macOS). Must be run with
|
||||||
|
# sudo privileges for the dd step (the script will prompt when needed).
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
SKIP_DETECT=0
|
||||||
|
ISO_PATH=""
|
||||||
|
|
||||||
|
while [[ $# -gt 0 ]]; do
|
||||||
|
case "$1" in
|
||||||
|
-p|--prompt)
|
||||||
|
SKIP_DETECT=1
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
-*)
|
||||||
|
echo "Unknown option: $1"
|
||||||
|
echo "Usage: $0 [--prompt|-p] /path/to/input.iso"
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
ISO_PATH="$1"
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
if [[ -z "$ISO_PATH" ]]; then
|
||||||
|
echo "Usage: $0 [--prompt|-p] /path/to/input.iso"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ ! -f "$ISO_PATH" ]]; then
|
||||||
|
echo "Error: file not found: $ISO_PATH"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# List external/removable disks only, to reduce risk of selecting an internal drive.
|
||||||
|
echo "Available external disks:"
|
||||||
|
echo "--------------------------"
|
||||||
|
diskutil list external
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
read -rp "Enter the disk identifier to write to (e.g. disk4): " DISK_ID
|
||||||
|
|
||||||
|
# Normalize input in case user includes /dev/ prefix.
|
||||||
|
DISK_ID="${DISK_ID#/dev/}"
|
||||||
|
DISK_PATH="/dev/${DISK_ID}"
|
||||||
|
RDISK_PATH="/dev/r${DISK_ID}"
|
||||||
|
|
||||||
|
if [[ ! -e "$DISK_PATH" ]]; then
|
||||||
|
echo "Error: $DISK_PATH does not exist."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
DISK_INFO="$(diskutil info "$DISK_PATH")"
|
||||||
|
DISK_SIZE="$(echo "$DISK_INFO" | grep "Disk Size" | sed -E 's/.*Disk Size:[[:space:]]*//; s/[[:space:]]*\(.*//')"
|
||||||
|
# Not all diskutil info output includes a "Disk Size" field (varies by
|
||||||
|
# identifier type, e.g. whole-disk vs partition). Fall back to "Total Size"
|
||||||
|
# if the first lookup came back empty.
|
||||||
|
[[ -z "$DISK_SIZE" ]] && DISK_SIZE="$(echo "$DISK_INFO" | grep "Total Size" | sed -E 's/.*Total Size:[[:space:]]*//; s/[[:space:]]*\(.*//')"
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "Selected device: $DISK_PATH (${DISK_SIZE:-unknown size})"
|
||||||
|
echo "$DISK_INFO" | grep -E "Device / Media Name|Protocol|Total Size|Removable Media"
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "WARNING: all data on $DISK_PATH will be destroyed."
|
||||||
|
read -rp "Type the disk identifier again to confirm (e.g. disk4): " CONFIRM_ID
|
||||||
|
if [[ "$CONFIRM_ID" != "$DISK_ID" ]]; then
|
||||||
|
echo "Confirmation did not match. Aborting."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
WORKDIR="$(mktemp -d)"
|
||||||
|
trap 'rm -rf "$WORKDIR"' EXIT
|
||||||
|
|
||||||
|
IMG_PATH=""
|
||||||
|
|
||||||
|
# Check for an El Torito boot record to determine if the ISO is hybrid.
|
||||||
|
# The boot record volume descriptor lives at sector 17 (byte offset 0x8800).
|
||||||
|
# Byte 0 of that sector is 0x00 (boot record type), followed by the string
|
||||||
|
# "CD001", followed by the boot system identifier. Hybrid/El Torito ISOs
|
||||||
|
# carry "EL TORITO SPECIFICATION" in that identifier field.
|
||||||
|
is_hybrid_iso() {
|
||||||
|
local iso="$1"
|
||||||
|
dd if="$iso" bs=1 skip=34823 count=23 2>/dev/null | grep -aq "EL TORITO SPECIFICATION"
|
||||||
|
}
|
||||||
|
|
||||||
|
DEFAULT_DIRECT=""
|
||||||
|
if [[ "$SKIP_DETECT" -eq 1 ]]; then
|
||||||
|
echo "Skipping El Torito auto-detection (--prompt set)."
|
||||||
|
else
|
||||||
|
echo "Inspecting ISO for El Torito hybrid boot support..."
|
||||||
|
if is_hybrid_iso "$ISO_PATH"; then
|
||||||
|
echo "Detected: hybrid El Torito/ISO9660 image. Direct dd write should work."
|
||||||
|
DEFAULT_DIRECT="Y"
|
||||||
|
else
|
||||||
|
echo "No El Torito boot record found. This ISO is likely not hybrid;"
|
||||||
|
echo "converting via hdiutil is recommended."
|
||||||
|
DEFAULT_DIRECT="N"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
read -rp "Attempt direct write of the raw ISO without conversion? [${DEFAULT_DIRECT:-y/N}]: " DIRECT
|
||||||
|
DIRECT="${DIRECT:-$DEFAULT_DIRECT}"
|
||||||
|
if [[ "$DIRECT" =~ ^[Yy]$ ]]; then
|
||||||
|
IMG_PATH="$ISO_PATH"
|
||||||
|
else
|
||||||
|
echo "Converting ISO to UDRW image..."
|
||||||
|
hdiutil convert -format UDRW -o "${WORKDIR}/output.img" "$ISO_PATH"
|
||||||
|
# hdiutil appends .dmg to the output filename even though it is raw content.
|
||||||
|
IMG_PATH="${WORKDIR}/output.img.dmg"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Unmounting $DISK_PATH..."
|
||||||
|
diskutil unmountDisk "$DISK_PATH"
|
||||||
|
|
||||||
|
echo "Writing image to $RDISK_PATH. This may take several minutes..."
|
||||||
|
sudo dd if="$IMG_PATH" of="$RDISK_PATH" bs=1m status=progress
|
||||||
|
|
||||||
|
echo "Ejecting $DISK_PATH..."
|
||||||
|
diskutil eject "$DISK_PATH"
|
||||||
|
|
||||||
|
echo "Done."
|
||||||
@@ -25,7 +25,7 @@ if [[ ":$PATH:" != *":$HOME/.local/bin:"* ]]; then
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
# Add script binaries to $PATH if they exist
|
# Add script binaries to $PATH if they exist
|
||||||
if [[ -d $HOME/.scripts && ":$PATH:" != *":$PATH:"* ]]; then
|
if [[ -d $HOME/.scripts && ":$PATH:" != *":$HOME/.scripts:"* ]]; then
|
||||||
export PATH=$PATH:$HOME/.scripts
|
export PATH=$PATH:$HOME/.scripts
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@@ -53,6 +53,14 @@ if [[ "$(uname -s)" == "Darwin" ]]; then
|
|||||||
if [[ -d $HOME/Library/Python/3.8/bin && ":$PATH:" != *":$HOME/Library/Python/3.8/bin:"* ]]; then
|
if [[ -d $HOME/Library/Python/3.8/bin && ":$PATH:" != *":$HOME/Library/Python/3.8/bin:"* ]]; then
|
||||||
export PATH=$PATH:$HOME/Library/Python/3.8/bin
|
export PATH=$PATH:$HOME/Library/Python/3.8/bin
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# Bitwarden SSH agent (only if the application is installed and the socket file exists)
|
||||||
|
local bw_app="/Applications/Bitwarden.app"
|
||||||
|
local bw_sock="$HOME/.bitwarden-ssh-agent.sock"
|
||||||
|
|
||||||
|
if [[ -d "$bw_app" && -S "$bw_sock" ]]; then
|
||||||
|
export SSH_AUTH_SOCK="$bw_sock"
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Add goland $PATH if installed and not already in $PATH
|
# Add goland $PATH if installed and not already in $PATH
|
||||||
@@ -171,7 +179,7 @@ if command -v lsd &> /dev/null; then
|
|||||||
alias lg="lsd -F --group-dirs=first" # Group directories first
|
alias lg="lsd -F --group-dirs=first" # Group directories first
|
||||||
alias lt="lsd --tree --depth 5" # Show directory tree with depth of 5
|
alias lt="lsd --tree --depth 5" # Show directory tree with depth of 5
|
||||||
alias li="lsd -ilAF" # Show inode numbers
|
alias li="lsd -ilAF" # Show inode numbers
|
||||||
else
|
else
|
||||||
alias la="ls -a" # Show all files
|
alias la="ls -a" # Show all files
|
||||||
alias ll="ls -alh" # Show all files, long format, human readable sizes
|
alias ll="ls -alh" # Show all files, long format, human readable sizes
|
||||||
alias li="ls -ialh" # Show all files, long format, human readable sizes, inode numbers
|
alias li="ls -ialh" # Show all files, long format, human readable sizes, inode numbers
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ The zsh theme and plugins are installed manually rather than through a plugin ma
|
|||||||
├── .zshrc # zsh config: PATH, history, completions, prompt, aliases
|
├── .zshrc # zsh config: PATH, history, completions, prompt, aliases
|
||||||
├── .config/
|
├── .config/
|
||||||
│ ├── nvim/ # Neovim config (init.lua, lua/, after/, queries/)
|
│ ├── nvim/ # Neovim config (init.lua, lua/, after/, queries/)
|
||||||
│ └── opencode/ # opencode config (commands, plugins, MCP tools, rules)
|
│ └── opencode/ # opencode config (commands, plugins, skills, MCP tools, rules)
|
||||||
└── .scripts/ # Standalone shell scripts (on $PATH)
|
└── .scripts/ # Standalone shell scripts (on $PATH)
|
||||||
└── hello.sh
|
└── hello.sh
|
||||||
```
|
```
|
||||||
@@ -68,6 +68,29 @@ cd ~/dotfiles && stow -D .
|
|||||||
|
|
||||||
Running `stow .` again re-creates them.
|
Running `stow .` again re-creates them.
|
||||||
|
|
||||||
|
## Add new files or directories
|
||||||
|
|
||||||
|
Add each item to the repository at the same path it should have under the home directory. For example, opencode skills belong under `~/dotfiles/.config/opencode/skills/`. Then refresh the links:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
cd ~/dotfiles
|
||||||
|
stow .
|
||||||
|
```
|
||||||
|
|
||||||
|
If the corresponding target does not exist, Stow creates the symlink. This applies to an entire new directory such as `skills` and to files added inside an already-stowed directory.
|
||||||
|
|
||||||
|
If Stow reports that an existing target is neither a link nor a directory, the target is a real file that Stow will not overwrite. When the repository copy is authoritative, back up the target and rerun Stow:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
mv ~/.config/opencode/opencode.jsonc ~/.config/opencode/opencode.jsonc.pre-stow-backup
|
||||||
|
cd ~/dotfiles
|
||||||
|
stow .
|
||||||
|
```
|
||||||
|
|
||||||
|
Repeat the backup step for every conflicting target listed by Stow. Review and remove backups only after confirming the linked configuration works.
|
||||||
|
|
||||||
|
Do not use `stow --adopt` for this workflow. `--adopt` copies the existing target into the repository, replacing the repository version, which is the opposite of making the repository authoritative.
|
||||||
|
|
||||||
## Secrets
|
## 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.
|
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.
|
||||||
|
|||||||
Reference in New Issue
Block a user