nix all the things

opencode/agents: new ask agent

karitham.dev 661fb379 d07dd46f

verified
+43 -533
+42
modules/opencode/agents/ask.md
··· 1 + --- 2 + description: Exploratory read-only agent for searching, analyzing, and asking questions about the codebase. 3 + mode: primary 4 + temperature: 0.1 5 + tools: 6 + tools: 7 + read: true 8 + glob: true 9 + grep: true 10 + edit: false 11 + bash: true 12 + todowrite: false 13 + todoread: false 14 + permission: 15 + edit: deny 16 + bash: 17 + "*": ask 18 + "ls *": allow 19 + "cat *": allow 20 + "grep *": allow 21 + "find *": allow 22 + "rg *": allow 23 + "fd *": allow 24 + "git diff*": allow 25 + "git log*": allow 26 + "git status": allow 27 + "git show*": allow 28 + --- 29 + 30 + You are the "Ask" agent, a senior software architect and codebase explorer. Your purpose is entirely exploratory and analytical. The user interacting with you is a domain expert and fellow senior engineer. They will ask you to search for things, trace execution paths, and analyze high-level architectural patterns or complex implementation details. 31 + 32 + # Core Directives: 33 + 34 + 1. **Strictly Read-Only:** You operate in a purely exploratory environment. Do not attempt to modify, refactor, or write new code to the file system. 35 + 36 + 2. **Active Exploration & Precision:** Leverage read-only bash commands (`grep`, `rg`, `find`, `cat`, `ls`) to actively traverse the codebase. Do not guess—base all your answers on actual code reality. Always ground your analysis with precise, valid file paths and line references. 37 + 38 + 3. **Expert-Level Analysis:** Communicate peer-to-peer. Assume the user has deep technical fluency. Focus your explanations on architectural patterns, system constraints, data flow, and idiomatic usage. Gloss over basic syntax or trivial lexical differences. Get straight to the point without introductory fluff or over-explaining standard concepts. 39 + 40 + 4. **Proactive Investigation:** If given a high-level query (e.g., "Where is the auth middleware?"), autonomously locate the relevant implementations, trace the usage patterns, and present a concise, highly technical summary of the underlying mechanics. 41 + 42 + 5. **Boundary Enforcement:** If the user requests code modifications, politely decline, remind them of your read-only constraints, and advise them to use the `build` agent to apply changes.
+1 -5
modules/opencode/default.nix
··· 5 5 ... 6 6 }: 7 7 let 8 - rulesDir = ./rules; 9 - 10 8 opencodePkg = pkgs.symlinkJoin { 11 9 name = "opencode.wrapped"; 12 10 paths = [ pkgs.opencode ]; 13 11 buildInputs = [ pkgs.makeWrapper ]; 14 12 postBuild = '' 15 13 wrapProgram $out/bin/opencode \ 16 - --set SHELL ${lib.getExe pkgs.bash} \ 17 - --set-default LANGRULES_DIR ${rulesDir} 14 + --set SHELL ${lib.getExe pkgs.bash} 18 15 ''; 19 16 }; 20 17 ··· 34 31 enableMcpIntegration = cfg.enableMcp; 35 32 settings = { 36 33 inherit (cfg) theme; 37 - # plugin = [ "git@tangled.org:karitham.dev/langrules-opencode" ]; 38 34 permission = { 39 35 todoread = "deny"; 40 36 todowrite = "deny";
-56
modules/opencode/rules/global.md
··· 1 - # Global Coding Rules 2 - 3 - ## NO STUBS - ABSOLUTE RULE 4 - 5 - - NEVER write `TODO`, `FIXME`, `pass`, `...`, `unimplemented!()` 6 - - NEVER write empty function bodies or placeholder returns 7 - - If too complex for one turn: throw an error/exception with a clear reason 8 - 9 - ## Core Rules 10 - 11 - 1. **READ BEFORE WRITE**: Always read a file before editing. 12 - 2. **FULL FEATURES**: Complete the feature, don't stop partway. 13 - 3. **ERROR HANDLING**: No panics/crashes on bad input. 14 - 4. **SECURITY**: Validate input, parameterized queries, no hardcoded secrets. 15 - 5. **NO DEAD CODE**: Remove or complete incomplete code. 16 - 17 - ## Chainlink Lifecycle Management 18 - 19 - You MUST use Chainlink to track all work: 20 - 21 - - **Session Start**: `chainlink session start` - shows previous handoff 22 - - **Session Work**: `chainlink session work <id>` - mark current focus 23 - - **Progress**: `chainlink comment <id> "..."` - update regularly 24 - - **Session End**: `chainlink session end --notes "..."` - REQUIRED before stopping 25 - 26 - ### Handoff Notes Format 27 - 28 - ```markdown 29 - **Accomplished:** 30 - - Completed feature X 31 - - Added tests for Y 32 - 33 - **In Progress:** 34 - - Working on feature Z 35 - 36 - **Next:** 37 - - Complete feature Z 38 - - Run tests 39 - 40 - **Blockers:** 41 - - None 42 - ``` 43 - 44 - ## Code Quality Requirements 45 - 46 - - **NO DEAD CODE**: Remove unused functions, variables, imports 47 - - **NO HARDCODED SECRETS**: Use environment variables, configs 48 - - **COMMIT FREQUENTLY**: Small, focused commits 49 - - **DESCRIPTIVE COMMITS**: Explain WHY, not just WHAT 50 - 51 - ## Security 52 - 53 - - Validate ALL inputs (user, network, config) 54 - - Use parameterized queries for database access 55 - - Never log sensitive data (passwords, tokens, keys) 56 - - Follow principle of least privilege
-95
modules/opencode/rules/go.md
··· 1 - ### Go Best Practices 2 - 3 - Follow [Effective Go](https://go.dev/doc/effective_go) and [Go Code Review Comments](https://github.com/golang/go/wiki/CodeReviewComments). 4 - 5 - #### Code Style & Structure 6 - 7 - - **Existing Style**: The best Go style is the existing style. Adapt to existing patterns and conventions in the codebase as much as possible. 8 - - **Small Interfaces**: Keep interfaces small (often 1-3 methods). "The bigger the interface, the weaker the abstraction." 9 - - **Deep Modules**: Design modules with simple interfaces that hide significant complexity (deep vs. shallow). 10 - - **Align Left**: Keep the "happy path" aligned to the left. 11 - - **Early Returns**: Use guard clauses to handle errors and edge cases early, reducing nesting. 12 - - **Avoid Else**: Avoid `else` blocks; they often indicate complex branching that can be flattened with early returns. 13 - - **No Naked Returns**: Avoid using named return parameters for actual returns. 14 - - **Latest Features**: Leverage modern Go features (generics, `any`, `net/http` routing enhancements, `log/slog`, `t.Context()`). 15 - - **Simple Functions**: Write small, focused functions that do one thing well. 16 - - **Avoid God Objects**: Don't create types that try to do everything. Use composition. 17 - - **Pure Code**: Prefer pure functions where possible. 18 - - **Easy to Mock**: Accept interfaces, return structs. Use dependency injection. 19 - 20 - #### Error Handling 21 - 22 - Always check and handle errors immediately. Wrap errors with context. 23 - 24 - ```go 25 - // GOOD: Early returns, aligned left, no else 26 - func readConfig(path string) (*Config, error) { 27 - data, err := os.ReadFile(path) 28 - if err != nil { 29 - return nil, fmt.Errorf("read config: %w", err) 30 - } 31 - 32 - var config Config 33 - if err := json.Unmarshal(data, &config); err != nil { 34 - return nil, fmt.Errorf("parse config: %w", err) 35 - } 36 - 37 - return &config, nil 38 - } 39 - 40 - // BAD: Nested, use of else, harder to follow 41 - func readConfig(path string) (*Config, error) { 42 - data, err := os.ReadFile(path) 43 - if err == nil { 44 - var config Config 45 - err = json.Unmarshal(data, &config) 46 - if err == nil { 47 - return &config, nil 48 - } else { 49 - return nil, err 50 - } 51 - } else { 52 - return nil, err 53 - } 54 - } 55 - ``` 56 - 57 - #### Concurrency & Sync 58 - 59 - - **Package sync**: Use `sync.Mutex`, `sync.RWMutex`, `sync.Once`, and `sync.Pool` extensively. 60 - - **sync.WaitGroup**: Use for waiting on multiple goroutines. 61 - - **Channels**: Use for coordination between goroutines. 62 - - **Context**: Always propagate `context.Context`. Use `t.Context()` in tests for automatic cleanup. 63 - - **Atomic**: Use `sync/atomic` for simple counter/state updates. 64 - 65 - #### Testing 66 - 67 - Use the standard `testing` package effectively. 68 - 69 - - **Table-Driven Tests**: Use anonymous structs for test cases with clear `name`, `got`, and `want` fields. 70 - - **t.Context()**: Use `t.Context()` for test-scoped context that cancels when the test finishes. 71 - - **Few Functions, Good Tables**: Prefer one robust test function with a comprehensive table over many small test functions. 72 - - **Helper Functions**: Use `t.Helper()` in functions that assist in testing to keep stack traces clean. 73 - 74 - ```go 75 - func TestSum(t *testing.T) { 76 - tests := []struct { 77 - name string 78 - args []int 79 - want int 80 - }{ 81 - {"empty", []int{}, 0}, 82 - {"single", []int{1}, 1}, 83 - {"multiple", []int{1, 2, 3}, 6}, 84 - {"negative", []int{1, -1}, 0}, 85 - } 86 - 87 - for _, tt := range tests { 88 - t.Run(tt.name, func(t *testing.T) { 89 - if got := Sum(tt.args); got != tt.want { 90 - t.Errorf("Sum() = %v, want %v", got, tt.want) 91 - } 92 - }) 93 - } 94 - } 95 - ```
-36
modules/opencode/rules/javascript.md
··· 1 - ### JavaScript Best Practices 2 - 3 - #### Code Style 4 - - Use `const` by default, `let` when needed, never `var` 5 - - Use arrow functions for callbacks 6 - - Use template literals over string concatenation 7 - - Use destructuring for object/array access 8 - 9 - #### Error Handling 10 - ```javascript 11 - // GOOD: Proper async error handling 12 - async function fetchUser(id) { 13 - try { 14 - const response = await fetch(`/api/users/${id}`); 15 - if (!response.ok) { 16 - throw new Error(`HTTP ${response.status}`); 17 - } 18 - return await response.json(); 19 - } catch (error) { 20 - console.error('Failed to fetch user:', error); 21 - throw error; // Re-throw or handle appropriately 22 - } 23 - } 24 - 25 - // BAD: Ignoring errors 26 - async function fetchUser(id) { 27 - const response = await fetch(`/api/users/${id}`); 28 - return response.json(); // No error handling 29 - } 30 - ``` 31 - 32 - #### Security 33 - - Never use `eval()` or `innerHTML` with user input 34 - - Validate all input on both client and server 35 - - Use `textContent` instead of `innerHTML` when possible 36 - - Sanitize URLs before navigation or fetch
-306
modules/opencode/rules/nix.md
··· 1 - # Nix Best Practices 2 - 3 - ## Code Style 4 - 5 - - Use `nixfmt` for formatting (set as formatter in flake, run `nix fmt` before committing) 6 - - Follow the [Nixpkgs contributing guide](https://github.com/NixOS/nixpkgs/blob/master/CONTRIBUTING.md) for style conventions 7 - - Use descriptive variable names that explain purpose 8 - - Prefer `let ... in` blocks for local bindings over deep nesting 9 - - Keep derivations and functions small and composable 10 - - Use `lib.mkIf`, `lib.mkWhen`, `lib.optionals` for conditional logic 11 - - Use `lib.getExe` and `lib.getExe'` for accessing package executables 12 - 13 - ## Error Handling 14 - 15 - ```nix 16 - # GOOD: Proper error handling with builtins.tryEval 17 - let 18 - configPath = ./config.json; 19 - config = builtins.tryEval (builtins.fromJSON (builtins.readFile configPath)); 20 - in 21 - if config.success then config.value else throw "Failed to parse config" 22 - 23 - # GOOD: Using assert statements for validation 24 - assert lib.assertMsg (cfg.port > 0 && cfg.port < 65536) "Port must be between 1 and 65535"; 25 - cfg 26 - 27 - # GOOD: Using lib.mapAttrs' with lib.nameValuePair for building attribute sets 28 - lib.mapAttrs' (argName: argValue: 29 - lib.nameValuePair "${argName}+${dir.name}" { 30 - action = { 31 - "${argValue}-${dir.value}" = [ ]; 32 - }; 33 - } 34 - ) act 35 - 36 - # BAD: Silent failures or incomplete error messages 37 - let 38 - data = builtins.readFile configPath; 39 - config = builtins.fromJSON data; # Will throw cryptic error if invalid 40 - in config 41 - ``` 42 - 43 - ## Nix Module System 44 - 45 - - Use `lib.mkOptionType`, `lib.mkDefault`, `lib.mkForce` appropriately 46 - - Prefer `mkOption` with proper `type`, `default`, and `description` fields 47 - - Use `mkIf` for conditional module options rather than deep nesting 48 - - Keep modules focused - one module per responsibility 49 - - Use `imports` to compose modules rather than duplicating code 50 - - Use `lib.getExe pkgs.packageName` for executable paths in configuration 51 - 52 - ```nix 53 - # GOOD: Well-structured module option 54 - { lib, config, ... }: 55 - { 56 - options.my.username = lib.mkOption { 57 - type = lib.types.str; 58 - description = "The username for the current user."; 59 - default = "kar"; 60 - }; 61 - 62 - config = lib.mkIf (config.my.username != "root") { 63 - users.users.${config.my.username} = { 64 - home = "/home/${config.my.username}"; 65 - initialPassword = ""; 66 - isNormalUser = true; 67 - extraGroups = [ 68 - "networkmanager" 69 - "docker" 70 - "wheel" 71 - ]; 72 - }; 73 - }; 74 - } 75 - ``` 76 - 77 - ## Flake Patterns 78 - 79 - - Use `flake-parts` for modular flake structure 80 - - Use `withSystem` for system-specific configuration 81 - - Provide `devShells`, `packages`, `checks`, `formatter` per system 82 - - Lock `nixpkgs` reference using channel URLs or specific revisions 83 - - Provide formatter and linter in `devShells` 84 - - Use `nixConfig` for Nix configuration (experimental features, substituters) 85 - 86 - ## System Management 87 - 88 - - Use `easy-hosts` for organizing hosts by class (desktop, server, wsl) and tags 89 - - Define shared modules for all systems in `config.easy-hosts.shared.modules` 90 - - Use perClass and perTag for class-specific and tag-specific modules 91 - - Use `mkSystem'` for creating individual systems with proper specialArgs 92 - 93 - ## Overlay Patterns 94 - 95 - - Use `overrideAttrs` for patching existing packages 96 - - Use `fetchurl` or `fetchFromGitHub` for patches with hash verification 97 - - Use `callPackage` to add packages to overlay 98 - - Keep overlays focused and well-documented 99 - 100 - ## Package Building 101 - 102 - - Use `pkgs.buildGoModule` for Go packages with proper vendorHash 103 - - Use `pkgs.fetchFromGitHub` for GitHub sources with hash verification 104 - - Set `env.CGO_ENABLED`, `flags`, and `ldflags` appropriately for Go 105 - - Include proper `meta` with description, homepage, license, maintainers 106 - - Use `trimpath` and static linking flags for production binaries 107 - 108 - ## Security 109 - 110 - - Never commit secrets or API keys in Nix files 111 - - Use `sops-nix` for secrets management in production 112 - - Use sandbox mode in `nix.conf` (`sandbox = true`) for builds 113 - - Review network access in derivations - use `allowedRequisites` for purity 114 - - Use `fetchFromGitHub` or `fetchurl` with hash verification 115 - 116 - ## Dependency Management 117 - 118 - - Use specific Git revisions/commits for Git dependencies (not branches) 119 - - Always include `sha256` hash for fetch functions 120 - - Use `inputs.nixpkgs.follows` to avoid duplicating inputs 121 - - Pin `nixpkgs` in production configurations using `flake.lock` 122 - - Prefer `flake-inputs` over `builtins.fetchTarball` for external sources 123 - - Use `callPackage` pattern for package dependencies 124 - 125 - ## Testing 126 - 127 - - Use `nix-instantiate --parse` to check for syntax errors 128 - - Use `nix-build` with `-A` to test specific attributes 129 - - Write checks in `perSystem.checks` for package testing 130 - - Use `nix flake check` for flake validation 131 - - Test modules with `nixos-rebuild dry-build` or `nixos-rebuild test` 132 - 133 - ## Evaluation 134 - 135 - - Use `lib.warnIf` and `lib.deprecated` for deprecation notices 136 - - Avoid `builtins.trace` in production code (use for debugging only) 137 - - Use `lib.lists.foldl'` or `lib.lists.foldl'` for strict left folds 138 - - Prefer `lib.mapAttrs` and `lib.mapAttrs'` over `builtins.map` for attribute sets 139 - - Use `lib.filterAttrs` for filtering attributes 140 - - Use `lib.mergeAttrsList` for merging lists of attribute sets 141 - - Use `lib.attrsToList` for converting attributes to list of name-value pairs 142 - 143 - ## Performance 144 - 145 - - Use `lib.optionals` and `lib.concatMap` for list operations 146 - - Avoid deep recursion - use `foldl'` for accumulation 147 - - Use `overrideAttrs` for modifying packages instead of rewriting 148 - - Prefer `stdenv.mkDerivation` over raw `derivation` for packages 149 - - Use `pkgs.callPackage` with explicit arguments for clarity 150 - 151 - ## Home-Manager Module System 152 - 153 - Home-manager modules manage user-level configuration (home directory, user packages, programs). 154 - 155 - ### Module Structure 156 - 157 - ``` 158 - modules/ 159 - dev/ 160 - home.nix # Home-manager module with osConfig parameter 161 - nixos.nix # NixOS module importing home.nix via homeModules 162 - shell/ 163 - default.nix # Imports sub-modules 164 - nushell.nix # Actual configuration 165 - ``` 166 - 167 - ### Home-Manager Module Pattern 168 - 169 - ```nix 170 - # modules/dev/shell/default.nix 171 - { 172 - imports = [ 173 - ./atuin.nix 174 - ./nushell.nix 175 - ./starship.nix 176 - ./zellij.nix 177 - ]; 178 - } 179 - ``` 180 - 181 - ### Home-Manager with osConfig 182 - 183 - ```nix 184 - # modules/dev/home.nix 185 - { 186 - osConfig ? { }, 187 - lib, 188 - ... 189 - }: 190 - let 191 - inherit (lib) mkEnableOption; 192 - in 193 - { 194 - # Inherit options from NixOS module configuration 195 - config.dev = { 196 - inherit (osConfig.dev or { }) 197 - shell 198 - editor 199 - vcs 200 - tools 201 - ; 202 - }; 203 - 204 - # Define options (mirrors NixOS module) 205 - options.dev = { 206 - enable = mkEnableOption "all development tools"; 207 - shell.enable = mkEnableOption "shell-related tools"; 208 - editor.enable = mkEnableOption "editor tools"; 209 - vcs.enable = mkEnableOption "version control tools"; 210 - tools.enable = mkEnableOption "development utilities"; 211 - }; 212 - 213 - # Import sub-modules 214 - imports = [ 215 - ./shell 216 - ./editor 217 - ./vcs 218 - ./tools 219 - ]; 220 - } 221 - ``` 222 - 223 - ### Flake Integration 224 - 225 - ```nix 226 - # flake.nix modules section 227 - { 228 - imports = [ ../systems ]; 229 - 230 - perSystem = { ... }: { 231 - # ... 232 - }; 233 - 234 - flake = { 235 - homeModules = { 236 - dev = import ./dev/home.nix; 237 - desktop = import ./desktop/home.nix; 238 - }; 239 - 240 - nixosModules = { 241 - dev = import ./dev/nixos.nix; 242 - desktop = import ./desktop/nixos.nix; 243 - }; 244 - }; 245 - } 246 - ``` 247 - 248 - ### Usage in System Configuration 249 - 250 - ```nix 251 - # systems/kiwi.nix (NixOS) 252 - { 253 - imports = [ 254 - inputs.self.nixosModules.dev 255 - # ... other modules 256 - ]; 257 - 258 - dev.enable = true; 259 - dev.shell.enable = true; 260 - } 261 - ``` 262 - 263 - ```nix 264 - # modules/desktop/home.nix (Home-Manager) 265 - { config, self, ... }: 266 - { 267 - imports = [ 268 - self.homeModules.dev 269 - # ... other home modules 270 - ]; 271 - 272 - dev.enable = true; 273 - } 274 - ``` 275 - 276 - ### Key Differences from NixOS Modules 277 - 278 - | Aspect | NixOS Module | Home-Manager Module | 279 - |--------|--------------|---------------------| 280 - | Special args | `{ config, lib, pkgs, ... }` | `{ config, lib, pkgs, osConfig ? {}, ... }` | 281 - | System config | Direct access to `config.*` | Inherits via `osConfig.dev` | 282 - | User packages | `home.packages` | `home.packages` | 283 - | Programs | `programs.*` | `programs.*` | 284 - | System services | `services.*` | Not available | 285 - 286 - ### XDG Directories 287 - 288 - Home-manager manages XDG directories via `xdg.configFile`, `xdg.dataFile`, etc.: 289 - 290 - ```nix 291 - { config, ... }: 292 - { 293 - xdg.configFile."opencode/agents" = { 294 - source = ./agents; 295 - recursive = true; 296 - }; 297 - 298 - programs.opencode = { 299 - enable = true; 300 - package = opencodePkg; 301 - settings = { 302 - theme = "catppuccin-macchiato"; 303 - }; 304 - }; 305 - } 306 - ```
-35
modules/opencode/rules/typescript.md
··· 1 - ### TypeScript Best Practices 2 - 3 - #### Code Style 4 - - Use strict mode (`"strict": true` in tsconfig.json) 5 - - Prefer `interface` over `type` for object shapes 6 - - Use `const` by default, `let` when needed, never `var` 7 - - Enable `noImplicitAny` and `strictNullChecks` 8 - 9 - #### Type Safety 10 - ```typescript 11 - // GOOD: Explicit types and null handling 12 - function getUser(id: string): User | undefined { 13 - return users.get(id); 14 - } 15 - 16 - const user = getUser(id); 17 - if (user) { 18 - console.log(user.name); // TypeScript knows user is defined 19 - } 20 - 21 - // BAD: Type assertions to bypass safety 22 - const user = getUser(id) as User; // Dangerous if undefined 23 - console.log(user.name); // Might crash 24 - ``` 25 - 26 - #### Error Handling 27 - - Use try/catch for async operations 28 - - Define custom error types for domain errors 29 - - Never swallow errors silently 30 - 31 - #### Security 32 - - Validate all user input at API boundaries 33 - - Use parameterized queries for database operations 34 - - Sanitize data before rendering in DOM (prevent XSS) 35 - - Never use `eval()` or `Function()` with user input