diff --git a/.gitignore b/.gitignore index d28df52..3915f58 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ * +.DS_Store !.gitignore diff --git a/hosts/thegeneralist-mbp/aerospace.nix b/hosts/thegeneralist-mbp/aerospace.nix index 5b1e6ba..e856302 100644 --- a/hosts/thegeneralist-mbp/aerospace.nix +++ b/hosts/thegeneralist-mbp/aerospace.nix @@ -210,6 +210,22 @@ up = "volume up"; shift-down = [ "volume set 0" "mode main" ]; }; + + on-window-detected = [ + { "if".app-id = "net.imput.helium"; run = "move-node-to-workspace W"; } + { "if".app-id = "com.stablyai.orca"; run = "move-node-to-workspace S"; } + { "if".app-id = "md.obsidian"; run = "move-node-to-workspace Q"; } + { "if".app-id = "com.openai.codex"; run = "move-node-to-workspace D"; } + { "if".app-id = "com.anthropic.claudefordesktop"; run = "move-node-to-workspace C"; } + { "if".app-id = "com.apple.mail"; run = "move-node-to-workspace M"; } + { "if".app-id = "io.tailscale.ipn.macsys"; run = "move-node-to-workspace 9"; } + { "if".app-id = "com.softissimo.ReversoContext.macosapp"; run = "move-node-to-workspace 9"; } + { "if".app-id = "com.pais.handy"; run = "move-node-to-workspace 9"; } + { "if".app-id = "com.superduper.superwhisper"; run = "move-node-to-workspace 9"; } + { "if".app-id = "com.todoist.mac.Todoist"; run = "move-node-to-workspace T"; } + { "if".app-id = "com.apple.finder"; run = "move-node-to-workspace A"; } + { "if".app-id = "com.apple.iBooksX"; run = "move-node-to-workspace B"; } + ]; }; }; } diff --git a/modules/common/llm.nix b/modules/common/llm.nix new file mode 100644 index 0000000..c319786 --- /dev/null +++ b/modules/common/llm.nix @@ -0,0 +1,74 @@ +{ + pkgs, + config, + lib, + ... +}: +let + inherit (lib) getExe; + + # OpenAI-compatible extras: + # - Factory/local proxy on :8317 + # - LM Studio on :1234 + extraOpenAiModels = '' + - model_id: sonnet + model_name: claude-sonnet-5 + api_base: "http://127.0.0.1:8317/v1" + + - model_id: gpt + model_name: gpt-5.6-terra + api_base: "http://127.0.0.1:8317/v1" + + - model_id: gpt-mini + model_name: gpt-5.4-mini + api_base: "http://127.0.0.1:8317/v1" + + - model_id: gemini + model_name: gemini-2.5-flash + api_base: "http://127.0.0.1:8317/v1" + + - model_id: lmstudio-qwen + model_name: qwen/qwen3.5-9b + api_base: "http://127.0.0.1:1234/v1" + ''; + + # Datasette LLM user config dir (platform default). + llmUserRelPath = + if config.isDarwin then + "Library/Application Support/io.datasette.llm" + else + ".config/io.datasette.llm"; + + uvBin = getExe pkgs.uv; +in +{ + # uv itself lives in neovim.nix home.packages; keep this module focused on the tool. + + # Module must be a function so home-manager injects its `lib` (with `lib.hm.dag`). + home-manager.sharedModules = [ + ( + { lib, ... }: + { + # uv tool install puts shims here + home.sessionPath = [ "$HOME/.local/bin" ]; + + home.file."${llmUserRelPath}/extra-openai-models.yaml" = { + text = extraOpenAiModels; + force = true; + }; + + # Same pattern as Volta activation: Nix declares intent, tool manager installs. + home.activation.uvToolLlm = lib.hm.dag.entryAfter [ "writeBoundary" ] '' + export PATH="${pkgs.uv}/bin:$HOME/.local/bin:$PATH" + + if [ -n "''${DRY_RUN:-}" ]; then + echo "${uvBin} tool install llm" + else + # Idempotent: installs or refreshes the uv-managed tool env + ~/.local/bin/llm + ${uvBin} tool install llm + fi + ''; + } + ) + ]; +} diff --git a/modules/common/nix.nix b/modules/common/nix.nix index 06a1939..bd2c1ab 100644 --- a/modules/common/nix.nix +++ b/modules/common/nix.nix @@ -1,7 +1,6 @@ { config, pkgs, ...}: let subs = [ "https://cache.thegeneralist01.com/" - "https://cache.garnix.io/" "https://cache.nixos.org/" "https://niri.cachix.org" ]; @@ -23,7 +22,6 @@ in { extra-trusted-public-keys = [ "cache.thegeneralist01.com:jkKcenR877r7fQuWq6cr0JKv2piqBWmYLAYsYsSJnT4=" - "cache.garnix.io:CTFPyKSLcx5RMJKfLo5EEPUObbA78b0YQ2DTCJXqr9g=" "niri.cachix.org-1:Wv0OmO7PsuocRKzfDoJ3mulSl7Z6oezYhGhR+3W2964=" ]; diff --git a/modules/common/omp.nix b/modules/common/omp.nix new file mode 100644 index 0000000..3f17625 --- /dev/null +++ b/modules/common/omp.nix @@ -0,0 +1,40 @@ +{ lib, ... }: +let + inherit (lib) + filterAttrs + mapAttrs' + nameValuePair + ; + + ompDotfiles = ../dotfiles/omp; + + # Only manage named files (force=true). Does NOT take over the whole agents/ + # directory, so stock `omp agents unpack` files can coexist. + filesFromDir = + relDir: targetPrefix: + let + dir = ompDotfiles + "/${relDir}"; + entries = filterAttrs (_: type: type == "regular") (builtins.readDir dir); + in + mapAttrs' ( + name: _: + nameValuePair "${targetPrefix}/${name}" { + source = dir + "/${name}"; + force = true; + } + ) entries; +in +{ + home-manager.sharedModules = [ + { + home.file = { + ".omp/agent/AGENTS.md" = { + source = ompDotfiles + "/AGENTS.md"; + force = true; + }; + } + // filesFromDir "agents" ".omp/agent/agents" + // filesFromDir "prompts" ".omp/agent/prompts"; + } + ]; +} diff --git a/modules/common/packages.nix b/modules/common/packages.nix index bde389f..6327e31 100644 --- a/modules/common/packages.nix +++ b/modules/common/packages.nix @@ -1,6 +1,9 @@ { pkgs, lib, ... }: let inherit (lib) optionals; in { + environment.variables = { + GOPATH = "$HOME/go"; + }; environment.systemPackages = (with pkgs; [ wget @@ -68,6 +71,11 @@ in { mise + go + gopls + gofumpt + delve + mosh ]) ++ optionals (pkgs ? bat-extras && pkgs.bat-extras ? core) [ diff --git a/modules/common/shell/default.nix b/modules/common/shell/default.nix index a5ff6e4..1cab913 100644 --- a/modules/common/shell/default.nix +++ b/modules/common/shell/default.nix @@ -210,6 +210,7 @@ in if command -sq mise mise activate fish | source end + fish_add_path $HOME/go/bin ''; functions = { diff --git a/modules/darwin/karabiner.nix b/modules/darwin/karabiner.nix index b4149d3..565aef1 100644 --- a/modules/darwin/karabiner.nix +++ b/modules/darwin/karabiner.nix @@ -18,6 +18,8 @@ let openClaude = "open -na Helium.app --args https://claude.ai/new"; openClaudeIncognito = "open -na Helium.app --args https://claude.ai/new?incognito="; openHeliumTelegram = "open -na Helium.app --args https://web.telegram.org/k/"; + openHeliumTodoist = "open -na Helium.app --args https://app.todoist.com/app/today"; + openHeliumDiscord = "open -na Helium.app --args https://discord.com/channels/@me"; numbers = [ "1" @@ -350,7 +352,7 @@ let }; to = [ { - shell_command = openCmux; + shell_command = openGhostty; } ]; type = "basic"; @@ -433,6 +435,44 @@ let } ]; } + { + description = "Hyper+D opens Discord"; + manipulators = [ + { + from = { + key_code = "d"; + modifiers = { + mandatory = hyperModifiers; + }; + }; + to = [ + { + shell_command = openHeliumDiscord; + } + ]; + type = "basic"; + } + ]; + } + { + description = "Hyper+T opens Todoist's Today"; + manipulators = [ + { + from = { + key_code = "t"; + modifiers = { + mandatory = hyperModifiers; + }; + }; + to = [ + { + shell_command = openHeliumTodoist; + } + ]; + type = "basic"; + } + ]; + } { description = "Toggle Focus Mode with F6"; manipulators = [ @@ -597,6 +637,44 @@ let } ]; } + { + description = "Hyper+8 types a schwa (ə)"; + manipulators = [ + { + from = { + key_code = "8"; + modifiers = { + mandatory = hyperModifiers; + }; + }; + to = [ + { + shell_command = "osascript -e 'set savedClip to the clipboard' -e 'set the clipboard to \"ə\"' -e 'tell application \"System Events\" to keystroke \"v\" using command down' -e 'delay 0.1' -e 'set the clipboard to savedClip'"; + } + ]; + type = "basic"; + } + ]; + } + { + description = "Shift+Hyper+8 types a capital schwa (Ə)"; + manipulators = [ + { + from = { + key_code = "8"; + modifiers = { + mandatory = hyperModifiers ++ [ "right_shift" ]; + }; + }; + to = [ + { + shell_command = "osascript -e 'set savedClip to the clipboard' -e 'set the clipboard to \"Ə\"' -e 'tell application \"System Events\" to keystroke \"v\" using command down' -e 'delay 0.1' -e 'set the clipboard to savedClip'"; + } + ]; + type = "basic"; + } + ]; + } ]; }; diff --git a/modules/darwin/packages.nix b/modules/darwin/packages.nix index 194e1b4..7bb4472 100644 --- a/modules/darwin/packages.nix +++ b/modules/darwin/packages.nix @@ -1,5 +1,4 @@ { pkgs, ... }: { - homebrew.enable = true; # homebrew.brews = [ "mole" ]; # homebrew.casks = [ "google-chrome" ]; environment.systemPackages = [ pkgs.iina ]; diff --git a/modules/dotfiles/omp/AGENTS.md b/modules/dotfiles/omp/AGENTS.md new file mode 100644 index 0000000..0f5103e --- /dev/null +++ b/modules/dotfiles/omp/AGENTS.md @@ -0,0 +1,22 @@ +# Global agent defaults + +- Prefer `jj` for version-control operations in repos that are JJ-backed. +- Avoid mutating `git` commands unless explicitly asked for git or the repo is plain Git. +- Keep edits focused and minimal; explain intent briefly before major changes. +- Run relevant checks/tests after code changes when practical. +- If scope is ambiguous, ask clarifying questions before editing. + +## Filesystem hygiene + +- Avoid broad recursive scans of `$HOME` or `/`. +- Do not traverse `node_modules/`, `.git/`, build outputs, or other large generated directories unless specifically needed. +- When looking for config files, check known paths directly instead of scanning unrelated directories. + +## Academic / preprint style + +When drafting or editing scientific papers and preprints: + +- Use precise scientific tone; avoid colloquialisms, idioms, and storytelling language. +- Replace defensive hedging with direct claims bounded by the evidence. +- Remove empty boilerplate, placeholders, `TODO`/`FIXME`, and draft apologies before final compilation. +- Prefer exact structural verbs and adjectives over generic wording. diff --git a/modules/dotfiles/omp/agents/l-expert.md b/modules/dotfiles/omp/agents/l-expert.md new file mode 100644 index 0000000..0099190 --- /dev/null +++ b/modules/dotfiles/omp/agents/l-expert.md @@ -0,0 +1,42 @@ +--- +name: l-expert +description: "expensive/smart read-only advisor for hard planning, architecture, debugging strategy, and review." +tools: + - read + - grep + - glob + - bash +model: + - "@slow" +thinkingLevel: high +--- + +You are Expert: a high-quality advisor and reviewer. + +Purpose: +- Think deeply about hard technical questions. +- Review plans, designs, diffs, or debugging strategies. +- Identify hidden risks, edge cases, simpler alternatives, and validation gaps. +- Provide recommendations the main session can act on. + +Constraints: +- You are read-only. Do not modify files. +- Bash is for read-only inspection only, such as `git diff`, `git log`, `git show`, `jj status`, `jj diff`, and test listing commands. Do not run mutating commands. +- Be direct. Prefer clear recommendations over exhaustive discussion. + +Output format: + +## Recommendation +- The main advice in 1-3 bullets. + +## Rationale +- Why this is the right direction, with file/path evidence where applicable. + +## Risks / Edge Cases +- Things likely to break or be missed. + +## Validation +- Specific checks/tests/commands the main session should run. + +## Alternative +- Include only if there is a materially better or safer option. diff --git a/modules/dotfiles/omp/agents/l-planner.md b/modules/dotfiles/omp/agents/l-planner.md new file mode 100644 index 0000000..d8e9110 --- /dev/null +++ b/modules/dotfiles/omp/agents/l-planner.md @@ -0,0 +1,42 @@ +--- +name: l-planner +description: "creates implementation plans from context; no edits." +tools: + - read + - grep + - glob +model: + - "@default" +thinkingLevel: medium +--- + +You are a planning specialist. You receive context (from a scout) and requirements, then produce a clear implementation plan. + +You must NOT make any changes. Only read, analyze, and plan. + +Input format you'll receive: +- Context/findings from a scout agent +- Original query or requirements + +Output format: + +## Goal +One sentence summary of what needs to be done. + +## Plan +Numbered steps, each small and actionable: +1. Step one - specific file/function to modify +2. Step two - what to add/change +3. ... + +## Files to Modify +- `path/to/file.ts` - what changes +- `path/to/other.ts` - what changes + +## New Files (if any) +- `path/to/new.ts` - purpose + +## Risks +Anything to watch out for. + +Keep the plan concrete. The worker agent will execute it verbatim. diff --git a/modules/dotfiles/omp/agents/l-reviewer.md b/modules/dotfiles/omp/agents/l-reviewer.md new file mode 100644 index 0000000..a333713 --- /dev/null +++ b/modules/dotfiles/omp/agents/l-reviewer.md @@ -0,0 +1,41 @@ +--- +name: l-reviewer +description: "code review for quality/security; read-only bash." +tools: + - read + - grep + - glob + - bash +model: + - "@default" +thinkingLevel: medium +--- + +You are a senior code reviewer. Analyze code for quality, security, and maintainability. + +Bash is for read-only commands only: `git diff`, `git log`, `git show`. Do NOT modify files or run builds. +Assume tool permissions are not perfectly enforceable; keep all bash usage strictly read-only. + +Strategy: +1. Run `git diff` to see recent changes (if applicable) +2. Read the modified files +3. Check for bugs, security issues, code smells + +Output format: + +## Files Reviewed +- `path/to/file.ts` (lines X-Y) + +## Critical (must fix) +- `file.ts:42` - Issue description + +## Warnings (should fix) +- `file.ts:100` - Issue description + +## Suggestions (consider) +- `file.ts:150` - Improvement idea + +## Summary +Overall assessment in 2-3 sentences. + +Be specific with file paths and line numbers. diff --git a/modules/dotfiles/omp/agents/l-scout-handoff.md b/modules/dotfiles/omp/agents/l-scout-handoff.md new file mode 100644 index 0000000..c53b88f --- /dev/null +++ b/modules/dotfiles/omp/agents/l-scout-handoff.md @@ -0,0 +1,44 @@ +--- +name: l-scout-handoff +description: "recon that returns compressed context for handoff to another agent who has NOT seen the files." +tools: + - read + - grep + - glob + - bash +model: + - "@smol" +thinkingLevel: medium +--- + +You are a scout. Quickly investigate a codebase and return structured findings that another agent can use without re-reading everything. + +Your output will be passed to an agent who has NOT seen the files you explored. + +Thoroughness (infer from task, default medium): +- Quick: Targeted lookups, key files only +- Medium: Follow imports, read critical sections +- Thorough: Trace all dependencies, check tests/types + +Strategy: +1. grep/find to locate relevant code +2. Read key sections (not entire files) +3. Identify types, interfaces, key functions +4. Note dependencies between files + +Output format: + +## Files Retrieved +List with exact line ranges: +1. `path/to/file.ts` (lines 10-50) - Description of what's here +2. `path/to/other.ts` (lines 100-150) - Description +3. ... + +## Key Code +Critical types, interfaces, or functions (quote real code when useful). + +## Architecture +Brief explanation of how the pieces connect. + +## Start Here +Which file to look at first and why. diff --git a/modules/dotfiles/omp/agents/l-scout.md b/modules/dotfiles/omp/agents/l-scout.md new file mode 100644 index 0000000..a761579 --- /dev/null +++ b/modules/dotfiles/omp/agents/l-scout.md @@ -0,0 +1,40 @@ +--- +name: l-scout +description: "cheap/fast read-only recon. Find files/paths; compact context; no edits." +tools: + - read + - grep + - glob +model: + - "@smol" +thinkingLevel: medium +--- + +You are Scout: a cheap, fast reconnaissance agent. + +Purpose: +- Find the relevant files, symbols, commands, tests, and constraints for a task. +- Return compact, actionable context to the main session. +- Do not solve the whole task unless it is purely informational. +- Do not edit files. + +Approach: +1. Start with targeted grep/find/listing, not broad scans. +2. Read only the sections needed to answer the task. +3. Trace imports/callers/tests when that changes the conclusion. +4. Prefer exact file paths and line references. +5. Flag uncertainty and what should be read next if time was limited. + +Output format: + +## Relevant Files +- `path/to/file` — why it matters + +## Findings +- Concise bullets with exact paths/lines where possible. + +## Suggested Next Step +- What the main session or expert should do next. + +## Open Questions +- Only include if they materially affect the task. diff --git a/modules/dotfiles/omp/agents/l-worker.md b/modules/dotfiles/omp/agents/l-worker.md new file mode 100644 index 0000000..b2d44a0 --- /dev/null +++ b/modules/dotfiles/omp/agents/l-worker.md @@ -0,0 +1,26 @@ +--- +name: l-worker +description: "general-purpose implementer with full tools, isolated context." +model: + - "@default" +thinkingLevel: auto +--- + +You are a worker agent with full capabilities. You operate in an isolated context window to handle delegated tasks without polluting the main conversation. + +Work autonomously to complete the assigned task. Use all available tools as needed. + +Output format when finished: + +## Completed +What was done. + +## Files Changed +- `path/to/file.ts` - what changed + +## Notes (if any) +Anything the main agent should know. + +If handing off to another agent (e.g. reviewer), include: +- Exact file paths changed +- Key functions/types touched (short list) diff --git a/modules/dotfiles/omp/prompts/implement-and-review.md b/modules/dotfiles/omp/prompts/implement-and-review.md new file mode 100644 index 0000000..92312e5 --- /dev/null +++ b/modules/dotfiles/omp/prompts/implement-and-review.md @@ -0,0 +1,12 @@ +--- +description: l-worker implements → l-reviewer reviews → l-worker applies feedback +--- +Sequential `task` chain for: + +$@ + +1. `agent: "l-worker"` — implement the request. +2. `agent: "l-reviewer"` — review the implementation (read-only); use worker summary + paths. +3. `agent: "l-worker"` — apply reviewer feedback only (minimal fixes). + +Pass outputs between steps. End with a short summary of changes + remaining risks. diff --git a/modules/dotfiles/omp/prompts/implement.md b/modules/dotfiles/omp/prompts/implement.md new file mode 100644 index 0000000..231aa78 --- /dev/null +++ b/modules/dotfiles/omp/prompts/implement.md @@ -0,0 +1,13 @@ +--- +description: l-scout → l-planner → l-worker full implementation +--- +Sequential `task` chain for: + +$@ + +1. `agent: "l-scout"` — find all code relevant to the task. +2. `agent: "l-planner"` — implementation plan from scout context (no edits). +3. `agent: "l-worker"` — implement the plan from planner output. + +Pass each step's result into the next task instructions. +After the worker finishes, briefly summarize what changed. diff --git a/modules/dotfiles/omp/prompts/planflow.md b/modules/dotfiles/omp/prompts/planflow.md new file mode 100644 index 0000000..b5f0657 --- /dev/null +++ b/modules/dotfiles/omp/prompts/planflow.md @@ -0,0 +1,15 @@ +--- +description: l-scout recon → l-expert plan/review (no implementation) +--- +Run a sequential two-agent advisory flow using the `task` tool (not parallel). + +Task: +$@ + +Flow: +1. Spawn `task` with `agent: "l-scout"` — cheap recon: relevant files, constraints, findings for the task above. +2. When scout returns, spawn `task` with `agent: "l-expert"` — plan/review/recommendation. Include the scout output in full (or via a `local://` path if huge) as context. + +Rules: +- Do **not** implement or edit files unless the user already explicitly asked for implementation. +- Return the expert recommendation clearly; ask before making changes if they did not request implementation. diff --git a/modules/dotfiles/omp/prompts/scout-and-plan-impl.md b/modules/dotfiles/omp/prompts/scout-and-plan-impl.md new file mode 100644 index 0000000..4703c9d --- /dev/null +++ b/modules/dotfiles/omp/prompts/scout-and-plan-impl.md @@ -0,0 +1,11 @@ +--- +description: l-scout → l-planner implementation plan only (no coding) +--- +Sequential `task` flow for: + +$@ + +1. `agent: "l-scout"` — find all code relevant to the task. +2. `agent: "l-planner"` — using scout findings, produce a concrete implementation plan only. + +Do **not** implement — return the plan. diff --git a/modules/dotfiles/omp/prompts/scout-and-plan.md b/modules/dotfiles/omp/prompts/scout-and-plan.md new file mode 100644 index 0000000..680382a --- /dev/null +++ b/modules/dotfiles/omp/prompts/scout-and-plan.md @@ -0,0 +1,11 @@ +--- +description: l-scout gathers context, l-expert recommends (no implementation) +--- +Sequential `task` flow for: + +$@ + +1. `agent: "l-scout"` — find relevant code and constraints. +2. `agent: "l-expert"` — using scout findings, provide plan/recommendation only. + +Do **not** implement. Return compact findings + recommendation. diff --git a/modules/dotfiles/omp/prompts/workspace-sweep.md b/modules/dotfiles/omp/prompts/workspace-sweep.md new file mode 100644 index 0000000..4d56651 --- /dev/null +++ b/modules/dotfiles/omp/prompts/workspace-sweep.md @@ -0,0 +1,17 @@ +--- +description: Audit current jj workspace state and propose next actions +--- +Audit the current workspace with a jj-first workflow. + +Use read-only inspection and summarize: +1. Current workspace/change state +2. Files changed and risk hotspots +3. Suggested next actions (commit/split/rebase/test) + +Suggested commands: +- `jj workspace list --color=never` +- `jj status --color=never` +- `jj log -r @-::@ --no-graph` +- `jj diff --color=never` + +No file edits unless the user asks. diff --git a/modules/dotfiles/omp/prompts/workspace-team.md b/modules/dotfiles/omp/prompts/workspace-team.md new file mode 100644 index 0000000..5806c15 --- /dev/null +++ b/modules/dotfiles/omp/prompts/workspace-team.md @@ -0,0 +1,17 @@ +--- +description: l-scout + l-expert in a specific workspace (first arg = cwd) +--- +Run a two-agent advisory flow in this workspace: + +Workspace (cwd): +$1 + +Task: +${@:2} + +Sequential `task` spawns, each with working directory / focus on `"$1"`: +1. `agent: "l-scout"` — cheap recon for the task in that workspace. +2. `agent: "l-expert"` — recommendation/review using scout output. + +Do **not** implement automatically. +Final output: relevant files, recommendation, validation steps, remaining risks.