Skip to main content

ai-deroot-pre-commit

image image image

A pre-commit hook for managing symlinks to AI configuration files stored in a hidden directory.

Overview

Many AI tools (Claude Code, Gemini, etc.) require configuration files like CLAUDE.md, GEMINI.md, and project-specific files like specs/, templates/, and memory/ to be present at the repository root. However, committing these files directly to your main branch can clutter your repository and create merge conflicts when working across branches.

This pre-commit hook solves this by:

  1. Storing master files in a hidden directory (e.g., .llm/)
  2. Creating symlinks from the repository root to the hidden directory
  3. Managing .gitignore to prevent accidental commits of symlinked files
  4. Validating symlinks to ensure they're always properly configured
  5. Optional: Migrating existing files at the repo root into your hidden directory (copy or move) before creating the symlinks

Usage

Add this to your .pre-commit-config.yaml:

repos:
  - repo: https://github.com/shyndman/ai-deroot-pre-commit
    rev: v0.0.9  # Use the ref you want to point at
    hooks:
      - id: setup-managed-symlinks
      - id: check-managed-symlinks
      - id: update-gitignore-for-symlinks

Full Configuration Example

repos:
  - repo: https://github.com/shyndman/ai-deroot-pre-commit
    rev: v0.0.9
    hooks:
      # Sets up symlinks after checkout/merge
      - id: setup-managed-symlinks
        args:
          - --hidden-dir=.llm
          - --files=CLAUDE.md,GEMINI.md,specs,templates,memory
          - --migrate=move  # or copy

      # Validates symlinks during normal commits
      - id: check-managed-symlinks
        args:
          - --hidden-dir=.llm
          - --files=CLAUDE.md,GEMINI.md,specs,templates,memory

      # Ensures .gitignore includes symlinked files
      - id: update-gitignore-for-symlinks
        args:
          - --hidden-dir=.llm
          - --files=CLAUDE.md,GEMINI.md,specs,templates,memory

Hook Details

setup-managed-symlinks

When it runs: post-checkout, post-merge

Creates symlinks from the repository root to files in your hidden directory. This ensures that after switching branches or pulling changes, your LLM configuration files are always available where tools expect them.

Features:

  • Creates missing symlinks automatically
  • Fixes incorrectly pointing symlinks
  • Creates the hidden directory if it doesn't exist (supports any dot-dir like .ai, .llm, etc.)
  • Optional migration: copy or move existing root files into the hidden dir before creating symlinks

check-managed-symlinks

When it runs: pre-commit (when hidden directory or .gitignore changes)

Validates that all expected symlinks exist and point to the correct locations. Prevents commits when symlinks are broken or missing.

Features:

  • Validates symlink targets
  • Detects broken symlinks
  • Ensures source files exist
  • Provides clear error messages with fix instructions

update-gitignore-for-symlinks

When it runs: pre-commit

Automatically adds symlinked files to .gitignore to prevent accidental commits. This hook will modify .gitignore and require you to stage the changes.

Features:

  • Adds missing entries to .gitignore
  • Preserves existing .gitignore content
  • Adds descriptive comments
  • Only runs when changes are needed

Configuration Options

--hidden-dir

Specifies the directory where master files are stored.

  • Default: None (required parameter)
  • Example: --hidden-dir=.llm
  • Note: Can be any directory name, doesn't need to start with .

--files

Comma-separated list of files/directories to manage as symlinks.

  • Default: None (required parameter)
  • Example: --files=CLAUDE.md,GEMINI.md,specs,templates,memory
  • Note: Supports both files and directories

Workflow Example

  1. Initial setup:

    # Create your hidden directory and files
    mkdir .llm
    echo "# Claude Configuration" > .llm/CLAUDE.md
    mkdir .llm/specs
    
    # Install pre-commit hooks
    pre-commit install-hooks
    
    # Create initial symlinks
    pre-commit run --hook-stage post-checkout setup-managed-symlinks
    
  2. After setup, symlinks are created automatically:

    git checkout main
    # setup-managed-symlinks runs automatically
    # Creates: CLAUDE.md -> .llm/CLAUDE.md
    #          specs -> .llm/specs
    
  3. The .gitignore is updated automatically:

    git add file.py
    git commit -m "Add feature"
    # update-gitignore-for-symlinks runs
    # Adds entries to .gitignore if needed
    

Important Notes

File Conflicts

If you have existing files at the target locations, the setup-managed-symlinks hook will warn you and not overwrite them. You'll need to manually resolve these conflicts by either:

  • Moving the existing file to the hidden directory
  • Removing the existing file if it's no longer needed
  • Updating your .gitignore if the file should be tracked

Hook Stages

The hooks are designed to run at specific stages:

  • setup-managed-symlinks: post-checkout, post-merge - Ensures symlinks exist after branch operations
  • check-managed-symlinks: pre-commit - Validates before commits (only when relevant files change)
  • update-gitignore-for-symlinks: pre-commit - Updates .gitignore before commits

Updating File Lists

When you add or remove files from the --files argument, you must also update the files regex in the check-managed-symlinks hook configuration to ensure it runs at the appropriate times.

Troubleshooting

Broken Symlinks

If you see errors about broken symlinks:

# Run the setup hook manually
pre-commit run --hook-stage post-checkout setup-managed-symlinks

# Or use pre-commit's built-in command
pre-commit install --hook-type post-checkout

Permission Issues

If you encounter permission issues with symlinks, ensure your filesystem supports symbolic links and that you have appropriate permissions in the repository directory.

Git Ignore Not Updating

If .gitignore entries aren't being added automatically:

# Run the gitignore hook manually
pre-commit run update-gitignore-for-symlinks
git add .gitignore
git commit -m "Update .gitignore for managed symlinks"

Packaging

This project uses the uv_build PEP 517 build backend (pure Python). The package is kept at the repository root (no src/ layout) via:

[build-system]
requires = ["uv_build>=0.9.3,<0.10.0"]
build-backend = "uv_build"

[tool.uv.build-backend]
module-root = ""
module-name = "ai_deroot_pre_commit"

pre-commit installs this hook using its Python language backend by building and installing the package in an isolated environment.

License

Licensed under the Apache License, Version 2.0 (LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0).

--migrate

Optionally migrate existing root files into the hidden directory before creating symlinks.

  • Values: copy or move
  • move relocates the file/dir into the hidden directory
  • copy duplicates into the hidden directory; the original is replaced by a symlink

Notes:

  • Migration only occurs when the source does not yet exist in the hidden directory and the target exists as a real file/dir.
  • If both source and target exist, migration is skipped with a warning.

Metadata

Release files for ai-deroot-pre-commit 0.0.9

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for ai-deroot-pre-commit 0.0.9
File Size Uploaded
ai_deroot_pre_commit-0.0.9.tar.gz 6.3 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for ai-deroot-pre-commit 0.0.9
File Interpreter ABI Platform
ai_deroot_pre_commit-0.0.9-py3-none-any.whl Python 3 none any Details

Total release size: 14.1 kB

Release files / ai_deroot_pre_commit-0.0.9.tar.gz

Download URL ai_deroot_pre_commit-0.0.9.tar.gz
Size 6.3 kB
Tags Source
SHA-256 checksum
How to use checksums
26556425a0ef2c1c58249eb1700bba7f4e5171851185c5fb4fdfbed3b0708760
BLAKE2b-256 checksum
How to use checksums
79088242e69e4788ca47e4aca9539b90d9a845084186a8433bce694361246f06
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.8.4

Release files / ai_deroot_pre_commit-0.0.9-py3-none-any.whl

Download URL ai_deroot_pre_commit-0.0.9-py3-none-any.whl
Size 7.7 kB
Tags Python 3
SHA-256 checksum
How to use checksums
3c619685989835d132e6f35e75babf902ea5d20ff0eeecf96555f0f82875a9b7
BLAKE2b-256 checksum
How to use checksums
33824dfa3e973c9ff0d59db3c368b22a3152e3528a1a27983a90fe7265bab6ee
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.8.4

Release history Release notifications | RSS feed

This release

0.0.9 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page