{"id":51303854,"url":"https://github.com/phalt/pauldot","last_synced_at":"2026-06-30T22:32:19.495Z","repository":{"id":355845814,"uuid":"1229835518","full_name":"phalt/pauldot","owner":"phalt","description":null,"archived":false,"fork":false,"pushed_at":"2026-05-05T15:19:01.000Z","size":48,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-05-05T15:32:52.456Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/phalt.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-05-05T12:33:05.000Z","updated_at":"2026-05-05T15:19:06.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/phalt/pauldot","commit_stats":null,"previous_names":["phalt/pauldot"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/phalt/pauldot","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/phalt%2Fpauldot","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/phalt%2Fpauldot/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/phalt%2Fpauldot/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/phalt%2Fpauldot/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/phalt","download_url":"https://codeload.github.com/phalt/pauldot/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/phalt%2Fpauldot/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34986248,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-30T02:00:05.919Z","response_time":92,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2026-06-30T22:32:17.518Z","updated_at":"2026-06-30T22:32:19.441Z","avatar_url":"https://github.com/phalt.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# pauldot\n\nPauldot is a terminal and tooling configuration manager for users who want to keep their configuration across multiple machines in sync.\n\nUse it to manage:\n\n- Aliases\n- Dotfiles\n- Tools\n- Environment variables\n- Profiles\n\n\n## Install\n\n```sh\nuv tool install pauldot\n```\n\n## Quick start (new dotfiles repo)\n\n```sh\n# 1. Create your dotfiles repo on GitHub\ngh repo create \u003cyou\u003e/dotfiles --private --clone\n\n# 2. Scaffold the structure\npauldot init --scaffold ./dotfiles\n\n# 3. If you have an existing ~/.zshrc, migrate it in\npauldot migrate\n\n# 4. Edit pauldot.toml and bootstrap.sh, then push\ncd dotfiles \u0026\u0026 git add . \u0026\u0026 git commit -m \"init\" \u0026\u0026 git push\n\n# 5. On any new machine\ncurl -sSL https://raw.githubusercontent.com/\u003cyou\u003e/dotfiles/main/bootstrap.sh | sh\n```\n\nRun `pauldot help fork` for the full walkthrough.\n\n## Quick start (existing dotfiles repo, new machine)\n\n```sh\npauldot init git@github.com:\u003cyou\u003e/dotfiles\n\n# If this machine already has a ~/.zshrc, bring it under management first\npauldot migrate --dry-run   # preview what will be absorbed\npauldot migrate             # write aliases → aliases.zsh, rest → zshrc.base\n\npauldot apply\n```\n\nIf your repo is private, set up GitHub CLI first — `pauldot help gh` walks you through it.\n\n## Commands\n\n```\npauldot init [\u003crepo-url\u003e]        Clone your dotfiles repo and configure this machine\npauldot init --scaffold \u003cpath\u003e   Generate a starter dotfiles repo structure\npauldot apply                    Reconcile current profile (zshrc + tools + dotfiles)\npauldot apply --overwrite        Also overwrite existing dotfiles from repo (backs up first)\npauldot status                   Dry-run apply — show what would change\npauldot doctor                   Health check\n\npauldot migrate                  Migrate an existing ~/.zshrc into your dotfiles repo\npauldot migrate --dry-run        Preview what would be migrated without writing anything\n\npauldot track \u003cpath\u003e             Start tracking a dotfile: copy it into the repo\npauldot sync                     Pull remote changes; push local edits\npauldot clean                    List backup files left by pauldot (dry-run)\npauldot clean --yes              Delete all backup files\n\npauldot profile show             Show the active profile\npauldot profile list             List available profiles\npauldot profile set \u003cname\u003e       Switch profile\n\npauldot tool list                List all defined tools and install status\npauldot tool install [\u003cname\u003e]    Install a tool (or all profile tools)\npauldot tool add                 Interactively add a tool to tools.toml\npauldot tool remove \u003cname\u003e       Remove a tool from tools.toml\n\npauldot alias add \u003ckey\u003e \u003cvalue\u003e  Add an alias to aliases.zsh\npauldot alias list               List defined aliases\n\npauldot absorb                   Absorb external zshrc modifications into source files\npauldot absorb --dry-run         Show what would be absorbed without writing\npauldot absorb --target \u003cfile\u003e   Absorb into a specific source file (default: zshrc.base)\npauldot edit [profile|tools|zshrc|pauldot]  Open a dotfiles file in $EDITOR\n\npauldot help bootstrap           Bootstrap walkthrough for new machines\npauldot help gh                  GitHub CLI auth walkthrough\npauldot help fork                How to set up your own dotfiles repo\n```\n\n## Dotfiles\n\npauldot tracks dotfiles in `files/home/` inside your repo. A file tracked at `files/home/.gitconfig` maps to `~/.gitconfig` on each machine.\n\n```sh\npauldot track ~/.gitconfig       # copies to files/home/.gitconfig, adds to profile\npauldot apply                    # bootstraps missing dotfiles on a new machine\npauldot apply --overwrite        # pull repo version to live (with backup)\npauldot sync                     # copies live edits into repo and pushes\n```\n\n**Backups.** Whenever pauldot replaces an existing file — during `apply` on first run (for `~/.zshrc`) or `apply --overwrite` (for tracked dotfiles) — the original is backed up to `\u003cfile\u003e.bak.\u003ctimestamp\u003e` in the same directory. Run `pauldot clean` to list them; `pauldot clean --yes` to delete.\n\n**Sync behaviour.** `pauldot sync` detects per-file what changed on each side since the last pull:\n\n| Outcome | What happened | What sync does |\n|---|---|---|\n| `no_change` | Live matches repo | Nothing |\n| `synced` | Only live changed | Copies live → repo, commits, pushes |\n| `remote_updated` | Only remote changed | Ejects — run `pauldot apply --overwrite` |\n| `conflict` | Both sides changed | Ejects — resolve manually or run `apply --overwrite` |\n\nIf sync ejects due to `remote_updated` or `conflict`, it records the unresolved paths in `~/.config/pauldot/sync_state.toml`. Running sync again without resolving will eject again — it will never silently overwrite a remote change with a stale local file.\n\n## Dotfiles repo layout\n\n```\n~/.pauldot/\n├── pauldot.toml           # top-level config (shell, git, bootstrap settings)\n├── profiles/\n│   ├── base.toml          # shared base profile\n│   └── personal.toml      # extends base; machine-specific overrides\n├── files/\n│   ├── zshrc.base         # base zsh config\n│   ├── zshrc.personal     # profile-specific zsh config\n│   ├── aliases.zsh        # managed by `pauldot alias add`\n│   └── home/\n│       ├── .gitconfig     # tracked dotfiles (copied to ~ on apply)\n│       └── .config/\n│           └── starship.toml\n├── tools/\n│   └── tools.toml         # tool definitions (check + install commands)\n└── bootstrap.sh           # one-liner for new machines\n```\n\n`~/.zshrc` is a plain file written by pauldot (not a symlink). It is regenerated by `apply` each time your profile changes.\n\n## Local state\n\n```\n~/.config/pauldot/state.toml   # active profile, repo URL, and any unresolved sync issues (not committed)\n```\n\n## Development\n\n```sh\nmake install    # uv sync\nmake test       # uv run pytest\nmake lint       # uv run ruff check .\nmake format     # uv run ruff format .\n```\n\nRequires Python 3.14+ and [uv](https://github.com/astral-sh/uv).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fphalt%2Fpauldot","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fphalt%2Fpauldot","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fphalt%2Fpauldot/lists"}