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..githuband.pre-commit-config.yamlrequire--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 --cachedcommand 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)
| File | Size | Uploaded | |
|---|---|---|---|
| undot-0.3.0.tar.gz | 48.5 kB | Details |
Built distributions (wheels)
| File | Reset | |||
|---|---|---|---|---|
| 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}
|