Commit 388b37f1b2de
Changed files (13)
dots
config
claude
emacs
keyboards
tools
dots/config/claude/README.org → dots/config/claude/README.md
@@ -1,18 +1,16 @@
-#+title: Claude Code Infrastructure
-#+author: Vincent Demeester
-#+date: [2025-12-03 Wed]
+# Claude Code Infrastructure
-* Overview
+## Overview
This directory contains Claude Code infrastructure that is shared across machines and tracked in git. It includes agents, skills, hooks, plugins, and settings for the Personal AI Infrastructure (PAI).
-Inspired by [[https://github.com/danielmiessler/Personal_AI_Infrastructure][Daniel Miessler's Personal AI Infrastructure]].
+Inspired by [Daniel Miessler's Personal AI Infrastructure](https://github.com/danielmiessler/Personal_AI_Infrastructure).
-* Directory Structure
+## Directory Structure
-#+begin_src
+```
dots/.config/claude/
-├── README.org # This file
+├── README.md # This file
├── agents/ # Specialized AI agents
├── hooks/ # Event-driven automation hooks
├── plugins/ # Custom plugins (session-manager, etc.)
@@ -44,66 +42,66 @@
└── tool-outputs/ # Captured tool executions (via hooks)
~/.claude/ -> ~/.config/claude/ (backward compatibility)
-#+end_src
+```
-**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.
+**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.
+**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
+## Components
-** Agents (agents/)
+### Agents (agents/)
Specialized AI agents with specific expertise:
-- *engineer* - Software engineering and implementation
-- *architect* - Architecture and PRD creation
-- *designer* - UX/UI design and accessibility
-- *claude-researcher* - Web research with WebSearch
-- *researcher* - Comprehensive multi-tool research
+- **engineer** - Software engineering and implementation
+- **architect** - Architecture and PRD creation
+- **designer** - UX/UI design and accessibility
+- **claude-researcher** - Web research with WebSearch
+- **researcher** - Comprehensive multi-tool research
-See =agents/= for individual agent documentation.
+See `agents/` for individual agent documentation.
-** Skills (skills/)
+### Skills (skills/)
-*** CORE Skills
+#### CORE Skills
The CORE skills auto-load and define fundamental operating principles:
-- *CONSTITUTION.md*: Personal AI philosophy and architectural principles
-- *SKILL.md*: Core behaviors, response patterns, and workflows
-- *prompting.md*: Effective prompting guidelines
-- *history-system.md*: Integration between history capture and denote notes
+- **CONSTITUTION.md**: Personal AI philosophy and architectural principles
+- **SKILL.md**: Core behaviors, response patterns, and workflows
+- **prompting.md**: Effective prompting guidelines
+- **history-system.md**: Integration between history capture and denote notes
-*** Domain-Specific Skills
-- *homelab*: Managing NixOS infrastructure in ~/src/home repository
-- *golang*: Go development patterns, testing, and Nix integration
-- *nix*: NixOS/home-manager configuration best practices
-- *notes*: Note-taking in denote format with org-mode
-- *Art*: Visual content generation and Mermaid diagrams
-- *Createskill*: Skill creation and validation
+#### Domain-Specific Skills
+- **homelab**: Managing NixOS infrastructure in ~/src/home repository
+- **golang**: Go development patterns, testing, and Nix integration
+- **nix**: NixOS/home-manager configuration best practices
+- **notes**: Note-taking in denote format with org-mode
+- **Art**: Visual content generation and Mermaid diagrams
+- **Createskill**: Skill creation and validation
-See each skill's =SKILL.md= for documentation.
+See each skill's `SKILL.md` for documentation.
-** Hooks (hooks/)
+### Hooks (hooks/)
-Event-driven automation in TypeScript (=~/.config/claude/hooks/=):
-- =initialize-session.ts= - SessionStart: Sets terminal title, logs session start
-- =capture-tool-output.ts= - PostToolUse: Logs tool executions to JSONL
-- =save-session.ts= - SessionEnd: Prompts to save session summary
-- =validate-write-path.ts= - PreToolUse: Validates file paths and filenames
+Event-driven automation in TypeScript (`~/.config/claude/hooks/`):
+- `initialize-session.ts` - SessionStart: Sets terminal title, logs session start
+- `capture-tool-output.ts` - PostToolUse: Logs tool executions to JSONL
+- `save-session.ts` - SessionEnd: Prompts to save session summary
+- `validate-write-path.ts` - PreToolUse: Validates file paths and filenames
-See =dots/config/claude/hooks/= for source code.
+See `dots/config/claude/hooks/` for source code.
-** Plugins (plugins/)
+### Plugins (plugins/)
Custom Claude Code plugins:
-- *session-manager*: Provides =/save-session= command for creating session summaries
+- **session-manager**: Provides `/save-session` command for creating session summaries
-* Installation and Setup
+## Installation and Setup
-** Setup on New Machine
+### Setup on New Machine
To set up Claude Code infrastructure on a new machine:
-#+begin_src bash
+```bash
# Clone the home repository
cd ~/src/home
@@ -129,11 +127,11 @@
}
}
EOF
-#+end_src
+```
-** Makefile Targets
+### Makefile Targets
-#+begin_src bash
+```bash
# Link individual components
make claude-skills # Link skills
make claude-agents # Link agents
@@ -143,59 +141,60 @@
# Link everything
make all
-#+end_src
+```
-* Settings Strategy
+## Settings Strategy
-** settings.json (Shared)
+### settings.json (Shared)
-*Location*: =dots/.config/claude/settings.json= (symlinked to =~/.config/claude/settings.json=)
+**Location**: `dots/.config/claude/settings.json` (symlinked to `~/.config/claude/settings.json`)
-*Purpose*: Shared configuration across all machines
+**Purpose**: Shared configuration across all machines
-*Contains*:
+**Contains**:
- Hook configurations
- Enabled plugins list
- General preferences (alwaysThinkingEnabled, etc.)
- Shared MCP server configs
-*Why shared*:
+**Why shared**:
- Consistent hooks across machines
- Same plugins enabled everywhere
- Synchronized preferences
-- Uses absolute paths that are consistent (=/home/vincent/.config/claude/...=)
+- Uses absolute paths that are consistent (`/home/vincent/.config/claude/...`)
-** settings.local.json (Machine-Specific)
+### settings.local.json (Machine-Specific)
-*Location*: =~/.config/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
+**Purpose**: Machine or project-specific overrides
-*Contains*:
+**Contains**:
- Permissions (project-specific)
- Machine-specific paths
- Local environment variables
- Project-specific plugin configs
-*Not tracked in git*: Machine/project-specific configuration
+**Not tracked in git**: Machine/project-specific configuration
-** Settings Precedence
+### Settings Precedence
Claude Code merges settings in this order:
-1. =settings.json= (base configuration)
-2. =settings.local.json= (overrides)
+1. `settings.json` (base configuration)
+2. `settings.local.json` (overrides)
Local settings always take precedence over shared settings.
-** Permissions
+### Permissions
-Permissions are intentionally kept in =settings.local.json= because:
+Permissions are intentionally kept in `settings.local.json` because:
- Different projects need different permissions
- Security policies may vary by machine
- Easier to audit per-project permissions
Example project-specific permissions:
-#+begin_src json
+
+```json
{
"permissions": {
"allow": [
@@ -205,33 +204,34 @@
]
}
}
-#+end_src
+```
-* Usage
+## Usage
-** Skills
+### Skills
Skills are automatically available in Claude Code sessions. No special invocation needed - Claude will reference them contextually based on the task.
-** Editing Skills
+### Editing Skills
Skills are plain markdown files that can be edited directly:
-#+begin_src bash
+```bash
# Edit a skill
cd ~/src/home/dots/.config/claude/skills
vim homelab/SKILL.md
# Changes are immediately available (no rebuild required)
-#+end_src
+```
-** Adding New Skills
+### Adding New Skills
-1. Create a new directory in =.config/claude/skills/=
-2. Add a =SKILL.md= file with the skill content
+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
+
+```bash
mkdir -p .config/claude/skills/rust
cat > .config/claude/skills/rust/SKILL.md << 'EOF'
# Rust Development Skill
@@ -244,20 +244,20 @@
- Write comprehensive tests
- Follow Rust idioms
EOF
-#+end_src
+```
-* History System
+## History System
The History system automatically captures and documents AI interactions to build a comprehensive knowledge base.
-Adapted from the [[https://github.com/danielmiessler/Personal_AI_Infrastructure/blob/main/.claude/skills/CORE/CONSTITUTION.md#history-system][Personal AI Infrastructure History System]].
+Adapted from the [Personal AI Infrastructure History System](https://github.com/danielmiessler/Personal_AI_Infrastructure/blob/main/.claude/skills/CORE/CONSTITUTION.md#history-system).
-** Purpose
+### Purpose
Capture ALL valuable work for future reference, learning, and analysis.
-** Directory Structure
+### Directory Structure
-#+begin_src
+```
~/.config/claude/history/
├── raw-outputs/ # Raw event logs (JSONL)
│ └── YYYY-MM/
@@ -287,129 +287,132 @@
│ ├── README.md
│ └── [deprecated files]
└── YYYY-MM-DD_upgrade-description.md
-#+end_src
+```
-** What Gets Captured
+### What Gets Captured
-*** Automatic Capture (via hooks)
+#### Automatic Capture (via hooks)
- Session start and completion events
- Tool usage and command execution
-- All events logged to =raw-outputs/YYYY-MM/YYYY-MM-DD_all-events.jsonl=
+- All events logged to `raw-outputs/YYYY-MM/YYYY-MM-DD_all-events.jsonl`
-*** Manual Capture (by AI)
-- *Research completed* → save to =research/=
-- *Learning captured* → save to =learnings/=
-- *Work summary* → save to =sessions/=
-- *Command outputs* → save to =execution/=
+#### Manual Capture (by AI)
+- **Research completed** → save to `research/`
+- **Learning captured** → save to `learnings/`
+- **Work summary** → save to `sessions/`
+- **Command outputs** → save to `execution/`
-*** Workflow-Driven
+#### Workflow-Driven
- Some skills auto-save outputs
-- Example: research skill → =history/research/=
+- Example: research skill → `history/research/`
-** Categories
+### Categories
-*** Learnings
+#### Learnings
Problem-solving narratives and insights:
- How a bug was diagnosed and fixed
- Why a particular approach was chosen
- Lessons learned from failures
- Pattern discoveries
-Example: =2025-12/2025-12-03-154500_LEARNING_wireguard-vpn-setup.md=
+Example: `2025-12/2025-12-03-154500_LEARNING_wireguard-vpn-setup.md`
-*** Sessions
+#### Sessions
Work logs and summaries of significant work sessions:
- What was accomplished
- Decisions made
- Next steps
- Context for future reference
-Example: =2025-12/2025-12-03-100000_SESSION_homelab-infrastructure-upgrade.md=
+Example: `2025-12/2025-12-03-100000_SESSION_homelab-infrastructure-upgrade.md`
-*** Research
+#### Research
Analysis and investigations:
- Technical explorations
- Tool evaluations
- Architecture comparisons
- Deep dives into topics
-Example: =2025-12-03_personal-ai-infrastructure/=
+Example: `2025-12-03_personal-ai-infrastructure/`
-*** Execution
+#### Execution
Command outputs and results:
- Build logs
- Test results
- Deployment outputs
- Script executions
-Example: =2025-12/2025-12-03-150000_nixos-rebuild.txt=
+Example: `2025-12/2025-12-03-150000_nixos-rebuild.txt`
-*** Upgrades
+#### Upgrades
Architectural changes and migrations:
- System improvements
- Breaking changes
- Deprecated approaches
- Migration guides
-Example: =2025-12-03_claude-skills-implementation.md=
+Example: `2025-12-03_claude-skills-implementation.md`
-** Scratchpad vs History
+### Scratchpad vs History
-*** Scratchpad (=~/.config/claude/scratchpad/=)
+#### Scratchpad (`~/.config/claude/scratchpad/`)
- Temporary working files
- Tests and experiments
- Draft outputs
- Delete when done
-*** History (=~/.config/claude/history/=)
+#### History (`~/.config/claude/history/`)
- Permanent valuable outputs
- Research findings
- Learnings and insights
- Session logs
- Keep forever
-** Critical Rule
-*When in doubt, save to history!*
+### Critical Rule
+**When in doubt, save to history!**
-** Benefits
+### Benefits
-1. *Learn from history*: Reference past solutions to similar problems
-2. *Track evolution*: See how approaches and understanding develop over time
-3. *Share knowledge*: Documentation is automatically created
-4. *Context building*: AI can reference past interactions for better assistance
-5. *Institutional memory*: Build a knowledge base over time
+1. **Learn from history**: Reference past solutions to similar problems
+2. **Track evolution**: See how approaches and understanding develop over time
+3. **Share knowledge**: Documentation is automatically created
+4. **Context building**: AI can reference past interactions for better assistance
+5. **Institutional memory**: Build a knowledge base over time
-** Integration with Denote Notes
+### Integration with Denote Notes
-The History system is interconnected with the denote note-taking system in =~/desktop/org/notes/=.
+The History system is interconnected with the denote note-taking system in `~/desktop/org/notes/`.
-*** Tag-Based Integration
-All history-related notes use the =:history:= tag plus category-specific tags:
-- =:history:session:= - Work session summaries
-- =:history:learning:= - Problem-solving insights
-- =:history:research:= - Deep investigations
-- =:history:decision:= - Architecture decisions
-- =:history:execution:= - Command execution logs
+#### Tag-Based Integration
+All history-related notes use the `:history:` tag plus category-specific tags:
+- `:history:session:` - Work session summaries
+- `:history:learning:` - Problem-solving insights
+- `:history:research:` - Deep investigations
+- `:history:decision:` - Architecture decisions
+- `:history:execution:` - Command execution logs
-*** Bidirectional Links
-History entries in =~/.config/claude/history/= and denote notes cross-reference each other:
+#### Bidirectional Links
+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
+
+```markdown
## Related Notes
- [Topic Note](~/desktop/org/notes/20251203T151822--topic__history_session.org)
-#+end_src
+```
From notes to history (org-mode links in .org files):
-#+begin_src org
-,* Related History
+
+```org
+* Related History
- [[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.
+**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.
-*** Finding History-Linked Notes
-#+begin_src bash
+#### Finding History-Linked Notes
+
+```bash
# All history notes (by tag)
ls ~/desktop/org/notes/*__history*.org
@@ -422,22 +425,22 @@
# Search across both systems
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.
+**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* (=~/.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
+#### When to Use Each System
+- **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
-See =skills/CORE/history-system.md= for complete integration details.
+See `skills/CORE/history-system.md` for complete integration details.
-** Implementation Status
+### Implementation Status
Current implementation (manual workflow):
1. Manually create history entries for significant work
-2. Manually create denote notes with =:history:= tag
+2. Manually create denote notes with `:history:` tag
3. Cross-link between history and notes
4. Organize by category and date
@@ -447,61 +450,57 @@
- Searchable indexing across both systems
- AI-assisted note generation from history
-* Philosophy
+## Philosophy
-** Deterministic Over Probabilistic
+### Deterministic Over Probabilistic
Prefer structured, testable, code-based solutions over pure prompt engineering.
-** Progressive Disclosure
+### Progressive Disclosure
Load context in three tiers:
-1. *Essential*: Core principles always loaded
-2. *Contextual*: Task-specific knowledge loaded as needed
-3. *Reference*: Detailed docs retrieved on demand
+1. **Essential**: Core principles always loaded
+2. **Contextual**: Task-specific knowledge loaded as needed
+3. **Reference**: Detailed docs retrieved on demand
-** Code Before Prompts
+### Code Before Prompts
Build CLI tools and code first, then wrap with AI assistance. Code is:
- Testable
- Versioned
- Deterministic
- Shareable
-* Version Control
+## Version Control
Skills are tracked in the home repository:
-#+begin_src bash
+```bash
cd ~/src/home
git add dots/.config/claude/
git commit -m "feat: Update Claude AI skills"
-#+end_src
+```
-* References
+## Benefits of This Approach
-- [[https://github.com/danielmiessler/Personal_AI_Infrastructure][Personal AI Infrastructure]] - Original inspiration
-- [[file:~/src/home/CLAUDE.md][Repository CLAUDE.md]] - Repository-specific Claude instructions
-- [[file:~/desktop/org/notes/20251203T151822--personal-ai-infrastructure-implementation-plan__ai_claude_infrastructure_nixos_plan.org][PAI Implementation Plan]] - Planning notes
+1. **Consistency**: Same agents, skills, hooks, and plugins everywhere
+2. **Version Control**: Infrastructure tracked in git
+3. **Flexibility**: Machine-specific overrides when needed
+4. **Portability**: Easy to set up on new machines
+5. **Maintainability**: Single source of truth for shared config
+6. **Instant updates**: Edit skills, changes are immediate
+7. **No rebuilds**: No NixOS rebuild required (for skills/agents/plugins)
+8. **Iterative**: Easy to refine and experiment
-* Benefits of This Approach
+## Troubleshooting
-1. *Consistency*: Same agents, skills, hooks, and plugins everywhere
-2. *Version Control*: Infrastructure tracked in git
-3. *Flexibility*: Machine-specific overrides when needed
-4. *Portability*: Easy to set up on new machines
-5. *Maintainability*: Single source of truth for shared config
-6. *Instant updates*: Edit skills, changes are immediate
-7. *No rebuilds*: No NixOS rebuild required (for skills/agents/plugins)
-8. *Iterative*: Easy to refine and experiment
+### Symlinks not working?
-* Troubleshooting
-
-** Symlinks not working?
-#+begin_src bash
+```bash
cd ~/src/home/dots
make all
-#+end_src
+```
-** Settings not loading?
-#+begin_src bash
+### Settings not loading?
+
+```bash
# Check symlink
ls -la ~/.config/claude/settings.json
@@ -510,10 +509,11 @@
# Check backward compatibility symlink
ls -la ~/.claude
# Should point to: ~/.config/claude
-#+end_src
+```
-** Hooks not running?
-#+begin_src bash
+### Hooks not running?
+
+```bash
# Check settings.json has hooks configured
cat ~/.config/claude/settings.json | grep -A 10 hooks
@@ -521,22 +521,22 @@
ls ~/.config/claude/hooks/initialize-session.ts
ls ~/.config/claude/hooks/capture-tool-output.ts
ls ~/.config/claude/hooks/save-session.ts
-#+end_src
+```
-** History not syncing?
-#+begin_src bash
+### History not syncing?
+
+```bash
# Verify Syncthing is running
systemctl --user status syncthing
# Check if claude-history folder is configured
# After rebuilding NixOS with updated globals.nix
-#+end_src
+```
-* Related Documentation
+## Related Documentation
-- *Agents*: See individual agent =.md= files in =agents/=
-- *Skills*: See each skill's =SKILL.md= in =skills/=
-- *Hooks*: See =~/.config/claude/hooks/= (TypeScript, run via bun)
-- *History System*: See =skills/CORE/history-system.md=
-- *Repository Instructions*: See =~/src/home/CLAUDE.md=
-- *PAI Implementation Plan*: See =~/desktop/org/notes/20251203T151822--personal-ai-infrastructure-implementation-plan__ai_claude_infrastructure_nixos_plan.org=
+- **Agents**: See individual agent `.md` files in `agents/`
+- **Skills**: See each skill's `SKILL.md` in `skills/`
+- **Hooks**: See `~/.config/claude/hooks/` (TypeScript, run via bun)
+- **History System**: See `skills/CORE/history-system.md`
+- **Repository Instructions**: See `~/src/home/CLAUDE.md`
dots/config/emacs/README.md
@@ -0,0 +1,23 @@
+# Emacs Configuration
+
+## Inspirations
+
+- <https://tecosaur.github.io/emacs-config/config.html>
+- <https://github.com/jeremyf/dotemacs/>
+- <https://git.sr.ht/~pkal/emacs-init/tree>
+- <https://git.acdw.net/emacs/tree/>
+- <https://github.com/mfiano/emacs-config/tree/main>
+- <https://github.com/akirak/emacs-config/blob/master/emacs/emacs-config.org>
+- <https://robbmann.io/emacsd/>
+- <https://github.com/drshapeless/.emacs.d/>
+- <https://github.com/librephoenix/nixos-config/tree/main/user/app/doom-emacs>
+ - <https://github.com/psamim/dotfiles/blob/master/doom/config.el#L73>
+- <https://git.sr.ht/~sebasmonia/dotfiles/tree/master/item/.config/emacs/init.el>
+- <https://gitlab.com/andreyorst/dotfiles/>
+- <https://github.com/gopar/.emacs.d>
+- <https://github.com/precompute/CleanEmacs/>
+- <https://github.com/jakebox/jake-emacs>
+
+## Packages "inspirations"
+
+- <https://www.emacswiki.org/emacs/SetupEl>
dots/config/emacs/README.org
@@ -1,22 +0,0 @@
-
-* Inspirations
-
-- https://tecosaur.github.io/emacs-config/config.html
-- https://github.com/jeremyf/dotemacs/
-- https://git.sr.ht/~pkal/emacs-init/tree
-- https://git.acdw.net/emacs/tree/
-- https://github.com/mfiano/emacs-config/tree/main
-- https://github.com/akirak/emacs-config/blob/master/emacs/emacs-config.org
-- https://robbmann.io/emacsd/
-- https://github.com/drshapeless/.emacs.d/
-- https://github.com/librephoenix/nixos-config/tree/main/user/app/doom-emacs
- + https://github.com/psamim/dotfiles/blob/master/doom/config.el#L73
-- https://git.sr.ht/~sebasmonia/dotfiles/tree/master/item/.config/emacs/init.el
-- https://gitlab.com/andreyorst/dotfiles/
-- https://github.com/gopar/.emacs.d
-- https://github.com/precompute/CleanEmacs/
-- https://github.com/jakebox/jake-emacs
-
-* Packages "inspirations"
-
-- https://www.emacswiki.org/emacs/SetupEl
imperative/nagoya/README.org → imperative/nagoya/README.md
@@ -1,95 +1,92 @@
-#+TITLE: Nagoya Configuration
-#+FILETAGS: imperative debian server nagoya
+# Nagoya Configuration
-#+begin_quote
-⚠️ *DEPRECATED:* This imperative setup is now deprecated in favor of the declarative system-manager configuration at =~/src/home/systems/nagoya/system.nix=.
-
-The imperative scripts are kept as a backup fallback only.
-
-To use system-manager, see the deployment instructions in =CLAUDE.md=.
-#+end_quote
+> ⚠️ **DEPRECATED:** This imperative setup is now deprecated in favor of the declarative system-manager configuration at `~/src/home/systems/nagoya/system.nix`.
+>
+> The imperative scripts are kept as a backup fallback only.
+>
+> To use system-manager, see the deployment instructions in `CLAUDE.md`.
Configuration scripts for the Nagoya system, a Debian-based server.
-* Overview
+## Overview
This directory contains idempotent configuration scripts for the Nagoya host, which runs Debian and is not managed by NixOS.
-** System Information
+### System Information
-- *Hostname:* nagoya
-- *OS:* Debian
-- *Type:* Server
-- *Architecture:* aarch64
-- *VPN Address:* 10.100.0.80/24
+- **Hostname:** nagoya
+- **OS:** Debian
+- **Type:** Server
+- **Architecture:** aarch64
+- **VPN Address:** 10.100.0.80/24
-* Files
+## Files
-** =apply.sh=
+### `apply.sh`
The main configuration script that sets up the system. This script is designed to be run multiple times safely (idempotent).
-* Setup Components
+## Setup Components
-The =apply.sh= script configures the following:
+The `apply.sh` script configures the following:
-** Wireguard VPN
+### Wireguard VPN
- Configures wireguard VPN client
-- Creates =/etc/wireguard/wg0.conf= with VPN settings
+- Creates `/etc/wireguard/wg0.conf` with VPN settings
- Connects to VPN endpoint at 167.99.17.238:51820
- Assigns client IP: 10.100.0.80/24
-- Requires =WG_PRIVATE_KEY= environment variable
+- Requires `WG_PRIVATE_KEY` environment variable
-** Docker
+### Docker
- Removes old Docker packages (docker.io, podman-docker, etc.)
- Installs official Docker CE from docker.com repository
- Installs docker-ce, docker-ce-cli, containerd.io, and docker-buildx-plugin
- Configures Docker APT repository with proper GPG keys
-** Kind (Kubernetes in Docker)
+### Kind (Kubernetes in Docker)
- Installs Kind v0.30.0 for ARM64
-- Installs to =/usr/local/bin/kind=
+- Installs to `/usr/local/bin/kind`
- Used for local Kubernetes development
-** Syncthing
+### Syncthing
- Installs Syncthing from official APT repository
- Configures GPG keys for package verification
- Note: User service setup needs to be completed (see TODOs)
-* Usage
+## Usage
-** Running the Script
+### Running the Script
From the repository root:
-#+begin_src bash
+```bash
# Basic run (without wireguard configuration)
sudo ./imperative/nagoya/apply.sh
# With wireguard private key
sudo WG_PRIVATE_KEY="your-private-key-here" ./imperative/nagoya/apply.sh
-#+end_src
+```
-** First-Time Setup
+### First-Time Setup
1. Ensure you have root/sudo access
2. Have your wireguard private key ready
3. Run the script with the WG_PRIVATE_KEY environment variable
-** Updating Configuration
+### Updating Configuration
Simply re-run the script. It's designed to be idempotent, meaning running it multiple times will bring the system to the desired state without causing issues.
-* TODOs
+## TODOs
- [ ] Complete Syncthing user service setup
- [ ] Add config.txt configuration (diff with default, nvme settings)
- [ ] Add error handling for missing Kind download
- [ ] Consider adding Docker post-install steps (user groups, etc.)
-* Notes
+## Notes
-- The script uses =set -euo pipefail= for strict error handling
-- All setup functions are prefixed with =setup.=
+- The script uses `set -euo pipefail` for strict error handling
+- All setup functions are prefixed with `setup.`
- Logging functions provide colored output for better readability
- Shellcheck directives are used where system files are sourced
imperative/wakasu/README.org → imperative/wakasu/README.md
@@ -1,77 +1,76 @@
-#+TITLE: Wakasu Configuration
-#+FILETAGS: imperative fedora desktop wakasu
+# Wakasu Configuration
Configuration scripts for the Wakasu system, a Fedora-based desktop.
-* Overview
+## Overview
This directory contains idempotent configuration scripts for the Wakasu host, which runs Fedora and is not managed by NixOS.
-** System Information
+### System Information
-- *Hostname:* wakasu
-- *OS:* Fedora
-- *Type:* Desktop
-- *User:* vincent
-- *VPN Address:* 10.100.0.90/24
+- **Hostname:** wakasu
+- **OS:** Fedora
+- **Type:** Desktop
+- **User:** vincent
+- **VPN Address:** 10.100.0.90/24
-* Files
+## Files
-** =apply.sh=
+### `apply.sh`
The main configuration script that sets up the system. This script is designed to be run multiple times safely (idempotent).
-* Setup Components
+## Setup Components
-The =apply.sh= script configures the following:
+The `apply.sh` script configures the following:
-** Default Packages
-- *helix* - Modern terminal-based text editor
-- *acpi* - Command-line utilities for ACPI (power management)
+### Default Packages
+- **helix** - Modern terminal-based text editor
+- **acpi** - Command-line utilities for ACPI (power management)
-** Syncthing
+### Syncthing
- Installs Syncthing from Fedora repositories
-- Enables and starts systemd user service for user =vincent=
+- Enables and starts systemd user service for user `vincent`
- Enables loginctl lingering so service starts at boot
- Syncthing will be available at http://localhost:8384
-** Wireguard VPN
+### Wireguard VPN
- Installs wireguard-tools package
-- Creates =/etc/wireguard/wg0.conf= with VPN settings
+- Creates `/etc/wireguard/wg0.conf` with VPN settings
- Connects to VPN endpoint at 167.99.17.238:51820
- Assigns client IP: 10.100.0.90/24
-- Requires =WG_PRIVATE_KEY= environment variable
+- Requires `WG_PRIVATE_KEY` environment variable
- Gracefully skips configuration if private key is not provided
-* Usage
+## Usage
-** Running the Script
+### Running the Script
From the repository root:
-#+begin_src bash
+```bash
# Basic run (wireguard config will be skipped)
sudo ./imperative/wakasu/apply.sh
# With wireguard private key
sudo WG_PRIVATE_KEY="your-private-key-here" ./imperative/wakasu/apply.sh
-#+end_src
+```
-** First-Time Setup
+### First-Time Setup
1. Ensure you have root/sudo access
2. Have your wireguard private key ready (optional)
3. Run the script
-** Updating Configuration
+### Updating Configuration
Simply re-run the script. It's designed to be idempotent, meaning running it multiple times will bring the system to the desired state without causing issues.
-** Enabling Wireguard
+### Enabling Wireguard
-After running the script with =WG_PRIVATE_KEY=:
+After running the script with `WG_PRIVATE_KEY`:
-#+begin_src bash
+```bash
# Start wireguard
sudo systemctl start wg-quick@wg0
@@ -80,11 +79,11 @@
# Check status
sudo systemctl status wg-quick@wg0
-#+end_src
+```
-** Managing Syncthing
+### Managing Syncthing
-#+begin_src bash
+```bash
# Check syncthing status
systemctl --user status syncthing
@@ -93,19 +92,19 @@
# View syncthing logs
journalctl --user -u syncthing
-#+end_src
+```
-* Default Packages Explained
+## Default Packages Explained
-** Helix
+### Helix
A modern, Kakoune/Neovim inspired editor with built-in LSP support and tree-sitter syntax highlighting. Provides a powerful terminal-based editing experience.
-** ACPI
+### ACPI
Utilities for monitoring battery, temperature, and power management on laptops. Useful for checking battery status and system power state.
-* Notes
+## Notes
-- The script uses =set -euo pipefail= for strict error handling
-- All setup functions are prefixed with =setup.=
+- The script uses `set -euo pipefail` for strict error handling
+- All setup functions are prefixed with `setup.`
- Logging functions provide colored output for better readability
-- User-specific configuration is stored in the =USER_NAME= variable
+- User-specific configuration is stored in the `USER_NAME` variable
imperative/README.org → imperative/README.md
@@ -1,13 +1,12 @@
-#+TITLE: Imperative Configuration
-#+FILETAGS: imperative configuration scripts
+# Imperative Configuration
Idempotent configuration scripts for systems not managed by NixOS.
-* Overview
+## Overview
-This directory contains configuration scripts for hosts that cannot or do not use NixOS. Unlike the declarative NixOS configurations in =/systems=, these scripts use an imperative approach but are designed to be idempotent - safe to run multiple times.
+This directory contains configuration scripts for hosts that cannot or do not use NixOS. Unlike the declarative NixOS configurations in `/systems`, these scripts use an imperative approach but are designed to be idempotent - safe to run multiple times.
-** Philosophy
+### Philosophy
While NixOS provides declarative configuration management, some systems need to use traditional Linux distributions for various reasons:
- Hardware compatibility requirements
@@ -17,205 +16,206 @@
These scripts bridge the gap by providing repeatable, documented configuration management for non-NixOS systems.
-** Key Principles
+### Key Principles
-1. *Idempotent* - Scripts can be run multiple times safely
-2. *Self-contained* - Each host directory is independent
-3. *Documented* - Each host has a README explaining its setup
-4. *Versioned* - Configuration is tracked in git like NixOS configs
+1. **Idempotent** - Scripts can be run multiple times safely
+2. **Self-contained** - Each host directory is independent
+3. **Documented** - Each host has a README explaining its setup
+4. **Versioned** - Configuration is tracked in git like NixOS configs
-* Directory Structure
+## Directory Structure
Each host has its own directory containing:
-#+begin_example
+```
imperative/
-├── README.org # This file
+├── README.md # This file
├── nagoya/ # Debian server
-│ ├── README.org # Host-specific documentation
+│ ├── README.md # Host-specific documentation
│ └── apply.sh # Main configuration script
└── wakasu/ # Fedora desktop
- ├── README.org # Host-specific documentation
+ ├── README.md # Host-specific documentation
└── apply.sh # Main configuration script
-#+end_example
+```
-* Current Hosts
+## Current Hosts
-** nagoya - Debian Server
-- *OS:* Debian (aarch64)
-- *Type:* Server
-- *Components:* Docker, Kind, Wireguard, Syncthing
-- *VPN IP:* 10.100.0.80/24
+### nagoya - Debian Server
+- **OS:** Debian (aarch64)
+- **Type:** Server
+- **Components:** Docker, Kind, Wireguard, Syncthing
+- **VPN IP:** 10.100.0.80/24
-See [[file:nagoya/README.org][nagoya/README.org]] for details.
+See [nagoya/README.md](nagoya/README.md) for details.
-** wakasu - Fedora Desktop
-- *OS:* Fedora
-- *Type:* Desktop
-- *User:* vincent
-- *Components:* Helix, ACPI, Wireguard, Syncthing
-- *VPN IP:* 10.100.0.90/24
+### wakasu - Fedora Desktop
+- **OS:** Fedora
+- **Type:** Desktop
+- **User:** vincent
+- **Components:** Helix, ACPI, Wireguard, Syncthing
+- **VPN IP:** 10.100.0.90/24
-See [[file:wakasu/README.org][wakasu/README.org]] for details.
+See [wakasu/README.md](wakasu/README.md) for details.
-* Usage
+## Usage
-** Running Configuration Scripts
+### Running Configuration Scripts
From the repository root:
-#+begin_src bash
+```bash
# Apply configuration for a specific host
sudo ./imperative/<hostname>/apply.sh
# With environment variables (e.g., for wireguard)
sudo WG_PRIVATE_KEY="..." ./imperative/<hostname>/apply.sh
-#+end_src
+```
-** Adding a New Host
+### Adding a New Host
1. Create a new directory for the host:
- #+begin_src bash
+ ```bash
mkdir imperative/<hostname>
- #+end_src
+ ```
-2. Create an =apply.sh= script following the existing patterns:
- - Use =set -euo pipefail= for safety
+2. Create an `apply.sh` script following the existing patterns:
+ - Use `set -euo pipefail` for safety
- Implement colored logging functions
- Make functions idempotent
- - Use =setup.*= naming convention for functions
+ - Use `setup.*` naming convention for functions
-3. Create a =README.org= documenting:
+3. Create a `README.md` documenting:
- System information
- Components installed
- Usage instructions
- Environment variables needed
4. Make the script executable:
- #+begin_src bash
+ ```bash
chmod +x imperative/<hostname>/apply.sh
- #+end_src
+ ```
5. Update this README to include the new host
-** Testing Scripts
+### Testing Scripts
Test scripts in a VM or container before running on production systems:
-#+begin_src bash
+```bash
# Example with Docker
docker run -it --rm -v $(pwd):/repo debian:latest
cd /repo
./imperative/<hostname>/apply.sh
-#+end_src
+```
-* Script Conventions
+## Script Conventions
-** Error Handling
+### Error Handling
All scripts use strict error handling:
-#+begin_src bash
+
+```bash
set -euo pipefail
-#+end_src
+```
This ensures:
-- =set -e= - Exit on any error
-- =set -u= - Exit on undefined variable
-- =set -o pipefail= - Catch errors in pipes
+- `set -e` - Exit on any error
+- `set -u` - Exit on undefined variable
+- `set -o pipefail` - Catch errors in pipes
-** Logging
+### Logging
Use colored logging functions for clarity:
-#+begin_src bash
+```bash
log_info "Normal operation message"
log_warn "Warning message"
log_error "Error message"
-#+end_src
+```
-** Function Naming
+### Function Naming
-Use =setup.*= prefix for setup functions:
+Use `setup.*` prefix for setup functions:
-#+begin_src bash
+```bash
setup.docker() { ... }
setup.wireguard() { ... }
setup.syncthing() { ... }
-#+end_src
+```
-** Environment Variables
+### Environment Variables
- Document all required environment variables in the host's README
- Provide sensible defaults where possible
- Fail gracefully or warn when optional variables are missing
-** Idempotency
+### Idempotency
Make operations idempotent by:
- Checking if software is already installed
-- Using =||= for commands that might fail on re-run
+- Using `||` for commands that might fail on re-run
- Avoiding destructive operations
- Using configuration management tools when available
-* Integration with NixOS Configs
+## Integration with NixOS Configs
While these scripts are imperative, they share concepts with the NixOS configurations:
-- *Wireguard configuration* matches the network topology in =globals.nix=
-- *Syncthing* IDs should be coordinated with NixOS hosts
-- *VPN IP addressing* follows the same scheme (10.100.0.0/24)
+- **Wireguard configuration** matches the network topology in `globals.nix`
+- **Syncthing** IDs should be coordinated with NixOS hosts
+- **VPN IP addressing** follows the same scheme (10.100.0.0/24)
-* Transitioning to NixOS
+## Transitioning to NixOS
When ready to migrate a host to NixOS:
1. Document the current system state using the imperative script as reference
-2. Create a new NixOS configuration in =/systems/<hostname>=
+2. Create a new NixOS configuration in `/systems/<hostname>`
3. Test the NixOS configuration in a VM
4. Perform the migration
5. Archive or remove the imperative configuration
-* Maintenance
+## Maintenance
-** Updating Scripts
+### Updating Scripts
When updating scripts:
1. Test changes in a VM or non-production system
2. Update the host's README if behavior changes
3. Run shellcheck to catch common issues:
- #+begin_src bash
+ ```bash
shellcheck imperative/<hostname>/apply.sh
- #+end_src
+ ```
-** Version Control
+### Version Control
All changes to imperative configurations should be:
- Committed to git
- Documented in commit messages
- Tagged if significant milestones are reached
-* Comparison: Imperative vs NixOS
+## Comparison: Imperative vs NixOS
-| Aspect | Imperative (this directory) | NixOS (=/systems=) |
-|------------------+-----------------------------+---------------------------|
-| *Approach* | Scripts to reach state | Declare desired state |
-| *Idempotency* | Manual (via careful coding) | Automatic |
-| *Rollback* | Manual/difficult | Built-in generations |
-| *Reproducibility* | Best effort | Guaranteed |
-| *Documentation* | README + comments | Code is documentation |
-| *OS Support* | Any Linux distro | NixOS only |
-| *Learning Curve* | Familiar bash scripts | Steeper (Nix language) |
-| *State Management* | Imperative commands | Declarative configuration |
+| Aspect | Imperative (this directory) | NixOS (`/systems`) |
+|------------------|-----------------------------|-----------------------------|
+| **Approach** | Scripts to reach state | Declare desired state |
+| **Idempotency** | Manual (via careful coding) | Automatic |
+| **Rollback** | Manual/difficult | Built-in generations |
+| **Reproducibility** | Best effort | Guaranteed |
+| **Documentation** | README + comments | Code is documentation |
+| **OS Support** | Any Linux distro | NixOS only |
+| **Learning Curve** | Familiar bash scripts | Steeper (Nix language) |
+| **State Management** | Imperative commands | Declarative configuration |
-* Resources
+## Resources
-** Similar Approaches
+### Similar Approaches
- Ansible playbooks (declarative automation)
- Chef/Puppet recipes (configuration management)
- Shell scripts (traditional approach)
-** Why Not Use These Tools?
+### Why Not Use These Tools?
For simple single-host configurations, a well-written bash script:
- Has no dependencies beyond bash and standard tools
keyboards/eyelash_corne/README.org → keyboards/eyelash_corne/README.md
@@ -1,8 +1,8 @@
-#+title: Eyelash Corne ZMK Config
+# Eyelash Corne ZMK Config
Custom ZMK firmware for the Eyelash Corne keyboard (42-key split, nice!nano v2, wireless Bluetooth).
-* Features
+## Features
- Layouts: Bépo (primary), ErgoL, QWERTY
- Home row mods, smart numword layer, combos, mod-morph, leader keys
@@ -10,59 +10,59 @@
- nice!view display (gem animation), RGB underglow (auto-off on idle)
- Power: 12min sleep timeout, +8dBm BT transmission
-* Build & Flash
+## Build & Flash
-#+begin_src bash
+```bash
./go.sh build # Build both sides (output: firmwares/)
./go.sh flash # Build and flash left/right (bootloader mode prompts)
-#+end_src
+```
-Supports auto-mount (=/run/media/$USER/NICENANO=) and manual mount (=/mnt=).
+Supports auto-mount (`/run/media/$USER/NICENANO`) and manual mount (`/mnt`).
-* Keymap Visualization
+## Keymap Visualization
-[[file:../eyelash_corne.svg]]
+
-* Layers
+## Layers
| Layer | Name | Description |
-|-------+------------+----------------------------------------------------------|
+|-------|------------|----------------------------------------------------------|
| L0 | Bépo | Primary French layout, home row mods, Unicode accents |
| L1 | ErgoL | Alternative French layout |
| L2 | QWERTY | Standard layout |
-| L3 | Accents | French vowels (´ ` ^ ¨), Æ Œ Ñ Ç |
+| L3 | Accents | French vowels (´ ` ^ ¨), Æ Œ Ñ Ç |
| L4 | Symbols | Programming symbols, brackets, operators |
| L5 | Numbers | Calculator-style numpad |
| L6 | Navigation | Arrows, page nav, shortcuts |
| L7 | Function | F1-F12, media, system controls |
-*Home row mods (Bépo)*: Left: A(GUI) U(Alt) I(Shift) E(Ctrl) | Right: C(Hyper) T(Ctrl) S(Shift) R(Alt) N(GUI)
+**Home row mods (Bépo)**: Left: A(GUI) U(Alt) I(Shift) E(Ctrl) | Right: C(Hyper) T(Ctrl) S(Shift) R(Alt) N(GUI)
-* Configuration
+## Configuration
-- *Power*: 12min sleep timeout, RGB auto-off, soft off support
-- *Bluetooth*: +8dBm transmission, multiple devices
-- *Display*: nice!view gem animation (4.8s interval), shows layer/battery/BT
-- *Mouse*: Movement 1200, scroll 20, idle 125ms
+- **Power**: 12min sleep timeout, RGB auto-off, soft off support
+- **Bluetooth**: +8dBm transmission, multiple devices
+- **Display**: nice!view gem animation (4.8s interval), shows layer/battery/BT
+- **Mouse**: Movement 1200, scroll 20, idle 125ms
-Build config (=build.yaml=): Left/right halves with nice!view, settings reset
+Build config (`build.yaml`): Left/right halves with nice!view, settings reset
-* Leader Key Sequences
+## Leader Key Sequences
-Leader key is activated with the *RH0+RH2 combo* (right thumb cluster: Shift + Alt on QWERTY). After activation, press a sequence of keys (timeout: 300ms per key) to insert text snippets or launch applications.
+Leader key is activated with the **RH0+RH2 combo** (right thumb cluster: Shift + Alt on QWERTY). After activation, press a sequence of keys (timeout: 300ms per key) to insert text snippets or launch applications.
-** Layout Switching
+### Layout Switching
| Sequence | Output | Description |
-|----------+---------------+----------------------------|
+|----------|---------------|----------------------------|
| l b | Switch to BÉP | Switch to Bépo layout |
| l e | Switch to ERG | Switch to ErgoL layout |
| l q | Switch to QWE | Switch to QWERTY layout |
-** Development Patterns - General
+### Development Patterns - General
| Sequence | Output | Description |
-|----------+---------------------+-----------------------------|
+|----------|---------------------|-----------------------------|
| c n | nil | Go nil value |
| c e | if err != nil {↵⇥ | Go error check |
| c l | console.log() | JavaScript console.log |
@@ -70,10 +70,10 @@
| c f | function() {} | JavaScript function |
| c a | () => {} | JavaScript arrow function |
-** Development Patterns - Python
+### Development Patterns - Python
| Sequence | Output | Description |
-|----------+----------------------------------------------+--------------------------|
+|----------|----------------------------------------------|--------------------------|
| p i | if __name__ == "__main__":↵⇥ | Python main block |
| p d | def ():↵⇥ | Python function def |
| p c | class :↵⇥ | Python class def |
@@ -81,10 +81,10 @@
| p t | try:↵⇥↵except Exception as e:↵⇥ | Python try/except |
| p w | with open("", "r") as f:↵⇥ | Python with open |
-** Development Patterns - Emacs Lisp
+### Development Patterns - Emacs Lisp
| Sequence | Output | Description |
-|----------+---------------------+------------------------------|
+|----------|---------------------|------------------------------|
| e d | (defun ()↵ | Emacs Lisp defun |
| e i | (interactive) | Emacs Lisp interactive |
| e l | (let (( | Emacs Lisp let binding |
@@ -92,10 +92,10 @@
| e m | (message "") | Emacs Lisp message |
| e r | (require ') | Emacs Lisp require |
-** Development Patterns - Nix
+### Development Patterns - Nix
| Sequence | Output | Description |
-|----------+----------------------------------+--------------------------------|
+|----------|----------------------------------|--------------------------------|
| n f | { pkgs, ... }: | Nix function signature |
| n l | let↵⇥↵in↵ | Nix let/in expression |
| n w | with pkgs; [↵⇥↵] | Nix with statement |
@@ -103,29 +103,29 @@
| n b | buildInputs = [ ]; | Nix buildInputs attribute |
| n p | pkgs.writeShellScriptBin "" ''↵⇥↵'' | Nix shell script wrapper |
-** Import Patterns
+### Import Patterns
| Sequence | Output | Description |
-|----------+---------------------------------+--------------------------------|
+|----------|---------------------------------|--------------------------------|
| i p | import | Python import |
| i f | from import | Python from import |
| i n | { pkgs }: {↵⇥↵} | Nix module import |
| i e | (use-package ↵⇥ | Emacs use-package |
-** Personal Macros
+### Personal Macros
| Sequence | Output | Description |
-|----------+------------------------------------------------+-----------------------------|
+|----------|-------------------------------------------------|-----------------------------|
| m e | vincent@sbr.pm | Email address |
| m g | Vincent Demeester <vincent@sbr.pm> | Git signature |
| m s | --↵Vincent Demeester↵vincent@sbr.pm | Email signature |
-** Application Shortcuts
+### Application Shortcuts
These leader sequences trigger niri window manager keybindings:
| Sequence | Keybinding | Application |
-|----------+---------------------+----------------------|
+|----------|---------------------|-----------------------|
| a d | Mod+D | Fuzzel (app launcher)|
| a e | Mod+Shift+Enter | Emacs (client) |
| a t | Mod+Enter | Kitty (terminal) |
@@ -133,23 +133,23 @@
| a v | Mod+Control+V | Cliphist (clipboard) |
| a r | Mod+Shift+D | Raffi (launcher) |
-* Inspirations and References
+## Inspirations and References
-- https://github.com/urob/zmk-config
-- https://github.com/manna-harbour/miryoku_zmk
-- https://github.com/mctechnology17/zmk-config
-- https://github.com/urob/zmk-helpers
-- https://github.com/rayduck/pnohty
-- https://sunaku.github.io/home-row-mods.html
-- https://sunaku.github.io/ergohaven-remnant-keyboard.html
-- https://github.com/JeffDess/zmk-config
-- https://github.com/Townk/zmk-config
-- https://github.com/GPeye/hammerbeam-slideshow
-- https://github.com/zzeneg/zmk-nice-view-hid
-- https://github.com/GPeye/urchin-peripheral-animation
-- https://github.com/GPeye/nice-view-mod
-- https://github.com/n3oney/zmk-config
-- https://github.com/moutis/zmk-config
-- https://github.com/englmaxi/zmk-config
-- https://github.com/SethMilliken/zmk-config
-- https://github.com/minusfive/knucklehead
+- <https://github.com/urob/zmk-config>
+- <https://github.com/manna-harbour/miryoku_zmk>
+- <https://github.com/mctechnology17/zmk-config>
+- <https://github.com/urob/zmk-helpers>
+- <https://github.com/rayduck/pnohty>
+- <https://sunaku.github.io/home-row-mods.html>
+- <https://sunaku.github.io/ergohaven-remnant-keyboard.html>
+- <https://github.com/JeffDess/zmk-config>
+- <https://github.com/Townk/zmk-config>
+- <https://github.com/GPeye/hammerbeam-slideshow>
+- <https://github.com/zzeneg/zmk-nice-view-hid>
+- <https://github.com/GPeye/urchin-peripheral-animation>
+- <https://github.com/GPeye/nice-view-mod>
+- <https://github.com/n3oney/zmk-config>
+- <https://github.com/moutis/zmk-config>
+- <https://github.com/englmaxi/zmk-config>
+- <https://github.com/SethMilliken/zmk-config>
+- <https://github.com/minusfive/knucklehead>
keyboards/moonlander/README.md
@@ -0,0 +1,163 @@
+# ZSA Moonlander QMK Config
+
+Custom QMK firmware for the ZSA Moonlander split keyboard (72 keys, STM32 MCU, RGB backlighting).
+
+## Features
+
+- Layouts: Bépo (primary), ErgoL, QWERTY
+- Home row mods (280ms tapping term), smart numword layer
+- Combos, key overrides, leader key, tap dance
+- French accents (US International layout), repeat key
+
+## Build & Flash
+
+```bash
+./go.sh build # Build firmware (output: build/qmk_firmware/.build/)
+./go.sh flash # Build and flash (press reset button when prompted)
+./go.sh update # Update QMK submodules
+./go.sh clean # Clean build artifacts
+```
+
+## Keymap Visualization
+
+
+
+**Note**: Combo definitions are automatically parsed from `keymap.c` during visualization generation via `parse-combos.sh`.
+
+## Layers
+
+| Layer | Name | Description |
+|-------|------------|------------------------------------------------------------------|
+| L0 | Bépo | Primary French layout, home row mods, numword activation |
+| L1 | ErgoL | Alternative French layout |
+| L2 | QWERTY | Standard layout with home row mods |
+| L3 | Symbols | Programming symbols, brackets, operators |
+| L4 | Numbers | Numpad layout (auto-disable after 5s) |
+| L5 | Navigation | Arrows, page nav, media controls |
+| L6 | Mouse | Mouse emulation |
+| L7 | Modifiers | Additional modifiers and function keys |
+
+**Home row mods (Bépo)**: Left: A(GUI) U(Alt) I(Shift) E(Ctrl) ,(Hyper) | Right: C(Hyper) T(Ctrl) S(Shift) R(Alt) N(GUI)
+
+## Configuration
+
+### Timing
+- Tapping: 280ms | Quick tap: 100ms | Flow: 150ms | Combo: 40ms | Numword timeout: 5s
+
+### Combos & Overrides
+- Layer switching, Escape, special chars (|@#$/\&-_=), brackets
+- Bépo overrides: Shift+^=!, Shift+.=:, Shift+,=;, Shift+numbers, RAlt+B=|, RAlt+Space=_
+
+### French Accents (US International)
+é è ê à â ù û î ô ë ï ç € (uppercase variants supported)
+
+### QMK Features
+**Enabled**: Combos, key overrides, leader key, repeat key, tap dance, layer lock
+**Disabled**: Audio, caps word, auto shift, console, most RGB effects (size optimization)
+
+## Usage
+
+- **Layout switching**: Bépo (Nav+Shift), ErgoL (Q+P), QWERTY (Numb+Symb), or via leader sequences
+- **Numword**: Hold Space on Bépo layer (auto-disable after 5s)
+- **Leader key**: Combo Del+RAlt (right thumb cluster, 300ms timeout per key)
+- **Mouse toggle**: Combo Q+R
+
+### Leader Key Sequences
+
+The leader key is activated by pressing Del+RAlt simultaneously (right thumb cluster). After activation, you have 300ms to press each subsequent key in the sequence.
+
+#### Layout Switching (Leader + L + key)
+
+| Sequence | Action |
+|----------|-----------------|
+| l b | Switch to Bépo |
+| l e | Switch to ErgoL |
+| l q | Switch to QWERTY|
+
+#### Development Patterns - General (Leader + C + key)
+
+| Sequence | Output | Notes |
+|----------|----------------------------|--------------------------------|
+| c n | nil | Go/common nil keyword |
+| c e | if err != nil {<enter><tab>| Go error handling pattern |
+| c l | console.log() | Cursor positioned inside () |
+| c p | fmt.Println() | Cursor positioned inside () |
+| c f | function() {} | Cursor positioned inside {} |
+| c a | () => {} | Arrow function, cursor inside {}|
+
+#### Development Patterns - Python (Leader + P + key)
+
+| Sequence | Output | Notes |
+|----------|----------------------------|--------------------------------|
+| p i | if __name__ == "__main__": | Python main block |
+| p d | def (): | Function definition, cursor at name |
+| p c | class : | Class definition, cursor at name |
+| p p | print(f"") | f-string print, cursor inside quotes |
+| p t | try:...except Exception as e: | Try-except block |
+| p w | with open("", "r") as f: | File context manager, cursor at path |
+
+#### Development Patterns - Emacs Lisp (Leader + E + key)
+
+| Sequence | Output | Notes |
+|----------|----------------------------|--------------------------------|
+| e d | (defun () | Function definition, cursor at name |
+| e i | (interactive) | Interactive declaration |
+| e l | (let (( | Let binding |
+| e s | (setq ) | Set variable, cursor at name |
+| e m | (message "") | Message output, cursor inside quotes |
+| e r | (require ') | Require package, cursor after quote |
+
+#### Development Patterns - Nix (Leader + N + key)
+
+| Sequence | Output | Notes |
+|----------|----------------------------|--------------------------------|
+| n f | { pkgs, ... }: | Nix function signature |
+| n l | let...in | Let expression, cursor in body |
+| n w | with pkgs; [...] | With statement, cursor in list |
+| n i | inherit ; | Inherit, cursor before semicolon |
+| n b | buildInputs = [ ]; | buildInputs, cursor in list |
+| n p | pkgs.writeShellScriptBin ""| Shell script, cursor at name |
+
+#### Import Patterns (Leader + I + key)
+
+| Sequence | Output | Notes |
+|----------|----------------------------|--------------------------------|
+| i p | import | Python simple import |
+| i f | from import | Python from import, cursor at module |
+| i n | { pkgs }: {...} | Nix module definition |
+| i e | (use-package | Emacs use-package declaration |
+
+#### Personal Macros (Leader + M + key)
+
+| Sequence | Output | Notes |
+|----------|-------------------------------------|------------------------|
+| m e | vincent@sbr.pm | Email address |
+| m g | Vincent Demeester <vincent@sbr.pm> | Git signature format |
+| m s | --<enter>Vincent Demeester<enter>...| Email signature |
+| m t | <Ctrl+U> | Timestamp placeholder |
+
+#### Application Shortcuts (Leader + A + key)
+
+| Sequence | Keybind | Action |
+|----------|-------------------|--------------------------------|
+| a d | Mod+D | Launch fuzzel app launcher |
+| a e | Mod+Shift+Enter | Launch Emacs client |
+| a t | Mod+Enter | Launch Terminal (kitty) |
+| a j | Mod+Control+D | Emoji picker (rofimoji) |
+| a v | Mod+Control+V | Clipboard history (cliphist) |
+| a r | Mod+Shift+D | Raffi launcher |
+
+**Note**: These shortcuts match your niri window manager configuration.
+
+## Development
+
+Files: `config/{config.h, keymap.c, layermodes.{c,h}, rules.mk}`, `go.sh`
+
+## Inspirations and References
+
+- [QMK Documentation](https://docs.qmk.fm/)
+- [ZSA Oryx Configurator](https://configure.zsa.io/)
+- [Miryoku layout](https://github.com/manna-harbour/miryoku)
+- [Home row mods guide](https://sunaku.github.io/home-row-mods.html)
+- [Bépo keyboard layout](https://bepo.fr)
+- [ErgoL keyboard layout](https://ergol.org)
keyboards/moonlander/README.org
@@ -1,155 +0,0 @@
-#+title: ZSA Moonlander QMK Config
-
-Custom QMK firmware for the ZSA Moonlander split keyboard (72 keys, STM32 MCU, RGB backlighting).
-
-* Features
-
-- Layouts: Bépo (primary), ErgoL, QWERTY
-- Home row mods (280ms tapping term), smart numword layer
-- Combos, key overrides, leader key, tap dance
-- French accents (US International layout), repeat key
-
-* Build & Flash
-
-#+begin_src bash
-./go.sh build # Build firmware (output: build/qmk_firmware/.build/)
-./go.sh flash # Build and flash (press reset button when prompted)
-./go.sh update # Update QMK submodules
-./go.sh clean # Clean build artifacts
-#+end_src
-
-* Keymap Visualization
-
-[[file:../moonlander.svg]]
-
-*Note*: Combo definitions are automatically parsed from =keymap.c= during visualization generation via =parse-combos.sh=.
-
-* Layers
-
-| Layer | Name | Description |
-|-------+------------+------------------------------------------------------------------|
-| L0 | Bépo | Primary French layout, home row mods, numword activation |
-| L1 | ErgoL | Alternative French layout |
-| L2 | QWERTY | Standard layout with home row mods |
-| L3 | Symbols | Programming symbols, brackets, operators |
-| L4 | Numbers | Numpad layout (auto-disable after 5s) |
-| L5 | Navigation | Arrows, page nav, media controls |
-| L6 | Mouse | Mouse emulation |
-| L7 | Modifiers | Additional modifiers and function keys |
-
-*Home row mods (Bépo)*: Left: A(GUI) U(Alt) I(Shift) E(Ctrl) ,(Hyper) | Right: C(Hyper) T(Ctrl) S(Shift) R(Alt) N(GUI)
-
-* Configuration
-
-** Timing
-- Tapping: 280ms | Quick tap: 100ms | Flow: 150ms | Combo: 40ms | Numword timeout: 5s
-
-** Combos & Overrides
-- Layer switching, Escape, special chars (|@#$/\&-_=), brackets
-- Bépo overrides: Shift+^=!, Shift+.=:, Shift+,=;, Shift+numbers, RAlt+B=|, RAlt+Space=_
-
-** French Accents (US International)
-é è ê à â ù û î ô ë ï ç € (uppercase variants supported)
-
-** QMK Features
-*Enabled*: Combos, key overrides, leader key, repeat key, tap dance, layer lock
-*Disabled*: Audio, caps word, auto shift, console, most RGB effects (size optimization)
-
-* Usage
-
-- *Layout switching*: Bépo (Nav+Shift), ErgoL (Q+P), QWERTY (Numb+Symb), or via leader sequences
-- *Numword*: Hold Space on Bépo layer (auto-disable after 5s)
-- *Leader key*: Combo Del+RAlt (right thumb cluster, 300ms timeout per key)
-- *Mouse toggle*: Combo Q+R
-
-** Leader Key Sequences
-
-The leader key is activated by pressing Del+RAlt simultaneously (right thumb cluster). After activation, you have 300ms to press each subsequent key in the sequence.
-
-*** Layout Switching (Leader + L + key)
-| Sequence | Action |
-|----------+----------------|
-| l b | Switch to Bépo |
-| l e | Switch to ErgoL|
-| l q | Switch to QWERTY|
-
-*** Development Patterns - General (Leader + C + key)
-| Sequence | Output | Notes |
-|----------+---------------------------+--------------------------------|
-| c n | nil | Go/common nil keyword |
-| c e | if err != nil {<enter><tab>| Go error handling pattern |
-| c l | console.log() | Cursor positioned inside () |
-| c p | fmt.Println() | Cursor positioned inside () |
-| c f | function() {} | Cursor positioned inside {} |
-| c a | () => {} | Arrow function, cursor inside {}|
-
-*** Development Patterns - Python (Leader + P + key)
-| Sequence | Output | Notes |
-|----------+---------------------------+--------------------------------|
-| p i | if __name__ == "__main__":| Python main block |
-| p d | def (): | Function definition, cursor at name |
-| p c | class : | Class definition, cursor at name |
-| p p | print(f"") | f-string print, cursor inside quotes |
-| p t | try:...except Exception as e: | Try-except block |
-| p w | with open("", "r") as f: | File context manager, cursor at path |
-
-*** Development Patterns - Emacs Lisp (Leader + E + key)
-| Sequence | Output | Notes |
-|----------+---------------------------+--------------------------------|
-| e d | (defun () | Function definition, cursor at name |
-| e i | (interactive) | Interactive declaration |
-| e l | (let (( | Let binding |
-| e s | (setq ) | Set variable, cursor at name |
-| e m | (message "") | Message output, cursor inside quotes |
-| e r | (require ') | Require package, cursor after quote |
-
-*** Development Patterns - Nix (Leader + N + key)
-| Sequence | Output | Notes |
-|----------+---------------------------+--------------------------------|
-| n f | { pkgs, ... }: | Nix function signature |
-| n l | let...in | Let expression, cursor in body |
-| n w | with pkgs; [...] | With statement, cursor in list |
-| n i | inherit ; | Inherit, cursor before semicolon |
-| n b | buildInputs = [ ]; | buildInputs, cursor in list |
-| n p | pkgs.writeShellScriptBin ""| Shell script, cursor at name |
-
-*** Import Patterns (Leader + I + key)
-| Sequence | Output | Notes |
-|----------+---------------------------+--------------------------------|
-| i p | import | Python simple import |
-| i f | from import | Python from import, cursor at module |
-| i n | { pkgs }: {...} | Nix module definition |
-| i e | (use-package | Emacs use-package declaration |
-
-*** Personal Macros (Leader + M + key)
-| Sequence | Output | Notes |
-|----------+-------------------------------------+------------------------|
-| m e | vincent@sbr.pm | Email address |
-| m g | Vincent Demeester <vincent@sbr.pm> | Git signature format |
-| m s | --<enter>Vincent Demeester<enter>...| Email signature |
-| m t | <Ctrl+U> | Timestamp placeholder |
-
-*** Application Shortcuts (Leader + A + key)
-| Sequence | Keybind | Action |
-|----------+-------------------+--------------------------------|
-| a d | Mod+D | Launch fuzzel app launcher |
-| a e | Mod+Shift+Enter | Launch Emacs client |
-| a t | Mod+Enter | Launch Terminal (kitty) |
-| a j | Mod+Control+D | Emoji picker (rofimoji) |
-| a v | Mod+Control+V | Clipboard history (cliphist) |
-| a r | Mod+Shift+D | Raffi launcher |
-
-*Note*: These shortcuts match your niri window manager configuration.
-
-* Development
-
-Files: =config/{config.h, keymap.c, layermodes.{c,h}, rules.mk}=, =go.sh=
-
-* Inspirations and References
-
-- [[https://docs.qmk.fm/][QMK Documentation]]
-- [[https://configure.zsa.io/][ZSA Oryx Configurator]]
-- [[https://github.com/manna-harbour/miryoku][Miryoku layout]]
-- [[https://sunaku.github.io/home-row-mods.html][Home row mods guide]]
-- [[https://bepo.fr][Bépo keyboard layout]]
-- [[https://ergol.org][ErgoL keyboard layout]]
keyboards/README.org → keyboards/README.md
@@ -1,17 +1,17 @@
-#+title: Keyboard Configurations
+# Keyboard Configurations
Custom firmware configurations for split ergonomic keyboards with Bépo, ErgoL, and QWERTY layouts.
-* Keyboards
+## Keyboards
-| Keyboard | Firmware | Keys | Features | Details |
-|----------------+----------+------+------------------------------------------+------------------------------------------|
-| Moonlander | QMK | 72 | RGB backlighting, wired USB-C | [[file:moonlander/README.org][moonlander/README.org]] |
-| Eyelash Corne | ZMK | 42 | Wireless, nice!view display, RGB underglow | [[file:eyelash_corne/README.org][eyelash_corne/README.org]] |
+| Keyboard | Firmware | Keys | Features | Details |
+|---------------|----------|------|--------------------------------------------|--------------------------------------|
+| Moonlander | QMK | 72 | RGB backlighting, wired USB-C | [moonlander/README.md](moonlander/README.md) |
+| Eyelash Corne | ZMK | 42 | Wireless, nice!view display, RGB underglow | [eyelash_corne/README.md](eyelash_corne/README.md) |
-* Quick Start
+## Quick Start
-#+begin_src bash
+```bash
# Moonlander (QMK)
make moonlander/build # Build firmware
make moonlander/flash # Build and flash firmware
@@ -33,17 +33,17 @@
make all # Build all keyboards
make clean # Clean all build artifacts
make help # Show all targets
-#+end_src
+```
-* Layout Features
+## Layout Features
Both keyboards use:
-- *Primary*: [[https://bepo.fr][Bépo]] (French-optimized) | *Alternatives*: [[https://ergol.org][ErgoL]], QWERTY
+- **Primary**: [Bépo](https://bepo.fr) (French-optimized) | **Alternatives**: [ErgoL](https://ergol.org), QWERTY
- Home row mods (GUI, Alt, Shift, Ctrl, Hyper)
- Smart numword layer, combos, French accents
- Multiple layers: Base, Symbols, Numbers, Navigation, Function
-* Configuration Philosophy
+## Configuration Philosophy
- Minimize finger movement with home row mods
- Layer-based approach for symbols and numbers
@@ -52,4 +52,3 @@
- Wireless option (Corne) and wired option (Moonlander) for different use cases
See individual READMEs for detailed documentation.
-
tools/hl/README.md
@@ -0,0 +1,10 @@
+# hl, home-lab dispatcher
+
+This is a tool that encapsulate behavior and knowledge from my home
+network. The idea is that for things like wake-on-lan, etc. I can
+easily run a command.
+
+```bash
+$ hl wake-up shikoku # wakes up shikoku
+$ hl poweroff shikoku # shuts down shikoku (using ssh, …)
+```
tools/hl/README.org
@@ -1,10 +0,0 @@
-#+TITLE: hl, home-lab dispatcher
-
-This is a tool that encapsulate behavior and knowledge from my home
-network. The idea is that for things like wake-on-lan, etc. I can
-easily run a command.
-
-#+begin_src bash
- $ hl wake-up shikoku # wakes up shikoku
- $ hl poweroff shikoku # shuts down shikoku (using ssh, …)
-#+end_src
tools/README.org → tools/README.md
@@ -1,19 +1,18 @@
-#+TITLE: Tools
-#+AUTHOR: Vincent Demeester
-#+DATE: 2025-11-22
+# Tools
Collection of custom tools and utilities for system management and automation.
-* Shell Scripts
+## Shell Scripts
-** DNS Management
+### DNS Management
-*** show-dns.sh
+#### show-dns.sh
Display DNS zone configuration from NixOS bind configuration with enhanced formatting.
-*Usage:*
-#+begin_src shell
+**Usage:**
+
+```shell
# Show compact summary view (default)
./show-dns.sh
@@ -25,9 +24,9 @@
# Or via make target
make dns-show
-#+end_src
+```
-*Features:*
+**Features:**
- Compact summary view with record counts by default
- Color-coded DNS record types (SOA, NS, A, PTR, etc.)
- Column-aligned output for easy scanning
@@ -37,12 +36,13 @@
- Statistics summary at the end
- Useful for verifying DNS configuration before sync
-*** update-gandi-dns.sh
+#### update-gandi-dns.sh
Synchronize DNS records from NixOS configuration to Gandi Live DNS.
-*Usage:*
-#+begin_src shell
+**Usage:**
+
+```shell
# Dry run to preview changes (requires GANDIV5_PERSONAL_TOKEN)
./update-gandi-dns.sh --dry-run
@@ -52,48 +52,50 @@
# Or via make targets
make dns-update-gandi-dry-run
make dns-update-gandi
-#+end_src
+```
-*Features:*
+**Features:**
- Extracts A records from NixOS DNS zone configuration
- Syncs records to Gandi Live DNS API using Bearer token authentication
- Dry-run mode for safe preview of changes
- Skips unchanged records to minimize API calls
- Supports wildcard DNS records
-*Requirements:*
-- =GANDIV5_PERSONAL_TOKEN= environment variable (Gandi Personal Access Token)
-- On rhea: =source /run/agenix/gandi.env= to load token
+**Requirements:**
+- `GANDIV5_PERSONAL_TOKEN` environment variable (Gandi Personal Access Token)
+- On rhea: `source /run/agenix/gandi.env` to load token
-* Python Scripts
+## Python Scripts
-** Media Management (*arr Stack)
+### Media Management (*arr Stack)
-*** lidarr-update-paths.py
+#### lidarr-update-paths.py
Update artist paths in Lidarr to use a 'library' subdirectory.
-*Usage:*
-#+begin_src shell
+**Usage:**
+
+```shell
# Dry run to preview changes
./lidarr-update-paths.py http://localhost:8686 API_KEY /data/music --dry-run
# Apply changes
./lidarr-update-paths.py http://localhost:8686 API_KEY /data/music
-#+end_src
+```
-*Features:*
-- Migrates artists from =/music/<artist>= to =/music/library/<artist>=
+**Features:**
+- Migrates artists from `/music/<artist>` to `/music/library/<artist>`
- Dry-run mode for safe preview
- Categorizes artists by current location
- Bulk path updates via Lidarr API
-*** lidarr-rename-albums.py
+#### lidarr-rename-albums.py
Rename albums in Lidarr with interactive confirmation.
-*Usage:*
-#+begin_src shell
+**Usage:**
+
+```shell
# Dry run to preview renames
./lidarr-rename-albums.py http://localhost:8686 API_KEY --dry-run
@@ -102,20 +104,21 @@
# Auto-confirm all renames (--yolo or --no-confirm)
./lidarr-rename-albums.py http://localhost:8686 API_KEY --yolo
-#+end_src
+```
-*Features:*
+**Features:**
- Checks all artists for albums with files needing rename
- Shows preview of up to 10 file renames per artist
- Interactive confirmation before applying changes
- Dry-run and auto-confirm (--yolo/--no-confirm) modes
-*** lidarr-retag-albums.py
+#### lidarr-retag-albums.py
Retag albums in Lidarr with interactive confirmation.
-*Usage:*
-#+begin_src shell
+**Usage:**
+
+```shell
# Dry run to preview retags
./lidarr-retag-albums.py http://localhost:8686 API_KEY --dry-run
@@ -124,21 +127,22 @@
# Auto-confirm all retags (--yolo or --no-confirm)
./lidarr-retag-albums.py http://localhost:8686 API_KEY --yolo
-#+end_src
+```
-*Features:*
+**Features:**
- Checks all artists for albums with files needing retag
- Shows preview of up to 5 file retags per artist with tag changes
- Displays old → new values for each modified tag
- Interactive confirmation before applying changes
- Dry-run and auto-confirm (--yolo/--no-confirm) modes
-*** sonarr-rename-series.py
+#### sonarr-rename-series.py
Rename TV series episodes in Sonarr with interactive confirmation.
-*Usage:*
-#+begin_src shell
+**Usage:**
+
+```shell
# Dry run to preview renames
./sonarr-rename-series.py http://localhost:8989 API_KEY --dry-run
@@ -147,20 +151,21 @@
# Auto-confirm all renames (--yolo or --no-confirm)
./sonarr-rename-series.py http://localhost:8989 API_KEY --yolo
-#+end_src
+```
-*Features:*
+**Features:**
- Checks all series for episodes needing rename
- Shows preview of up to 10 episode renames per series
- Interactive confirmation before applying changes
- Dry-run and auto-confirm (--yolo/--no-confirm) modes
-*** radarr-rename-movies.py
+#### radarr-rename-movies.py
Rename movies in Radarr with interactive confirmation.
-*Usage:*
-#+begin_src shell
+**Usage:**
+
+```shell
# Dry run to preview renames
./radarr-rename-movies.py http://localhost:7878 API_KEY --dry-run
@@ -169,69 +174,70 @@
# Auto-confirm all renames (--yolo or --no-confirm)
./radarr-rename-movies.py http://localhost:7878 API_KEY --yolo
-#+end_src
+```
-*Features:*
+**Features:**
- Checks all movies for files needing rename
- Shows preview of all file renames per movie
- Interactive confirmation before applying changes
- Dry-run and auto-confirm (--yolo/--no-confirm) modes
-* Go Tools
+## Go Tools
-** arr
+### arr
Unified CLI for managing *arr services (Sonarr, Radarr, Lidarr) and Jellyfin with Spotify playlist sync.
-See [[file:arr/README.md][arr/README.md]] for detailed documentation.
+See [arr/README.md](arr/README.md) for detailed documentation.
-** battery-monitor
+### battery-monitor
Battery monitoring daemon and notification system for laptops.
-** cliphist-cleanup
+### cliphist-cleanup
Clipboard history cleanup utility for cliphist.
-** gh-pr
+### gh-pr
GitHub pull request management tool for approving and managing PRs.
-* Python Tools
+## Python Tools
-** music-playlist-dl
+### music-playlist-dl
Automated downloader for electronic music podcasts from Mixcloud/SoundCloud with M3U playlist generation.
-See [[file:music-playlist-dl/README.md][music-playlist-dl/README.md]] for detailed documentation.
+See [music-playlist-dl/README.md](music-playlist-dl/README.md) for detailed documentation.
-** download-kiwix-zim
+### download-kiwix-zim
Browse and download ZIM files from the Kiwix library using fzf.
-* Other Tools
+## Other Tools
-** org-manager
+### org-manager
Org-mode management utilities for programmatic org file manipulation.
-* Directories
+## Directories
-** emacs/
+### emacs/
Emacs configuration and custom packages.
-** fedora-vm/
+### fedora-vm/
Fedora VM setup and configuration scripts.
-* Notes
+## Notes
-All Python scripts use the =uv= tool with inline script metadata (PEP 723).
-They require only the =requests= library and will automatically manage
-dependencies when run with =uv=.
+All Python scripts use the `uv` tool with inline script metadata (PEP 723).
+They require only the `requests` library and will automatically manage
+dependencies when run with `uv`.
All scripts are executable and include built-in help:
-#+begin_src shell
+
+```shell
./script-name.py --help
-#+end_src
+```