{"id":17460960,"url":"https://github.com/pablopunk/dot","last_synced_at":"2026-04-15T10:03:58.847Z","repository":{"id":258222291,"uuid":"870103329","full_name":"pablopunk/dot","owner":"pablopunk","description":"Manage your apps, dotfiles, preferences, and their dependencies automagically","archived":false,"fork":false,"pushed_at":"2025-02-19T21:52:02.000Z","size":99,"stargazers_count":4,"open_issues_count":1,"forks_count":1,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-04-05T08:34:27.773Z","etag":null,"topics":["automagically","brew","dependencies","dotfiles","homebrew","install","linux","mac","magic"],"latest_commit_sha":null,"homepage":"","language":"Lua","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/pablopunk.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}},"created_at":"2024-10-09T12:57:07.000Z","updated_at":"2025-02-24T20:21:12.000Z","dependencies_parsed_at":"2024-10-20T13:29:56.718Z","dependency_job_id":"f16fd288-a34f-4e96-996b-d0694dae3200","html_url":"https://github.com/pablopunk/dot","commit_stats":{"total_commits":67,"total_committers":1,"mean_commits":67.0,"dds":0.0,"last_synced_commit":"4126fd31276bbd27f7ca369ca49381a9338a1364"},"previous_names":["pablopunk/dot"],"tags_count":17,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pablopunk%2Fdot","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pablopunk%2Fdot/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pablopunk%2Fdot/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pablopunk%2Fdot/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/pablopunk","download_url":"https://codeload.github.com/pablopunk/dot/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248088411,"owners_count":21045709,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","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":["automagically","brew","dependencies","dotfiles","homebrew","install","linux","mac","magic"],"created_at":"2024-10-18T06:08:11.561Z","updated_at":"2026-04-15T10:03:58.836Z","avatar_url":"https://github.com/pablopunk.png","language":"Lua","funding_links":[],"categories":[],"sub_categories":[],"readme":"# dot - all your computers in one repo\n\n\u003e All your tools, apps, and configs with 0 dependencies\n\n## Highlights ✨\n\n- **Zero Dependencies**: Single compiled binary with no external requirements.\n- **Cross-Platform**: Works on macOS and Linux.\n- **Profile-Based**: Organize configurations for different machine types (work, laptop, etc.)\n- **Install anything**: Run any shell command for installation - brew, apt, dnf, wget, curl, anything!\n- **Idempotent**: Run it twice and you'll see.\n- **macOS Preferences**: Yes! You can import/export GUI apps settings.\n\n## Installation 🚀\n\nInstall with a single command:\n\n```bash\ncurl -fsSL https://raw.githubusercontent.com/pablopunk/dot/main/scripts/install.sh | bash\n```\n\nThis will:\n- Download the latest release for your platform\n- Install to `~/.local/bin/dot`\n- Update your shell profile to include `~/.local/bin` in PATH\n\n## Quick Start\n\n1. Create a `dot.yaml` file in your dotfiles repository:\n\n```yaml\nprofiles:\n  \"*\":        # Always installed on every machine\n    - bash\n    - git\n  \n  work:       # Only on your work computer\n    - vpn\n    - ssh\n\nconfig:\n  bash:\n    link:\n      \"bash/.bashrc\": \"~/.bashrc\"\n      \"bash/.bash_profile\": \"~/.bash_profile\"\n  \n  git:\n    link:\n      \"git/.gitconfig\": \"~/.gitconfig\"\n    install:\n      brew: \"brew install git\"\n      apt: \"apt install -y git\"\n  \n  vpn:\n    install:\n      brew: \"brew install --cask viscosity\"\n      apt: \"apt install -y openvpn\"\n  \n  ssh:\n    link:\n      \"ssh/config\": \"~/.ssh/config\"\n```\n\n2. Run dot to install the default profile:\n\n```bash\ndot\n```\n\n3. Install a specific profile:\n\n```bash\ndot work\n```\n\n**Note:** Profiles are additive. Running `dot work` adds the `work` profile to your active profiles (it doesn't replace existing ones). All active profiles are applied on every run.\n\n4. Install multiple profiles at once:\n\n```bash\ndot work laptop\n```\n\nBoth `work` and `laptop` profiles will be active and merged with the default `*` profile.\n\n## Configuration\n\n### Profile Structure\n\nProfiles are simple lists of tool names. Each tool is configured in the `config` section:\n\n```yaml\nprofiles:\n  \"*\":              # Always installed (special profile)\n    - git\n    - vim\n    - zsh\n  \n  work:             # Named profile (installed when requested)\n    - docker\n    - slack\n  \n  gui:\n    - apps          # Can reference nested config containers\n\nconfig:\n  git:              # Tool configuration\n    install:        # Installation commands (any shell command)\n      brew: \"brew install git\"\n      apt: \"apt install -y git\"\n      wget: \"wget https://example.com/git.zip -O /Applications/git.zip\"\n    uninstall:      # Optional uninstall commands\n      brew: \"brew uninstall git\"\n      apt: \"apt remove -y git\"\n    link:           # File/directory linking\n      \"source/path\": \"~/target/path\"\n    postinstall:    # Run after successful installation\n      \"echo 'Installed successfully'\"\n    postlink:       # Run after successful linking\n      \"echo 'Linked successfully'\"\n    os: [\"mac\"]     # OS restrictions (mac/darwin, linux)\n    defaults:       # macOS system defaults (macOS only)\n      \"com.apple.dock\": \"macos/dock.plist\"\n  \n  vim:\n    link:\n      \"vim/.vimrc\": \"~/.vimrc\"\n      \"vim/.vim/\": \"~/.vim/\"\n  \n  zsh:\n    install:\n      brew: \"brew install zsh\"\n      apt: \"apt install -y zsh\"\n  \n  docker:\n    install:\n      brew: \"brew install docker\"\n      apt: \"apt install -y docker.io\"\n    postinstall: \"sudo usermod -aG docker $USER\"\n  \n  slack:\n    os: [\"mac\"]\n    install:\n      brew: \"brew install slack\"\n```\n\n### Special Profiles\n\n- `\"*\"`: Always installed on every machine\n- Named profiles (e.g., `work`, `laptop`, `rice`): Only installed on machines where they apply\n- **Profiles are additive**: Running `dot work` adds `work` to your active profiles. Existing profiles remain active.\n- You can pass multiple profiles at once (e.g., `dot work laptop`). The `*` profile is always included.\n- You can also use profiles with fuzzy search: `dot work git` (installs all tools in `*` and `work` profiles, plus any tool matching \"git\")\n- Use `--rm \u003cprofile\u003e` or `--remove-profile \u003cprofile\u003e` to remove a profile from the active set\n\n\n### OS Restrictions\n\nRestrict tools to specific operating systems:\n\n```yaml\nprofiles:\n  \"*\":\n    - mac_only\n    - linux_only\n    - cross_platform\n\nconfig:\n  mac_only:\n    os: [\"mac\"]     # or [\"darwin\"]\n    install:\n      brew: \"brew install --cask app\"\n\n  linux_only:\n    os: [\"linux\"]\n    install:\n      apt: \"apt install -y package\"\n\n  cross_platform:\n    # No OS restriction - installs everywhere\n    install:\n      brew: \"brew install tool\"\n      apt: \"apt install -y tool\"\n```\n\n### Multiple Link Destinations\n\nLink the same source file to multiple destinations (useful for monorepos or shared configs):\n\n```yaml\nconfig:\n  shared-configs:\n    os: [\"mac\"]\n    link:\n      # Old format still works (single destination)\n      \"./config/shared/settings.json\": \"~/.config/settings.json\"\n      \n      # New format for multiple destinations\n      \"./config/shared/.eslintrc\":\n        - \"~/project-a/.eslintrc\"\n        - \"~/project-b/.eslintrc\"\n        - \"~/project-c/.eslintrc\"\n```\n\nBoth formats can be mixed in the same component. The old format (`source: dest`) is automatically converted to a single-item array for backward compatibility.\n\n### Advanced Features\n\n#### Nested Configs\n\nOrganize tools in nested structures for better readability:\n\n```yaml\nprofiles:\n  \"*\":\n    - cli      # References a nested config container\n  \n  gui:\n    - apps     # References another nested config container\n\nconfig:\n  cli:         # Container with shell tools\n    bash:\n      install: {...}\n    zsh:\n      install: {...}\n    git:\n      install: {...}\n  \n  apps:        # Container with GUI applications\n    slack:\n      install: {...}\n    docker:\n      install: {...}\n    chrome:\n      install: {...}\n```\n\nWhen you run `dot gui`, it will install all tools from: `*` + `gui` profiles, automatically expanding `cli` and `apps` containers.\n\n#### Fuzzy Search\n\nInstall specific tools by name without specifying profiles:\n\n```bash\n# Install any tool matching \"git\"\ndot git\n\n# Install tools matching multiple terms\ndot git vim\n\n# Mix profiles and fuzzy search\ndot work git    # Installs from *, work profiles, plus any tool matching \"git\"\n```\n\n## Usage\n\n### Basic Commands\n\n```bash\n# Install default profile\ndot\n\n# Install specific profiles\ndot work laptop\n\n# List available profiles\ndot --profiles\n\n# Preview changes without applying\ndot --dry-run work\n\n# Force reinstall everything\ndot --install\n\n# Uninstall removed components\ndot --uninstall\n\n# Verbose output\ndot -v work\n```\n\n### Advanced Usage\n\n```bash\n# Fuzzy search for components\ndot git     # Installs any component matching \"git\"\n\n# Remove a profile from active set\ndot --rm work\n# or\ndot --remove-profile work\n\n# Run hooks independently\ndot --postinstall       # Run only postinstall hooks\ndot --postlink          # Run only postlink hooks\n\n# Link config files only (skip installs/defaults/hooks)\ndot --link\n\n# macOS defaults management\ndot --defaults-export   # Export current settings to plist/XML files\ndot --defaults-import   # Import settings from plist/XML files\n\n# Upgrade dot itself\ndot --upgrade\n```\n\n## Install Commands\n\ndot can run any shell command for installation. It automatically detects which commands are available on your system and runs the first available one.\n\nYou can use any command for installation:\n\n```yaml\nprofiles:\n  \"*\":\n    # Package managers\n    node:\n      install:\n        brew: \"brew install node\"\n        apt: \"apt install -y nodejs npm\"\n        yum: \"yum install -y nodejs npm\"\n\n    # Direct downloads\n    1piece:\n      os: [\"mac\"]\n      install:\n        wget: \"wget https://app1piece.com/1Piece-4.2.1.zip -O /Applications/1Piece.app\"\n        curl: \"curl -L https://app1piece.com/1Piece-4.2.1.zip -o /Applications/1Piece.app\"\n\n    # Custom scripts\n    custom_tool:\n      install:\n        bash: \"./scripts/install-my-tool.sh\"\n        python: \"python setup.py install\"\n```\n\nThe tool will check if each command exists (using `which`) and run the first available one.\n\n## Hooks\n\nRun custom commands after installation or linking:\n\n```yaml\nprofiles:\n  \"*\":\n    tmux:\n      install:\n        brew: \"brew install tmux\"\n      postinstall: |\n        echo \"Setting up tmux...\"\n        tmux new-session -d -s setup\n\n    vim:\n      link:\n        \"vim/.vimrc\": \"~/.vimrc\"\n        \"vim/.vim\": \"~/.vim\"\n      postlink: |\n        echo \"Installing vim plugins...\"\n        vim +PlugInstall +qall\n```\n\n### Hook Types\n\n- **`postinstall`**: Runs only if package installation was executed and succeeded in the current run\n- **`postlink`**: Runs only if symlink creation was performed and succeeded in the current run\n- **`--link` CLI mode**: Creates/updates symlinks only, skipping package installs, defaults checks/imports, and hooks\n\n### Running Hooks Independently\n\nYou can run hooks without performing full installation:\n\n```bash\n# Run only postinstall hooks\ndot --postinstall\n\n# Run only postlink hooks\ndot --postlink\n\n# Run hooks for specific components\ndot git --postinstall    # Run postinstall for git component\ndot vim --postlink       # Run postlink for vim component\n\n# Run hooks with dry-run to see what would execute\ndot --postinstall --dry-run -v\n\n# Run hooks for specific profiles\ndot work --postinstall   # Run postinstall hooks for work profile\n```\n\nThis is useful for:\n- **Testing hooks** during development\n- **Re-running configuration** after manual changes\n- **Debugging hook failures** without full reinstalls\n- **Updating configs** without reinstalling packages\n\n## macOS Defaults\n\nManage macOS system preferences with plist or XML files:\n\n```yaml\nprofiles:\n  \"*\":\n    dock:\n      defaults:\n        \"com.apple.dock\": \"macos/dock.plist\"\n        \"com.apple.finder\": \"macos/finder.xml\"        # XML format for better readability\n```\n\nCommands:\n- `dot --defaults-export`: Export current settings to plist/XML files\n- `dot --defaults-import`: Import settings from plist/XML files\n- Normal runs will warn if current settings differ from saved files\n\nFiles ending in `.xml` are exported as XML format for better readability and version control.\n\n## State Management\n\ndot maintains a state file at `~/.local/state/dot/lock.yaml` to track:\n- Installed components and their package managers\n- Active profiles\n- Link mappings\n- Hook execution status\n- Install commands used for each component\n- Uninstall commands for removed components\n\nThis enables:\n- **Incremental updates**: Only install/link what's changed\n- **Automatic cleanup**: Remove components deleted from config\n- **State persistence**: Remember active profiles across runs (profiles are additive)\n- **Efficient linking**: Skip symlinks that already exist and point correctly\n- **Smart uninstalls**: Run uninstall commands for components removed from config\n\nProfiles accumulate over time. To see active profiles, run `dot --profiles`. To remove a profile, use `dot --rm \u003cprofile\u003e`.\n\n## Examples\n\n### Basic Development Setup\n\n```yaml\nprofiles:\n  \"*\":\n    - shell\n    - git\n    - vim\n\nconfig:\n  shell:\n    link:\n      \"shell/.bashrc\": \"~/.bashrc\"\n      \"shell/.zshrc\": \"~/.zshrc\"\n\n  git:\n    link:\n      \"git/.gitconfig\": \"~/.gitconfig\"\n    install:\n      brew: \"brew install git\"\n      apt: \"apt install -y git\"\n\n  vim:\n    link:\n      \"vim/.vimrc\": \"~/.vimrc\"\n    install:\n      brew: \"brew install vim\"\n      apt: \"apt install -y vim\"\n```\n\n### Work Machine Profile\n\n```yaml\nprofiles:\n  work:\n    - docker\n    - vpn\n    - kubectl\n\nconfig:\n  docker:\n    install:\n      brew: \"brew install docker\"\n      apt: \"apt install -y docker.io\"\n    postinstall: \"sudo usermod -aG docker $USER\"\n\n  vpn:\n    install:\n      brew: \"brew install --cask viscosity\"\n      apt: \"apt install -y openvpn\"\n    link:\n      \"work/vpn.conf\": \"~/.config/vpn/client.conf\"\n\n  kubectl:\n    install:\n      brew: \"brew install kubectl\"\n      curl: \"curl -LO https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl \u0026\u0026 chmod +x kubectl \u0026\u0026 sudo mv kubectl /usr/local/bin/\"\n```\n\n### Laptop-Specific Tools\n\n```yaml\nprofiles:\n  laptop:\n    - battery\n    - wifi\n\nconfig:\n  battery:\n    os: [\"mac\"]\n    install:\n      brew: \"brew install --cask battery-guardian\"\n\n  wifi:\n    os: [\"linux\"]\n    install:\n      apt: \"apt install -y network-manager\"\n```\n\n## Building from Source\n\nRequirements:\n- Go 1.21 or later\n\n```bash\n# Clone the repository\ngit clone https://github.com/pablopunk/dot.git\ncd dot\n\n# Build for current platform\nmake build\n\n# Build for all platforms\nmake build-all\n\n# Run tests\nmake test\n\n# Install locally\nmake install\n```\n\n## Contributing\n\n1. Fork the repository\n2. Create a feature branch: `git checkout -b feature-name`\n3. Make your changes and add tests\n4. Run tests: `make test`\n5. Submit a pull request\n\n## License\n\nMIT License - see [LICENSE](LICENSE) file for details.\n\n## Comparison with Other Tools\n\n| Feature | dot | GNU Stow | chezmoi | dotbot |\n|---------|-----|----------|---------|--------|\n| Zero dependencies | ✅ | ❌ | ❌ | ❌ |\n| Single binary | ✅ | ❌ | ✅ | ❌ |\n| Package installation | ✅ | ❌ | ✅ | ✅ |\n| Cross-platform | ✅ | ✅ | ✅ | ✅ |\n| Profile-based | ✅ | ❌ | ✅ | ❌ |\n| State tracking | ✅ | ❌ | ✅ | ❌ |\n| Dry run | ✅ | ✅ | ✅ | ❌ |\n\n---\n\n**dot** - Simple, fast, and reliable dotfiles management.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpablopunk%2Fdot","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpablopunk%2Fdot","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpablopunk%2Fdot/lists"}