diff --git a/CLAUDE.md b/CLAUDE.md index 295409c..62bf34e 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -1,10 +1,13 @@ # CLAUDE.md -This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. +This file provides guidance to Claude Code (claude.ai/code) when working with +code in this repository. ## Overview -Cross-platform dotfiles managed with Nix flakes, nix-darwin (macOS), and Home Manager (Linux). Provides reproducible system and user-level configuration with host-specific overrides. +Cross-platform dotfiles managed with Nix flakes, nix-darwin (macOS), and Home +Manager (Linux). Provides reproducible system and user-level configuration with +host-specific overrides. ## Common Commands @@ -37,11 +40,16 @@ nvim-dev [files] ## Architecture -- **flake.nix** - Entry point defining inputs, outputs, and all configurations. Contains `mkDarwinConfiguration` and `mkHomeConfiguration` helper functions. -- **home-manager/home.nix** - Main Home Manager config importing all program modules -- **home-manager/programs/*.nix** - Modular program configurations (git, fish, claude-code, etc.) -- **nix-darwin/base.nix** - macOS system-level config (keyboard, homebrew, GUI apps). Includes Home Manager as a module. -- **config/nvim/** - Neovim IDE configuration (Lua-based with LSP, Telescope, Treesitter) +- **flake.nix** - Entry point defining inputs, outputs, and all configurations. + Contains `mkDarwinConfiguration` and `mkHomeConfiguration` helper functions. +- **home-manager/home.nix** - Main Home Manager config importing all program + modules +- **home-manager/programs/*.nix** - Modular program configurations (git, fish, + claude-code, etc.) +- **nix-darwin/base.nix** - macOS system-level config (keyboard, homebrew, GUI + apps). Includes Home Manager as a module. +- **config/nvim/** - Neovim IDE configuration (Lua-based with LSP, Telescope, + Treesitter) - **secrets/** - Encrypted secrets using sops-nix with age encryption ## Key Conventions diff --git a/config/fish/config.fish b/config/fish/config.fish new file mode 100644 index 0000000..4095a3d --- /dev/null +++ b/config/fish/config.fish @@ -0,0 +1,3 @@ +if status is-interactive +# Commands to run in interactive sessions can go here +end diff --git a/config/fish/fish_variables b/config/fish/fish_variables new file mode 100644 index 0000000..ad10b9b --- /dev/null +++ b/config/fish/fish_variables @@ -0,0 +1,3 @@ +# This file contains fish universal variable definitions. +# VERSION: 3.0 +SETUVAR __fish_initialized:4300 diff --git a/config/nvim/init.lua b/config/nvim/init.lua index 3270e18..37a3626 100644 --- a/config/nvim/init.lua +++ b/config/nvim/init.lua @@ -75,6 +75,11 @@ vim.opt.cursorline = true -- Minimal number of screen lines to keep above and below the cursor. vim.opt.scrolloff = 10 +-- Treesitter-based folding. +vim.o.foldmethod = "expr" +vim.o.foldexpr = "v:lua.vim.treesitter.foldexpr()" +vim.o.foldlevelstart = 99 + -- [[ Basic Keymaps ]] -- See `:help vim.keymap.set()` diff --git a/config/nvim/lazy-lock.json b/config/nvim/lazy-lock.json index ff3a710..a7b0bc5 100644 --- a/config/nvim/lazy-lock.json +++ b/config/nvim/lazy-lock.json @@ -1,31 +1,31 @@ { - "blink.cmp": { "branch": "main", "commit": "4b18c32adef2898f95cdef6192cbd5796c1a332d" }, + "blink.cmp": { "branch": "main", "commit": "78336bc89ee5365633bcf754d93df01678b5c08f" }, "codesnap.nvim": { "branch": "main", "commit": "0a0941340376439a25d6cd8a4d1d2b372edbfdbd" }, - "conform.nvim": { "branch": "master", "commit": "086a40dc7ed8242c03be9f47fbcee68699cc2395" }, - "fidget.nvim": { "branch": "main", "commit": "7fa433a83118a70fe24c1ce88d5f0bd3453c0970" }, + "conform.nvim": { "branch": "master", "commit": "dca1a190aa85f9065979ef35802fb77131911106" }, + "fidget.nvim": { "branch": "main", "commit": "889e2e96edef4e144965571d46f7a77bcc4d0ddf" }, "friendly-snippets": { "branch": "main", "commit": "6cd7280adead7f586db6fccbd15d2cac7e2188b9" }, "git-blame.nvim": { "branch": "main", "commit": "5c536e2d4134d064aa3f41575280bc8a2a0e03d7" }, - "gitsigns.nvim": { "branch": "main", "commit": "7c4faa3540d0781a28588cafbd4dd187a28ac6e3" }, + "gitsigns.nvim": { "branch": "main", "commit": "6d808f99bd63303646794406e270bd553ad7792e" }, "lazy.nvim": { "branch": "main", "commit": "306a05526ada86a7b30af95c5cc81ffba93fef97" }, - "lazydev.nvim": { "branch": "main", "commit": "5231c62aa83c2f8dc8e7ba957aa77098cda1257d" }, - "lualine.nvim": { "branch": "master", "commit": "47f91c416daef12db467145e16bed5bbfe00add8" }, + "lazydev.nvim": { "branch": "main", "commit": "ff2cbcba459b637ec3fd165a2be59b7bbaeedf0d" }, + "lualine.nvim": { "branch": "master", "commit": "a905eeebc4e63fdc48b5135d3bf8aea5618fb21c" }, "noice.nvim": { "branch": "main", "commit": "7bfd942445fb63089b59f97ca487d605e715f155" }, "nui.nvim": { "branch": "main", "commit": "de740991c12411b663994b2860f1a4fd0937c130" }, "nvim-autopairs": { "branch": "master", "commit": "59bce2eef357189c3305e25bc6dd2d138c1683f5" }, - "nvim-lint": { "branch": "master", "commit": "606b823a57b027502a9ae00978ebf4f5d5158098" }, - "nvim-lspconfig": { "branch": "master", "commit": "0203a9608d63eda57679b01e69f33a7b4c34b0d1" }, + "nvim-lint": { "branch": "master", "commit": "eab58b48eb11d7745c11c505e0f3057165902461" }, + "nvim-lspconfig": { "branch": "master", "commit": "eeef061d58d759b5419c1e20c4b3a5bc3154f871" }, "nvim-notify": { "branch": "master", "commit": "8701bece920b38ea289b457f902e2ad184131a5d" }, "nvim-surround": { "branch": "main", "commit": "61319d4bd1c5e336e197defa15bd104c51f0fb29" }, - "nvim-tree.lua": { "branch": "master", "commit": "a0db8bf7d6488b1dcd9cb5b0dfd6684a1e14f769" }, - "nvim-treesitter": { "branch": "master", "commit": "42fc28ba918343ebfd5565147a42a26580579482" }, - "nvim-treesitter-context": { "branch": "master", "commit": "529ee357b8c03d76ff71233afed68fd0f5fe10b1" }, - "nvim-web-devicons": { "branch": "master", "commit": "d7462543c9e366c0d196c7f67a945eaaf5d99414" }, - "plenary.nvim": { "branch": "master", "commit": "b9fd5226c2f76c951fc8ed5923d85e4de065e509" }, - "render-markdown.nvim": { "branch": "main", "commit": "e3c18ddd27a853f85a6f513a864cf4f2982b9f26" }, - "snacks.nvim": { "branch": "main", "commit": "9912042fc8bca2209105526ac7534e9a0c2071b2" }, + "nvim-tree.lua": { "branch": "master", "commit": "85d1145ac71c1b8e1423862c78165a1f609faf60" }, + "nvim-treesitter": { "branch": "main", "commit": "4916d6592ede8c07973490d9322f187e07dfefac" }, + "nvim-treesitter-context": { "branch": "master", "commit": "b0c45cefe2c8f7b55fc46f34e563bc428ef99636" }, + "nvim-web-devicons": { "branch": "master", "commit": "8069e89df2d7259704286a5906a11c5b27d5b440" }, + "plenary.nvim": { "branch": "master", "commit": "74b06c6c75e4eeb3108ec01852001636d85a932b" }, + "render-markdown.nvim": { "branch": "main", "commit": "3f3eea97b80839f629c951ca660ffd125bfa5b34" }, + "snacks.nvim": { "branch": "main", "commit": "ad9ede6a9cddf16cedbd31b8932d6dcdee9b716e" }, "telescope.nvim": { "branch": "master", "commit": "3333a52ff548ba0a68af6d8da1e54f9cd96e9179" }, "todo-comments.nvim": { "branch": "main", "commit": "31e3c38ce9b29781e4422fc0322eb0a21f4e8668" }, - "tokyonight.nvim": { "branch": "main", "commit": "5da1b76e64daf4c5d410f06bcb6b9cb640da7dfd" }, + "tokyonight.nvim": { "branch": "main", "commit": "cdc07ac78467a233fd62c493de29a17e0cf2b2b6" }, "vscpanel.nvim": { "branch": "main", "commit": "d38fe9d56ef681452633f75ad721256ce3888b36" }, "which-key.nvim": { "branch": "main", "commit": "3aab2147e74890957785941f0c1ad87d0a44c15a" } } diff --git a/config/nvim/lua/custom/plugins/lsp.lua b/config/nvim/lua/custom/plugins/lsp.lua index 8249a79..a34d282 100644 --- a/config/nvim/lua/custom/plugins/lsp.lua +++ b/config/nvim/lua/custom/plugins/lsp.lua @@ -68,6 +68,8 @@ return { phpactor = {}, -- https://github.com/python-lsp/python-lsp-server pylsp = {}, + -- https://github.com/swiftlang/sourcekit-lsp + sourcekit = {}, -- https://github.com/tailwindlabs/tailwindcss-intellisense tailwindcss = {}, -- https://github.com/hashicorp/terraform-ls diff --git a/config/nvim/lua/custom/plugins/treesitter.lua b/config/nvim/lua/custom/plugins/treesitter.lua index 3746f38..d9a2c93 100644 --- a/config/nvim/lua/custom/plugins/treesitter.lua +++ b/config/nvim/lua/custom/plugins/treesitter.lua @@ -1,8 +1,9 @@ return { { 'nvim-treesitter/nvim-treesitter', + branch = 'main', build = ':TSUpdate', - main = 'nvim-treesitter.configs', + main = 'nvim-treesitter', opts = { ensure_installed = { 'bash', @@ -14,6 +15,7 @@ return { 'html', 'http', 'javascript', + 'json', 'jsonc', 'lua', 'luadoc', diff --git a/flake.lock b/flake.lock index 4c5a5d6..eaab84e 100644 --- a/flake.lock +++ b/flake.lock @@ -7,11 +7,11 @@ ] }, "locked": { - "lastModified": 1772633327, - "narHash": "sha256-jl+DJB2DUx7EbWLRng+6HNWW/1/VQOnf0NsQB4PlA7I=", + "lastModified": 1778144356, + "narHash": "sha256-dGM+QCstz/DyLB68+JK5GWyMx4QSqmOJEVgZmy63d/g=", "owner": "nix-community", "repo": "home-manager", - "rev": "5a75730e6f21ee624cbf86f4915c6e7489c74acc", + "rev": "e4419d3123b780d5f4c0bceeace450424387638c", "type": "github" }, "original": { @@ -27,11 +27,11 @@ ] }, "locked": { - "lastModified": 1772379624, - "narHash": "sha256-NG9LLTWlz4YiaTAiRGChbrzbVxBfX+Auq4Ab/SWmk4A=", + "lastModified": 1777780666, + "narHash": "sha256-8wURyQMdDkGUarSTKOGdCuFfYiwa3HbzwscUfn3STDE=", "owner": "nix-darwin", "repo": "nix-darwin", - "rev": "52d061516108769656a8bd9c6e811c677ec5b462", + "rev": "8c62fba0854ba15c8917aed18894dbccb48a3777", "type": "github" }, "original": { @@ -42,11 +42,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1772615108, - "narHash": "sha256-lC0KbklwgeSqS+sTkaYpnSYr/HDeVMzYUZqV/dT31Lo=", + "lastModified": 1778124196, + "narHash": "sha256-pYEytCNic/czazbV9r3tbQ6BZzqRBg/41x2dIC5ymOo=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "0c39f3b5a9a234421d4ad43ab9c7cf64840172d0", + "rev": "68a8af93ff4297686cb68880845e61e5e2e41d92", "type": "github" }, "original": { @@ -71,11 +71,11 @@ ] }, "locked": { - "lastModified": 1772495394, - "narHash": "sha256-hmIvE/slLKEFKNEJz27IZ8BKlAaZDcjIHmkZ7GCEjfw=", + "lastModified": 1777944972, + "narHash": "sha256-VfGRo1qTBKOe3s2gOv8LSoA6Fk19PvBlwQ1ECN0Evn8=", "owner": "Mic92", "repo": "sops-nix", - "rev": "1d9b98a29a45abe9c4d3174bd36de9f28755e3ff", + "rev": "c591bf665727040c6cc5cb409079acb22dcce33c", "type": "github" }, "original": { diff --git a/home-manager/home.nix b/home-manager/home.nix index 889f610..3567b84 100644 --- a/home-manager/home.nix +++ b/home-manager/home.nix @@ -19,6 +19,7 @@ ./programs/jujutsu.nix ./programs/k9s.nix ./programs/mcp.nix + ./programs/opencode.nix ./programs/sops.nix ./programs/starship.nix ./programs/tmux.nix @@ -54,6 +55,7 @@ pkgs.phpactor pkgs.python313Packages.python-lsp-server pkgs.shellcheck + pkgs.sourcekit-lsp pkgs.tailwindcss-language-server pkgs.terraform-ls pkgs.tree-sitter @@ -70,6 +72,7 @@ pkgs.bat pkgs.bazel_8 pkgs.cmake + pkgs.codex pkgs.delta pkgs.dive pkgs.exercism @@ -79,6 +82,7 @@ pkgs.graphviz pkgs.hyperfine pkgs.imagemagick + pkgs.jjui pkgs.jq pkgs.just pkgs.kind @@ -89,8 +93,8 @@ pkgs.lazygit pkgs.lua51Packages.lua pkgs.luajitPackages.luarocks - pkgs.opencode pkgs.neovim + pkgs.ngrok pkgs.nh pkgs.nodejs_24 pkgs.php diff --git a/home-manager/programs/claude-code.nix b/home-manager/programs/claude-code.nix index d08a0dc..d9d7691 100644 --- a/home-manager/programs/claude-code.nix +++ b/home-manager/programs/claude-code.nix @@ -5,10 +5,8 @@ enableMcpIntegration = true; - agents = { - notes--daily-summary = ./../../agents/notes/daily-summary.md; - image--svg-to-png = ./../../agents/image/svg-to-png.md; - }; + agentsDir = ./../../agents; + skills = ./../../skills; settings = { permissions = { diff --git a/home-manager/programs/gpg.nix b/home-manager/programs/gpg.nix index aabf9af..cacf5fe 100644 --- a/home-manager/programs/gpg.nix +++ b/home-manager/programs/gpg.nix @@ -1,7 +1,18 @@ -{pkgs, ...}: { +{ + pkgs, + lib, + system, + ... +}: let + isDarwin = lib.hasInfix "darwin" system; + pinentryPkg = + if isDarwin + then pkgs.pinentry_mac + else pkgs.pinentry-curses; +in { home.packages = with pkgs; [ gnupg - pinentry-curses + pinentryPkg ]; programs.gpg = { @@ -17,7 +28,7 @@ services.gpg-agent = { enable = true; enableFishIntegration = true; - pinentry.package = pkgs.pinentry-curses; + pinentry.package = pinentryPkg; defaultCacheTtl = 28800; # 8 hours maxCacheTtl = 86400; # 24 hours }; diff --git a/home-manager/programs/opencode.nix b/home-manager/programs/opencode.nix new file mode 100644 index 0000000..779998c --- /dev/null +++ b/home-manager/programs/opencode.nix @@ -0,0 +1,22 @@ +# https://github.com/nix-community/home-manager/blob/master/modules/programs/opencode.nix +{...}: { + programs.opencode = { + enable = true; + settings = { + provider = { + lmstudio = { + npm = "@ai-sdk/openai-compatible"; + name = "LM Studio"; + options = { + baseURL = "http://127.0.0.1:1234/v1"; + }; + models = { + "qwen3.6-35b-a3b-nvfp4" = { + name = "Qwen 3.6"; + }; + }; + }; + }; + }; + }; +} diff --git a/nix-darwin/base.nix b/nix-darwin/base.nix index 78fe581..eb43b8e 100644 --- a/nix-darwin/base.nix +++ b/nix-darwin/base.nix @@ -39,6 +39,7 @@ casks = [ "devtoys" "headlamp" + "lm-studio" ]; }; diff --git a/skills/jj-describe/SKILL.md b/skills/jj-describe/SKILL.md new file mode 100644 index 0000000..a21e7b1 --- /dev/null +++ b/skills/jj-describe/SKILL.md @@ -0,0 +1,77 @@ +--- +name: jj-describe +description: Describe jujutsu changes with a markdown-formatted message suitable for GitHub PRs. Use when the user asks to describe, commit, or summarize their current jj changes, or after a logical chunk of work is completed. +allowed-tools: Bash(jj *) Read Grep Glob +--- + +## Instructions + +Analyze the current jujutsu change and write a description for it. The +description will be used as a GitHub PR where the first line becomes the PR +title and the rest becomes the PR body. + +### Step 1: Gather context + +Run these commands in parallel to understand the current change: + +```! +jj status +``` + +```! +jj diff --stat +``` + +```! +jj log -r @ --no-graph -T 'concat(change_id, "\n", commit_id, "\n", description, "\n", bookmarks)' +``` + +```! +jj log --no-graph -r 'ancestors(@, 5)' -T 'concat(change_id.shortest(), " ", description.first_line(), "\n")' +``` + +### Step 2: Inspect the full diff + +Run `jj diff` to see the complete diff for the current change. For large diffs, +read specific modified files as needed to understand the changes. + +### Step 3: Write the description + +Compose a description following this format: + +``` + + +## Summary +<1-3 bullet points describing what changed and why> + +## Changes +<bulleted list of specific changes, grouped by area if needed> +``` + +Guidelines: +- **Title**: Use Conventional Commits (`feat:`, `fix:`, `chore:`, `docs:`, + `refactor:`, `test:`). Keep under 72 characters. Capitalize the first word + after the prefix (e.g., `feat: Add new feature`). Focus on the "what" at a + high level. +- **Summary**: Explain the motivation and impact. Focus on "why" over "what". +- **Changes**: List specific changes. Group by file or area for larger changes. +- Omit the Summary or Changes section if the change is trivial (e.g., a one-line + fix). +- Do not include `Co-Authored-By` lines. + +### Step 4: Apply the description + +Use `jj describe -m` to set the description on the current change. Pass the +message via a HEREDOC: + +```bash +jj describe -m "$(cat <<'EOF' +<description here> +EOF +)" +``` + +### Step 5: Confirm + +Show the user the final description by running `jj log -r @ --no-graph`.