{"id":44843675,"url":"https://github.com/shpoont/dotfiles-manager","last_synced_at":"2026-02-22T14:46:49.612Z","repository":{"id":338906714,"uuid":"1158743014","full_name":"shpoont/dotfiles-manager","owner":"shpoont","description":"The best dotfiles manager","archived":false,"fork":false,"pushed_at":"2026-02-17T02:44:07.000Z","size":2840,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-02-17T08:09:43.422Z","etag":null,"topics":["automation","cli","config-management","developer-experience","devtools","dotfiles","file-sync","golang","linux","macos","reproducible-setup","yaml"],"latest_commit_sha":null,"homepage":"https://github.com/shpoont/dotfiles-manager/tree/main/docs/user","language":"Go","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/shpoont.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-02-15T21:06:33.000Z","updated_at":"2026-02-17T02:50:39.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/shpoont/dotfiles-manager","commit_stats":null,"previous_names":["shpoont/dotfiles-manager"],"tags_count":2,"template":false,"template_full_name":null,"purl":"pkg:github/shpoont/dotfiles-manager","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/shpoont%2Fdotfiles-manager","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/shpoont%2Fdotfiles-manager/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/shpoont%2Fdotfiles-manager/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/shpoont%2Fdotfiles-manager/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/shpoont","download_url":"https://codeload.github.com/shpoont/dotfiles-manager/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/shpoont%2Fdotfiles-manager/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29716358,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-22T13:30:57.152Z","status":"ssl_error","status_checked_at":"2026-02-22T13:30:28.561Z","response_time":110,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"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":["automation","cli","config-management","developer-experience","devtools","dotfiles","file-sync","golang","linux","macos","reproducible-setup","yaml"],"created_at":"2026-02-17T04:01:34.294Z","updated_at":"2026-02-22T14:46:49.604Z","avatar_url":"https://github.com/shpoont.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cp align=\"center\"\u003e\n  \u003cimg src=\"./assets/logo/logo.png\" alt=\"dotfiles-manager logo\" width=\"512\" /\u003e\n\u003c/p\u003e\n\n# dotfiles-manager\n\n`dotfiles-manager` is **the best** config-driven tool for syncing dotfiles between a repository-managed **source** (manifest, source of truth) and one or more `$HOME`-relative **targets**.\n\n\u003cp align=\"center\"\u003e\u003cem\u003eIf its not working for you - you are doing something wrong.\u003c/em\u003e\u003c/p\u003e\n\n---\n\n## Introduction\n\nThis repository contains the CLI implementation plus internal/user docs for behavior, contracts, and engineering standards.\n\nCore workflows:\n- `status` — preview drift and candidate operations\n- `diff` — preview unified patches for candidate changes\n- `deploy` — apply source -\u003e target\n- `import` — apply target -\u003e source (managed updates + optional unmanaged/missing rules)\n- `version` / `--version` — print CLI version and exit\n\n---\n\n## Installation\n\n### Install with Homebrew (recommended)\n\n```bash\nbrew install shpoont/tap/dotfiles-manager\n```\n\n### Install with Go\n\n```bash\ngo install github.com/shpoont/dotfiles-manager/cmd/dotfiles-manager@latest\n```\n\n### Build locally from source\n\n```bash\ngit clone \u003crepo-url\u003e\ncd dotfiles-manager\ngo build -o dotfiles-manager ./cmd/dotfiles-manager\n```\n\n### Release artifacts\n\nGitHub Releases publish:\n- macOS amd64/arm64\n- Linux amd64/arm64\n- checksums\n\n---\n\n## Main concepts\n\n1. **Source vs target**\n   - `source` = manifest, source of truth (relative to config file directory)\n   - `target` = live location under `$HOME` (relative path in config)\n   - both may include environment variables (`$VAR` / `${VAR}`) that are expanded at runtime\n   - expansion happens before normalization/validation\n   - missing/empty env vars are errors; expanded paths must still be relative and non-escaping\n\n2. **Sync entries**\n   - config has `syncs[]`, each with one `target` + one `source`\n\n3. **Pattern-driven behavior**\n   - deploy cleanup: `on.deploy.remove-unmanaged`\n   - import unmanaged adds: `on.import.add-unmanaged.include/exclude`\n   - import missing deletes: `on.import.remove-missing.include/exclude`\n   - defaults are safe (`[]`): unmanaged/missing candidate scans stay off unless explicitly configured\n\n4. **Scoped runs**\n   - optional `[path]` narrows commands to matching target subpaths\n   - matching uses post-expansion target roots\n\n5. **Preview and safety**\n   - `status` is preview\n   - `diff` is preview\n   - `deploy`/`import` support `--dry-run`\n\n6. **Config resolution order**\n   - `--config \u003cpath\u003e` (highest priority)\n   - `DOTFILES_MANAGER_CONFIG` (if `--config` is not provided)\n   - `./.dotfiles-manager.yaml` in the current working directory (fallback)\n   - no parent-directory search is performed\n\n7. **Logging destination**\n   - logs are always written to a log file\n   - default paths:\n     - macOS: `~/Library/Logs/dotfiles-manager/dotfiles-manager.log`\n     - Linux: `${XDG_STATE_HOME:-~/.local/state}/dotfiles-manager/dotfiles-manager.log`\n   - `--log-file \u003cpath\u003e` overrides the destination path\n   - logs are always human-readable text (no log format option)\n\n8. **Logging level**\n   - default log level is `info`\n   - set `--log-level \u003cdebug|info|warn|error\u003e` for verbosity control\n\n9. **stderr behavior**\n   - warnings and errors are emitted as human-readable diagnostics on stderr\n   - command output remains on stdout\n\n---\n\n## Quick start\n\n1) Create config file in your project root:\n\n```yaml\n# .dotfiles-manager.yaml\nsyncs:\n  - target: .config/nvim\n    source: .config/nvim\n  - target: ./\n    source: ./global\n  - target: ./\n    source: \"./$HOSTNAME/$USER\"\n    on:\n      deploy:\n        remove-unmanaged:\n          - '**/*.bak'\n      import:\n        add-unmanaged:\n          include:\n            - '**'\n          exclude:\n            - '**/*.tmp'\n        remove-missing:\n          include:\n            - 'lua/**'\n```\n\n2) Run commands (using default config discovery in current directory):\n\n```bash\ndotfiles-manager --version\ndotfiles-manager status\ndotfiles-manager diff ~/.config/nvim\ndotfiles-manager deploy --dry-run ~/.config/nvim\ndotfiles-manager deploy ~/.config/nvim\ndotfiles-manager import --dry-run ~/.config/nvim\ndotfiles-manager import ~/.config/nvim\n```\n\n`--version`/`version` prints `dotfiles-manager version \u003cvalue\u003e` and exits (`dev` on local non-release builds).\n\n3) Optional explicit override:\n\n```bash\ndotfiles-manager --config ./custom-config.yaml status\n```\n\n---\n\n## Example workflow\n\nUse path-scoped deploy for only `nvim/lua`:\n\n```bash\ndotfiles-manager deploy --dry-run ~/.config/nvim/lua\ndotfiles-manager deploy ~/.config/nvim/lua\n```\n\nUse JSON for automation:\n\n```bash\ndotfiles-manager status --json ~/.config/nvim\ndotfiles-manager diff --json --direction deploy ~/.config/nvim\n```\n\n---\n\n## Documentation map\n\n- `docs/README.md` — full docs map (audience + scope levels)\n- `docs/internal/README.md` — canonical internal specs/contracts/engineering docs\n- `docs/user/README.md` — user-facing usage docs\n- `docs/internal/contracts/config-schema.json` — JSON Schema for `.dotfiles-manager.yaml`\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fshpoont%2Fdotfiles-manager","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fshpoont%2Fdotfiles-manager","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fshpoont%2Fdotfiles-manager/lists"}