Skip to main content

undot

Declutter a project's root directory by taming configuration file sprawl.

before              after
──────              ─────
.claude/            .config/
.cursor/            .github/
.editorconfig       src/
.github/
.npmrc
.yarn/
src/

Every tool wants a dotfile at the repository root. undot moves them into a single tracked .config/ directory. Gitignored symlinks point back to the root, so every tool keeps working. A pre-commit hook (or prek) recreates the symlinks on every clone and checkout. Teammates install nothing and notice nothing.

Install

uv tool install undot   # or: pip install undot

Small static binaries (~200KB, instant startup) for Linux and macOS, also on GitHub releases. The pre-commit hook (below) needs no install at all.

Migrate an existing repository

undot migrate             # or name entries: undot migrate .claude .cursor
git add -A && git commit
pre-commit install

One idempotent command:

  • moves the configs
  • creates the symlinks
  • updates .gitignore (existing rules that reached inside a moved directory get matching .config/ patterns)
  • registers the git hook below

Clones and new repos set themselves up

migrate writes this hook config. After clone, checkout, merge, or rebase, it restores any missing symlink:

default_install_hook_types: [pre-commit, post-checkout, post-merge, post-rewrite]
repos:
  - repo: https://github.com/jmelahman/undot
    rev: v0.3.0
    hooks:
      - id: undot

CI configs migrate too

CI checkouts don't run hooks. Most tools accept an explicit config path, so a file like .goreleaser.yaml can live in .config/ with no symlink at all:

undot migrate .goreleaser.yaml
echo 'nolink .goreleaser.yaml' >> .config/undot.conf
- run: goreleaser release --clean --config .config/.goreleaser.yaml

Guardrails

  • .git* files are never migrated. .github and .pre-commit-config.yaml require --force, because a fresh clone must be able to bootstrap the hook.
  • Caches, secrets, and CI-read configs (.venv, .env, .golangci.yml, ...) are skipped unless you name them.
  • Conflicts are reported, never overwritten. Migrating a tracked file prints the git rm --cached command you'll want afterwards.

Tune the scan in .config/undot.conf or ~/.config/undot/undot.conf, one name or glob per line:

# never migrate these here
.idea*
# do migrate .env, despite the default skip
!.env
# keep in .config/ without a root symlink
nolink .goreleaser.yaml

Metadata

Release files for undot 0.3.0

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

Source distribution (sdist)

Source distribution for undot 0.3.0
File Size Uploaded
undot-0.3.0.tar.gz 48.5 kB Details

Built distributions (wheels)

Table of built distributions (wheels) for undot 0.3.0
File
undot-0.3.0-py3-none-manylinux_2_17_x86_64.whl Python 3 none Linux glibc 2.17+ x86-64 Details
undot-0.3.0-py3-none-manylinux_2_17_aarch64.whl Python 3 none Linux glibc 2.17+ ARM64 Details
undot-0.3.0-py3-none-macosx_11_0_arm64.whl Python 3 none macOS 11.0+ ARM64 Details
undot-0.3.0-py3-none-macosx_10_12_x86_64.whl Python 3 none macOS 10.12+ x86-64 Details

Total release size: 423.5 kB

Release files / undot-0.3.0.tar.gz

Download URL undot-0.3.0.tar.gz
Size 48.5 kB
Tags Source
SHA-256 checksum
How to use checksums
da90864282ef713cec47289a6f014fb15fe2c09d92eadf73fbb25c185add369a
BLAKE2b-256 checksum
How to use checksums
661678ecb742de7399cc33540f81c4b2416751cf51d2af1768e78f54962664e7
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.12.3 {"installer":{"name":"uv","version":"0.12.3","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release files / undot-0.3.0-py3-none-manylinux_2_17_x86_64.whl

Download URL undot-0.3.0-py3-none-manylinux_2_17_x86_64.whl
Size 127.1 kB
Tags Linux glibc 2.17+ x86-64 Python 3
SHA-256 checksum
How to use checksums
4972f247461666a48f52cd61c546bc73a1031f24eaa5dca83ab43a235bbe0061
BLAKE2b-256 checksum
How to use checksums
21ebb9406545cee70045be12925b9bb26944bb95b084b015d16137f7fcfc59ea
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.12.3 {"installer":{"name":"uv","version":"0.12.3","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release files / undot-0.3.0-py3-none-manylinux_2_17_aarch64.whl

Download URL undot-0.3.0-py3-none-manylinux_2_17_aarch64.whl
Size 132.2 kB
Tags Linux glibc 2.17+ ARM64 Python 3
SHA-256 checksum
How to use checksums
90a7f1c6b59ab11166b1ae0cdfac1be70bac9973bb817e186bea779b15eeaf7b
BLAKE2b-256 checksum
How to use checksums
24f25d1c6d841c992df0ecc60e8bdccad249a4b850c389fa050631eb844eea8c
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.12.3 {"installer":{"name":"uv","version":"0.12.3","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release files / undot-0.3.0-py3-none-macosx_11_0_arm64.whl

Download URL undot-0.3.0-py3-none-macosx_11_0_arm64.whl
Size 57.9 kB
Tags Python 3 macOS 11.0+ ARM64
SHA-256 checksum
How to use checksums
019d4bac57c1b5a07c7aec7b0a6cbd76fed6329f0f98843fc33b3ca03eb48151
BLAKE2b-256 checksum
How to use checksums
39dd02580262a38051b987bf2ad691451be75f0f74402ad5dae1f4398844e432
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.12.3 {"installer":{"name":"uv","version":"0.12.3","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release files / undot-0.3.0-py3-none-macosx_10_12_x86_64.whl

Download URL undot-0.3.0-py3-none-macosx_10_12_x86_64.whl
Size 57.8 kB
Tags Python 3 macOS 10.12+ x86-64
SHA-256 checksum
How to use checksums
a960fd58bf305568263780f8a3f51a2338b8bf1e3c00823dbfe8d3d5daddc8da
BLAKE2b-256 checksum
How to use checksums
b431024f1cf80c2b8d3ab25fbea7627352be27a9c15810722fdec52ef5180548
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.12.3 {"installer":{"name":"uv","version":"0.12.3","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release history Release notifications | RSS feed

This release

0.3.0 This release

5 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