diff --git a/CLAUDE.md b/CLAUDE.md index 8204b89..3e62b02 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -66,6 +66,28 @@ When working in this repository, you're reading both the global AGENTS.md (gener - `encrypted_*.age` age-encrypted files (safe to commit) - `run_onchange_*` executable scripts that run during apply +**Finding Files - Template Extension Patterns:** + +⚠️ **CRITICAL**: Most managed files have `.tmpl` extensions. Use wildcard patterns to find both base and `.tmpl` variants in one search. + +Common patterns where `.tmpl` is added to the FULL filename: +- `config.md` → `config.md.tmpl` (NOT `config.tmpl`) +- `settings.json` → `settings.json.tmpl` (NOT `settings.tmpl`) +- `config.ts` → `config.ts.tmpl` (NOT `config.tmpl`) +- `.bashrc` → `dot_bashrc.tmpl` (combines `dot_` and `.tmpl`) +- `.config/opencode/opencode.jsonc` → `dot_config/opencode/opencode.jsonc.tmpl` + +**Search strategy - Use wildcards to catch both variants:** +- Pattern: `**/filename*` (e.g., `**/CLAUDE.md*` finds both `CLAUDE.md` AND `CLAUDE.md.tmpl`) +- Pattern: `**/*.ext.tmpl` for type-specific template files (e.g., `**/*.ts.tmpl`, `**/*.json.tmpl`) +- Check both `home/` and `home/.chezmoitemplates/` directories + +**Examples:** +- Looking for "CLAUDE.md"? → Search `**/CLAUDE.md*` (finds both base and `.tmpl`) +- Looking for "config.nu"? → Search `**/config.nu*` (finds both variants) +- Looking for all TypeScript templates? → Search `**/*.ts.tmpl` +- Looking for all JSON configs? → Search `**/*.json*` (finds `.json` and `.json.tmpl`) + **Template System:** - Uses Go templates with platform detection - Two types of templates with different variable access patterns: diff --git a/home/.chezmoi.toml.tmpl b/home/.chezmoi.toml.tmpl index 248ca92..91c2955 100644 --- a/home/.chezmoi.toml.tmpl +++ b/home/.chezmoi.toml.tmpl @@ -45,10 +45,11 @@ encryption = "age" [merge] -command = "bash" +command = "chezmoi-merge-helper.sh" args = [ - "-c", - "cp {{ "{{" }} .Target {{ "}}" }} {{ "{{" }} .Target {{ "}}" }}.base && code --new-window --wait --merge {{ "{{" }} .Destination {{ "}}" }} {{ "{{" }} .Target {{ "}}" }} {{ "{{" }} .Target {{ "}}" }}.base {{ "{{" }} .Source {{ "}}" }}", + "{{ "{{" }} .Destination {{ "}}" }}", + "{{ "{{" }} .Target {{ "}}" }}", + "{{ "{{" }} .Source {{ "}}" }}", ] [data] diff --git a/home/dot_claude/CLAUDE.md.tmpl b/home/dot_claude/CLAUDE.md.tmpl index 45c00ea..4a39123 100644 --- a/home/dot_claude/CLAUDE.md.tmpl +++ b/home/dot_claude/CLAUDE.md.tmpl @@ -221,38 +221,88 @@ When a project uses `assert2`: - Grep tool for searching (not `grep`, `rg`) - Bash ONLY for actual system commands and terminal operations -### GitHub File Fetching +### GitHub & External Resources -When fetching files from GitHub repositories: +**Fetching file content from GitHub:** - **STRONGLY prefer raw.githubusercontent.com over github.com** - Raw URLs return plain content without HTML wrapper - simpler and faster - Pattern: `https://raw.githubusercontent.com/{owner}/{repo}/{branch}/{path}` - - Example: `https://raw.githubusercontent.com/user/repo/main/src/file.rs` + - For specific commits/tags: `https://raw.githubusercontent.com/{owner}/{repo}/{commit-sha}/{path}` - Only use github.com URLs when you need the web interface or rendered view -- **Use GitHub CLI (`gh`) for repository operations** - - Perfect for metadata and repository management - - Examples: `gh repo view`, `gh issue list`, `gh pr view`, `gh pr checkout` - - More reliable than web scraping for structured data +**GitHub CLI (`gh`) for everything else:** -- **Use MCP gh_grep tool for code search** (see below) +- **Authenticated API access** - use `gh api` for direct GitHub API calls: + - `gh api repos/{owner}/{repo}/releases/latest` - get latest release info + - `gh api repos/{owner}/{repo}/contents/{path}` - get file metadata/content + - `gh api repos/{owner}/{repo}` - get repository details + - Supports GraphQL: `gh api graphql -f query='...'` + +- **Search GitHub** - use `gh search` subcommands: + - `gh search repos "query"` - find repositories + - `gh search issues "query" --repo owner/repo` - search issues + - `gh search code "query"` - GitHub's native code search (different from gh_grep) + +- **Repository operations** - metadata and management: + - `gh repo view owner/repo` - repository info + - `gh release list -R owner/repo` - list releases with versions + - `gh issue/pr view` - issue and PR details ### MCP Tools (When Available) -**gh_grep (GitHub Code Search)** -- Search real-world code examples from 1M+ public repos -- Use for: unfamiliar APIs, usage patterns, real implementation examples -- Search for **literal code**, not keywords: `'useState('`, `'async function'`, `'import React from'` -- Use regex with `useRegexp: true` for flexible patterns: `'(?s)useEffect\\(\\(\\) => {.*cleanup'` -- Filter by `language`, `repo`, or `path` to narrow results -- Perfect for seeing how others solve similar problems +**gh_grep - CRITICAL: THIS IS LITERAL PATTERN MATCHING, NOT SEMANTIC SEARCH** + +This tool searches for **exact character sequences** in source code files. It is `grep`, not Google. + +It CANNOT: +- Understand what you're looking for conceptually +- Find "related" code or similar patterns +- Interpret natural language or keywords + +❌ **WRONG** - these will fail or return garbage: +- `"how to handle errors"` → literally searches for that sentence in code +- `"authentication"` → only finds that exact word as a string, not auth implementations +- `"best practices"` → completely useless +- `"react state management"` → meaningless as a code pattern + +✅ **CORRECT** - search for actual code that appears in source files: +- `'useAuth('` → finds useAuth function calls +- `'catch (AuthError'` → finds specific error handling +- `'implements OAuth'` → finds class implementations +- `'(?s)async function.*await fetch'` with `useRegexp: true` → async functions with fetch + +**Rule of thumb**: If your query wouldn't make sense copy-pasted into a source file, it's wrong. + +Use `language`, `repo`, and `path` filters to narrow results. **context7 (Library Documentation)** - Get up-to-date docs for libraries/frameworks -- Two-step process: `resolve-library-id` → `get-library-docs` -- Use `mode: 'code'` for API references (default), `mode: 'info'` for guides -- Prefer when you need official docs vs community examples +- Two-step process: `resolve-library-id` → `query-docs` +- Prefer when you need official documentation vs community examples from gh_grep + +## Useful CLI Tools + +Prefer these over convoluted bash pipelines or manual parsing. + +**JSON Processing (`jq`):** +- Use for parsing API responses, transforming configs, extracting data +- Example: `gh api repos/owner/repo/releases | jq '.[0] | {tag: .tag_name, date: .published_at}'` +- Pipe any JSON output through jq for readable formatting: `... | jq .` + +**Quick TypeScript Scripts (`bun`):** +- When shell gets too complex, write a quick inline script instead +- Prefer over chained `sed`/`awk`/`grep` pipelines for data transformation +- Example: `bun -e "console.log(JSON.parse(require('fs').readFileSync('data.json')).items.filter(x => x.active).length)"` +- Can also run `.ts` files directly: `bun run script.ts` + +**Benchmarking (`hyperfine`):** +- Compare command performance: `hyperfine 'command1' 'command2'` +- Useful for verifying optimization claims + +**Codebase Statistics (`tokei`):** +- Quick language breakdown and LOC counts: `tokei .` +- Useful for understanding unfamiliar codebases ## Security & Error Handling diff --git a/home/dot_config/fish/functions/chmerge.fish b/home/dot_config/fish/functions/chmerge.fish new file mode 100644 index 0000000..3558ec7 --- /dev/null +++ b/home/dot_config/fish/functions/chmerge.fish @@ -0,0 +1,30 @@ +function chmerge --description "Interactively merge chezmoi conflicts using fzf" + # Get files with merge conflicts (MM = modified in both source and target) + set -l conflict_files (chezmoi status | grep '^MM ' | awk '{print $2}') + + if test (count $conflict_files) -eq 0 + echo "No merge conflicts found." + return 0 + end + + # Use fzf for selection with multi-select enabled + set -l selected (printf '%s\n' $conflict_files | fzf \ + --multi \ + --preview 'chezmoi diff {}' \ + --preview-window 'right:70%:wrap' \ + --header 'Select files to merge (Tab for multi-select, Enter to confirm)' \ + --bind 'ctrl-/:toggle-preview') + + if test (count $selected) -eq 0 + echo "No files selected." + return 0 + end + + # Convert to absolute target paths and merge + for file in $selected + # Expand ~ to home directory for chezmoi merge + set -l target_path (string replace -r '^~' $HOME $file) + echo "Merging: $file" + chezmoi merge $target_path + end +end diff --git a/home/dot_local/bin/executable_chezmoi-merge-helper.sh b/home/dot_local/bin/executable_chezmoi-merge-helper.sh new file mode 100644 index 0000000..5b6e846 --- /dev/null +++ b/home/dot_local/bin/executable_chezmoi-merge-helper.sh @@ -0,0 +1,41 @@ +#!/usr/bin/env bash +# Helper script for chezmoi merge with clear labels +# Arguments: $1=destination $2=target $3=source + +destination="$1" +target="$2" +source="$3" + +# Create base file (copy of target state) +base="${target}.base" +cp "$target" "$base" + +# Show clear explanation before merge +cat << EOF +╔════════════════════════════════════════════════════════════════╗ +║ CHEZMOI MERGE LAYOUT ║ +╠════════════════════════════════════════════════════════════════╣ +║ ║ +║ LEFT (Current): DESTINATION - File in your home dir ║ +║ ↓ External changes (e.g., app updates) ║ +║ ║ +║ RIGHT (Incoming): TARGET - What chezmoi wants to apply ║ +║ ↓ Your chezmoi changes (templates, etc) ║ +║ ║ +║ BOTTOM (Result): SOURCE - Will be saved to chezmoi repo ║ +║ ║ +╠════════════════════════════════════════════════════════════════╣ +║ File: $(basename "$destination") +╚════════════════════════════════════════════════════════════════╝ + +Press Enter to open merge editor... +EOF + +read -r + +# Launch VSCode merge +# Syntax: code --merge +code --new-window --wait --merge "$destination" "$target" "$base" "$source" + +# Cleanup +rm -f "$base"