Commit 3c0537bbb520

Vincent Demeester <vincent@sbr.pm>
2025-12-04 10:54:29
feat: Migrate Claude Code config to XDG Base Directory
- Comply with XDG Base Directory specification for better organization - Maintain backward compatibility via ~/.claude symlink - Enable consistent config location across XDG-compliant systems Co-Authored-By: Claude <noreply@anthropic.com> Signed-off-by: Vincent Demeester <vincent@sbr.pm>
1 parent daa9854
dots/.claude/agents/architect.md → dots/.config/claude/agents/architect.md
File renamed without changes
dots/.claude/agents/claude-researcher.md → dots/.config/claude/agents/claude-researcher.md
File renamed without changes
dots/.claude/agents/designer.md → dots/.config/claude/agents/designer.md
File renamed without changes
dots/.claude/agents/engineer.md → dots/.config/claude/agents/engineer.md
File renamed without changes
dots/.claude/agents/researcher.md → dots/.config/claude/agents/researcher.md
File renamed without changes
dots/.claude/hooks/lib/claude-paths.ts → dots/.config/claude/hooks/lib/claude-paths.ts
File renamed without changes
dots/.claude/hooks/capture-tool-output.ts → dots/.config/claude/hooks/capture-tool-output.ts
File renamed without changes
dots/.claude/hooks/initialize-session.ts → dots/.config/claude/hooks/initialize-session.ts
File renamed without changes
dots/.claude/hooks/README.md → dots/.config/claude/hooks/README.md
@@ -22,7 +22,7 @@ Adapted from [Personal AI Infrastructure](https://github.com/danielmiessler/Pers
 ```json
 {
   "hooks": {
-    "SessionStart": ["bun ~/.claude/hooks/initialize-session.ts"]
+    "SessionStart": ["bun ~/.config/claude/hooks/initialize-session.ts"]
   }
 }
 ```
@@ -36,14 +36,14 @@ Adapted from [Personal AI Infrastructure](https://github.com/danielmiessler/Pers
 **What it does**:
 - Captures outputs from interesting tools (Bash, Edit, Write, Read, Task, etc.)
 - Logs to JSONL files organized by year-month
-- Stores in `~/.claude/history/tool-outputs/YYYY-MM/YYYY-MM-DD_tool-outputs.jsonl`
+- Stores in `~/.config/claude/history/tool-outputs/YYYY-MM/YYYY-MM-DD_tool-outputs.jsonl`
 - Silent failure - doesn't disrupt workflow
 
 **Setup**:
 ```json
 {
   "hooks": {
-    "PostToolUse": ["bun ~/.claude/hooks/capture-tool-output.ts"]
+    "PostToolUse": ["bun ~/.config/claude/hooks/capture-tool-output.ts"]
   }
 }
 ```
@@ -70,7 +70,7 @@ Adapted from [Personal AI Infrastructure](https://github.com/danielmiessler/Pers
 **Usage**:
 ```bash
 # Run manually
-bun ~/.claude/hooks/validate-docs.ts
+bun ~/.config/claude/hooks/validate-docs.ts
 
 # Add to pre-commit (optional)
 ```
@@ -96,7 +96,7 @@ The following hooks from PAI were **not imported** as they require more setup or
 ### Directory Structure
 
 ```
-~/.claude/hooks/
+~/.config/claude/hooks/
 ├── README.md                    # This file
 ├── lib/
 │   └── claude-paths.ts         # Path utilities
@@ -108,21 +108,23 @@ The following hooks from PAI were **not imported** as they require more setup or
 ### Helper Library: lib/claude-paths.ts
 
 Provides:
-- `CLAUDE_DIR`: Base directory (~/.claude)
+- `CLAUDE_DIR`: Base directory (~/.config/claude)
 - `HOOKS_DIR`, `SKILLS_DIR`, `AGENTS_DIR`, `HISTORY_DIR`: Subdirectories
 - `getHistoryFilePath(subdir, filename)`: Generate history file paths
 - `getTimestamp()`: Get formatted timestamp
 - Path validation on import
 
+**Note**: For backward compatibility, `~/.claude/` is symlinked to `~/.config/claude/`.
+
 ## Configuration
 
-Hooks are configured in Claude Code settings (`.claude/settings.json` or `.claude/settings.local.json`):
+Hooks are configured in Claude Code settings (`.config/claude/settings.json` or `.config/claude/settings.local.json`):
 
 ```json
 {
   "hooks": {
-    "SessionStart": ["bun ~/.claude/hooks/initialize-session.ts"],
-    "PostToolUse": ["bun ~/.claude/hooks/capture-tool-output.ts"]
+    "SessionStart": ["bun ~/.config/claude/hooks/initialize-session.ts"],
+    "PostToolUse": ["bun ~/.config/claude/hooks/capture-tool-output.ts"]
   }
 }
 ```
@@ -146,10 +148,10 @@ Available hook events:
 
 ## History Logging
 
-Hooks that capture data store it in `~/.claude/history/`:
+Hooks that capture data store it in `~/.config/claude/history/`:
 
 ```
-~/.claude/history/
+~/.config/claude/history/
 ├── sessions/
 │   └── YYYY-MM/
 │       └── YYYY-MM-DD_session-log.txt
@@ -158,13 +160,13 @@ Hooks that capture data store it in `~/.claude/history/`:
         └── YYYY-MM-DD_tool-outputs.jsonl
 ```
 
-This integrates with the history system documented in `.claude/skills/CORE/history-system.md`.
+This integrates with the history system documented in `.config/claude/skills/CORE/history-system.md`.
 
 ## Adding More Hooks
 
 To add additional hooks:
 
-1. Create the hook file in `~/.claude/hooks/`
+1. Create the hook file in `~/.config/claude/hooks/`
 2. Add shebang: `#!/usr/bin/env bun`
 3. Make it executable: `chmod +x hook-name.ts`
 4. Use `lib/claude-paths.ts` for paths
@@ -175,18 +177,18 @@ To add additional hooks:
 
 **Hook not running:**
 - Check settings.json syntax
-- Verify file is executable (`ls -la ~/.claude/hooks/`)
+- Verify file is executable (`ls -la ~/.config/claude/hooks/`)
 - Check hook output in stderr
 - Verify Bun is installed: `bun --version`
 
 **Permission errors:**
-- Ensure directories exist: `mkdir -p ~/.claude/history/{sessions,tool-outputs}`
+- Ensure directories exist: `mkdir -p ~/.config/claude/history/{sessions,tool-outputs}`
 - Check write permissions
 
 **Debugging:**
 - Hooks write to stderr - check terminal output
 - Add debug logging: `console.error('[hook-name] Debug message')`
-- Run manually: `bun ~/.claude/hooks/hook-name.ts`
+- Run manually: `bun ~/.config/claude/hooks/hook-name.ts`
 
 ## Future Enhancements
 
dots/.claude/hooks/validate-docs.ts → dots/.config/claude/hooks/validate-docs.ts
File renamed without changes
dots/.claude/plugins/session-manager/commands/save-session.md → dots/.config/claude/plugins/session-manager/commands/save-session.md
File renamed without changes
dots/.claude/plugins/session-manager/plugin.json → dots/.config/claude/plugins/session-manager/plugin.json
File renamed without changes
dots/.claude/skills/Art/workflows/Mermaid.md → dots/.config/claude/skills/Art/workflows/Mermaid.md
File renamed without changes
dots/.claude/skills/Art/workflows/Visualize.md → dots/.config/claude/skills/Art/workflows/Visualize.md
File renamed without changes
dots/.claude/skills/Art/SKILL.md → dots/.config/claude/skills/Art/SKILL.md
File renamed without changes
dots/.claude/skills/CORE/CONSTITUTION.md → dots/.config/claude/skills/CORE/CONSTITUTION.md
File renamed without changes
dots/.claude/skills/CORE/history-system.md → dots/.config/claude/skills/CORE/history-system.md
File renamed without changes
dots/.claude/skills/CORE/prompting.md → dots/.config/claude/skills/CORE/prompting.md
File renamed without changes
dots/.claude/skills/CORE/SKILL.md → dots/.config/claude/skills/CORE/SKILL.md
File renamed without changes
dots/.claude/skills/Createskill/workflows/CreateSkill.md → dots/.config/claude/skills/Createskill/workflows/CreateSkill.md
File renamed without changes
dots/.claude/skills/Createskill/workflows/ValidateSkill.md → dots/.config/claude/skills/Createskill/workflows/ValidateSkill.md
File renamed without changes
dots/.claude/skills/Createskill/SKILL.md → dots/.config/claude/skills/Createskill/SKILL.md
File renamed without changes
dots/.claude/skills/git/SKILL.md → dots/.config/claude/skills/git/SKILL.md
@@ -372,8 +372,8 @@ The home repository uses pre-commit hooks for:
 # Format files
 make fmt
 
-# Re-add and commit
-git add .
+# Re-add specific formatted files and commit
+git add path/to/formatted/file.nix
 git commit --signoff -m "your message"
 ```
 
@@ -486,7 +486,9 @@ git config --global diff.algorithm histogram
 git config --global merge.conflictstyle diff3
 ```
 
-## Integration with /git-commit:commit Command
+## Preferred Method: Use /git-commit:commit Command
+
+**IMPORTANT**: When creating commits, ALWAYS prefer using the `/git-commit:commit` slash command instead of running `git commit` directly.
 
 The `/git-commit:commit` slash command provides a guided workflow:
 
@@ -495,6 +497,7 @@ The `/git-commit:commit` slash command provides a guided workflow:
 3. **Commit message creation** - Focus on WHY and impact
 4. **User approval** - Explicit confirmation before committing
 5. **Smart push offer** - Automatic push handling
+6. **Explicit file staging** - Never uses `git add -A` or `git add .`
 
 The command follows all the best practices in this skill and ensures:
 - Proper `--signoff` usage
@@ -502,6 +505,16 @@ The command follows all the best practices in this skill and ensures:
 - No emojis
 - Focus on WHY over WHAT
 - Atomic, well-structured commits
+- Explicit file staging (never adds all files blindly)
+
+**When to use it**:
+- Creating any new commit
+- Committing staged or unstaged changes
+- Need to review changes before committing
+
+**When you can use git directly**:
+- Amending the last commit (`git commit --amend`)
+- Specific git operations like rebase, cherry-pick, etc.
 
 ## Anti-Patterns to Avoid
 
@@ -533,6 +546,26 @@ git commit -m "feat: Add login function
 git push --force origin main  # NEVER!
 ```
 
+### ❌ Using git add -A or git add .
+```bash
+git add -A   # NEVER! Too broad, adds everything
+git add .    # NEVER! Too broad, adds everything
+```
+
+**Why to avoid**:
+- Adds ALL changes including unintended files
+- Can include generated files (build outputs, dependencies)
+- Can include sensitive files (.env, credentials)
+- Bypasses intentional staging control
+- Makes commits less atomic and focused
+
+**✅ Instead, explicitly add files or directories**:
+```bash
+git add src/auth/
+git add docs/authentication.md
+git add tests/auth.test.ts
+```
+
 ### ❌ Committing Secrets
 ```bash
 git add .env  # Check for secrets first!
@@ -546,12 +579,13 @@ git add config/credentials.json  # NO!
 1. ✅ **ALWAYS use `--signoff`**
 2. ✅ **Include `Co-Authored-By: Claude`** when working with AI
 3. ❌ **NEVER use emojis** in commit messages
-4. ✅ **Focus on WHY and IMPACT**, not WHAT
-5. ✅ **Keep commits atomic** - one logical change per commit
-6. ✅ **Use HEREDOC** for multi-line commit messages
-7. ✅ **Rebase, don't merge** when updating feature branches
-8. ✅ **Review before committing** - check diffs and verify no secrets
-9. ✅ **2-3 bullet points** maximum, each under 80 chars
-10. ✅ **Test before committing** - run pre-commit checks
+4. ❌ **NEVER use `git add -A` or `git add .`** - always add files explicitly
+5. ✅ **Focus on WHY and IMPACT**, not WHAT
+6. ✅ **Keep commits atomic** - one logical change per commit
+7. ✅ **Use HEREDOC** for multi-line commit messages
+8. ✅ **Rebase, don't merge** when updating feature branches
+9. ✅ **Review before committing** - check diffs and verify no secrets
+10. ✅ **2-3 bullet points** maximum, each under 80 chars
+11. ✅ **Test before committing** - run pre-commit checks
 
 **Remember**: Future you will thank present you for clear, descriptive commit messages that explain WHY changes were made!
dots/.claude/skills/golang/SKILL.md → dots/.config/claude/skills/golang/SKILL.md
File renamed without changes
dots/.claude/skills/homelab/SKILL.md → dots/.config/claude/skills/homelab/SKILL.md
File renamed without changes
dots/.claude/skills/nix/SKILL.md → dots/.config/claude/skills/nix/SKILL.md
File renamed without changes
dots/.claude/skills/notes/SKILL.md → dots/.config/claude/skills/notes/SKILL.md
File renamed without changes
dots/.claude/README.org → dots/.config/claude/README.org
@@ -11,7 +11,7 @@
 * Directory Structure
 
 #+begin_src
-dots/.claude/
+dots/.config/claude/
 ├── README.org           # This file
 ├── agents/              # Specialized AI agents
 ├── hooks/               # Event-driven automation hooks
@@ -28,12 +28,12 @@
 │   └── notes/          # Note-writing workflow (denote)
 └── settings.json        # Shared settings (tracked in git)
 
-~/.claude/
-├── agents/             -> /home/vincent/src/home/dots/.claude/agents/
-├── hooks/              -> /home/vincent/src/home/dots/.claude/hooks/
-├── plugins/            -> /home/vincent/src/home/dots/.claude/plugins/
-├── skills/             -> /home/vincent/src/home/dots/.claude/skills/
-├── settings.json       -> /home/vincent/src/home/dots/.claude/settings.json
+~/.config/claude/
+├── agents/             -> /home/vincent/src/home/dots/.config/claude/agents/
+├── hooks/              -> /home/vincent/src/home/dots/.config/claude/hooks/
+├── plugins/            -> /home/vincent/src/home/dots/.config/claude/plugins/
+├── skills/             -> /home/vincent/src/home/dots/.config/claude/skills/
+├── settings.json       -> /home/vincent/src/home/dots/.config/claude/settings.json
 ├── settings.local.json # Machine/project-specific (NOT tracked)
 └── history/            # Captured sessions and logs (synced via Syncthing)
     ├── sessions/       # Work session summaries
@@ -42,9 +42,13 @@
     ├── execution/      # Command outputs
     ├── decisions/      # Architecture decisions
     └── tool-outputs/   # Captured tool executions (via hooks)
+
+~/.claude/              -> ~/.config/claude/ (backward compatibility)
 #+end_src
 
-**Note**: History entries in =~/.claude/history/= are interconnected with denote notes in =~/desktop/org/notes/= using the =:history:= tag. History is synced across machines via Syncthing.
+**Note**: History entries in =~/.config/claude/history/= are interconnected with denote notes in =~/desktop/org/notes/= using the =:history:= tag. History is synced across machines via Syncthing.
+
+**Migration Note**: Claude Code now uses XDG Base Directory specification (=~/.config/claude/=). For backward compatibility, =~/.claude/= is symlinked to =~/.config/claude/= so older documentation and hooks continue to work.
 
 * Components
 
@@ -108,14 +112,15 @@
 make all
 
 # This will link:
-# - ~/.claude/skills/
-# - ~/.claude/agents/
-# - ~/.claude/hooks/
-# - ~/.claude/plugins/
-# - ~/.claude/settings.json
+# - ~/.config/claude/skills/
+# - ~/.config/claude/agents/
+# - ~/.config/claude/hooks/
+# - ~/.config/claude/plugins/
+# - ~/.config/claude/settings.json
+# - ~/.claude/ -> ~/.config/claude/ (backward compatibility)
 
 # Optionally create machine-specific settings
-cat > ~/.claude/settings.local.json <<EOF
+cat > ~/.config/claude/settings.local.json <<EOF
 {
   "permissions": {
     "allow": [
@@ -144,7 +149,7 @@
 
 ** settings.json (Shared)
 
-*Location*: =dots/.claude/settings.json= (symlinked to =~/.claude/settings.json=)
+*Location*: =dots/.config/claude/settings.json= (symlinked to =~/.config/claude/settings.json=)
 
 *Purpose*: Shared configuration across all machines
 
@@ -158,11 +163,11 @@
 - Consistent hooks across machines
 - Same plugins enabled everywhere
 - Synchronized preferences
-- Uses absolute paths that are consistent (=/home/vincent/.claude/...=)
+- Uses absolute paths that are consistent (=/home/vincent/.config/claude/...=)
 
 ** settings.local.json (Machine-Specific)
 
-*Location*: =~/.claude/settings.local.json= or project =.claude/settings.local.json=
+*Location*: =~/.config/claude/settings.local.json= or project =.claude/settings.local.json=
 
 *Purpose*: Machine or project-specific overrides
 
@@ -213,7 +218,7 @@
 
 #+begin_src bash
 # Edit a skill
-cd ~/src/home/dots/.claude/skills
+cd ~/src/home/dots/.config/claude/skills
 vim homelab/SKILL.md
 
 # Changes are immediately available (no rebuild required)
@@ -221,14 +226,14 @@
 
 ** Adding New Skills
 
-1. Create a new directory in =.claude/skills/=
+1. Create a new directory in =.config/claude/skills/=
 2. Add a =SKILL.md= file with the skill content
 3. Skills are automatically discovered by Claude Code
 
 Example:
 #+begin_src bash
-mkdir -p .claude/skills/rust
-cat > .claude/skills/rust/SKILL.md << 'EOF'
+mkdir -p .config/claude/skills/rust
+cat > .config/claude/skills/rust/SKILL.md << 'EOF'
 # Rust Development Skill
 
 ## Purpose
@@ -253,7 +258,7 @@
 ** Directory Structure
 
 #+begin_src
-~/.claude/history/
+~/.config/claude/history/
 ├── raw-outputs/              # Raw event logs (JSONL)
 │   └── YYYY-MM/
 │       └── YYYY-MM-DD_all-events.jsonl
@@ -350,13 +355,13 @@
 
 ** Scratchpad vs History
 
-*** Scratchpad (=~/.claude/scratchpad/=)
+*** Scratchpad (=~/.config/claude/scratchpad/=)
 - Temporary working files
 - Tests and experiments
 - Draft outputs
 - Delete when done
 
-*** History (=~/.claude/history/=)
+*** History (=~/.config/claude/history/=)
 - Permanent valuable outputs
 - Research findings
 - Learnings and insights
@@ -387,7 +392,7 @@
 - =:history:execution:= - Command execution logs
 
 *** Bidirectional Links
-History entries in =~/.claude/history/= and denote notes cross-reference each other:
+History entries in =~/.config/claude/history/= and denote notes cross-reference each other:
 
 From history to notes (markdown links in .md files):
 #+begin_src markdown
@@ -398,7 +403,7 @@
 From notes to history (org-mode links in .org files):
 #+begin_src org
 ,* Related History
-- [[file:~/.claude/history/sessions/2025-12/2025-12-03-150000_SESSION_implementation.md][Implementation Session]]
+- [[file:~/.config/claude/history/sessions/2025-12/2025-12-03-150000_SESSION_implementation.md][Implementation Session]]
 #+end_src
 
 **Note on formats**: History uses markdown (=.md=), notes use org-mode (=.org=). Both are plain text, searchable, and git-friendly. Use appropriate link syntax for each format.
@@ -416,13 +421,13 @@
 ls ~/desktop/org/notes/*==pkai*__history_session*.org
 
 # Search across both systems
-rg "topic" ~/.claude/history/ ~/desktop/org/notes/*__history*.org
+rg "topic" ~/.config/claude/history/ ~/desktop/org/notes/*__history*.org
 #+end_src
 
 *Signature*: =pkai= stands for "Personal Knowledge Automated Infrastructure" and identifies notes created by the history system. This makes it easy to distinguish automated notes from manual ones.
 
 *** When to Use Each System
-- *History directory* (=~/.claude/history/=): Chronological tracking, raw captures, session-by-session
+- *History directory* (=~/.config/claude/history/=): Chronological tracking, raw captures, session-by-session
 - *Denote notes* (=~/desktop/org/notes/=): Topic-based organization, long-term reference, knowledge building
 - *Both*: Significant learnings, important decisions, research worth sharing
 
@@ -466,7 +471,7 @@
 
 #+begin_src bash
 cd ~/src/home
-git add dots/.claude/
+git add dots/.config/claude/
 git commit -m "feat: Update Claude AI skills"
 #+end_src
 
@@ -498,15 +503,19 @@
 ** Settings not loading?
 #+begin_src bash
 # Check symlink
-ls -la ~/.claude/settings.json
+ls -la ~/.config/claude/settings.json
 
-# Should point to: /home/vincent/src/home/dots/.claude/settings.json
+# Should point to: /home/vincent/src/home/dots/.config/claude/settings.json
+
+# Check backward compatibility symlink
+ls -la ~/.claude
+# Should point to: ~/.config/claude
 #+end_src
 
 ** Hooks not running?
 #+begin_src bash
 # Check settings.json has hooks configured
-cat ~/.claude/settings.json | grep -A 10 hooks
+cat ~/.config/claude/settings.json | grep -A 10 hooks
 
 # Verify hook binaries are in PATH
 which claude-hooks-initialize-session
dots/.claude/settings.json → dots/.config/claude/settings.json
@@ -31,6 +31,12 @@
       }
     ]
   },
+  "skills": {
+    "enabled": true,
+    "directories": [
+      "~/.config/claude/skills"
+    ]
+  },
   "enabledPlugins": {
     "bug-hunter@chmouel-cc-plugins": true,
     "deslop@chmouel-cc-plugins": true,
dots/Makefile
@@ -20,19 +20,28 @@ all += niri
 niri : ~/.config/niri/config.kdl
 
 all += claude-skills
-claude-skills : ~/.claude/skills
+claude-skills : ~/.config/claude/skills
 
 all += claude-agents
-claude-agents : ~/.claude/agents
+claude-agents : ~/.config/claude/agents
 
 all += claude-hooks
-claude-hooks : ~/.claude/hooks
+claude-hooks : ~/.config/claude/hooks
 
 all += claude-settings
-claude-settings : ~/.claude/settings.json
+claude-settings : ~/.config/claude/settings.json
 
 all += claude-plugins
-claude-plugins : ~/.claude/plugins/session-manager
+claude-plugins : ~/.config/claude/plugins/session-manager
+
+all += claude-compat
+claude-compat : ~/.claude
+
+# Backward compatibility: symlink ~/.claude to ~/.config/claude
+~/.claude : force
+	@echo "🔗 Creating backward compatibility symlink: ~/.claude -> ~/.config/claude"
+	@mkdir -p ~/.config
+	@ln -snf ~/.config/claude ~/.claude
 
 # Example: Override default rule to generate content instead of copying
 # Uncomment and customize this pattern for files that should be generated: