profilectl
Cross-platform dotfiles automation for macOS, Linux, and Windows, powered by Rust.
Manage your development environment through profiles — declarative TOML files that describe your symlinks, tools, and environment per machine. Works as a direct CLI or an interactive TUI.
Quick Start
Install via cargo
cargo install profilectl
Install via shell script (macOS/Linux)
curl --proto '=https' --tlsv1.2 -LsSf https://github.com/carlosferreyra/profilectl/releases/latest/download/profilectl-installer.sh | sh
Install via PowerShell (Windows)
powershell -ExecutionPolicy ByPass -c "irm https://github.com/carlosferreyra/profilectl/releases/latest/download/profilectl-installer.ps1 | iex"
Usage
Interactive mode (no arguments)
profilectl
Launches a guided TUI to select a profile, preview changes, and apply them.
CLI subcommands
profilectl sync Apply the active profile (links + tools)
profilectl install Install declared tools via the appropriate package manager
profilectl link Create symlinks defined in the profile
profilectl unlink Remove managed symlinks
profilectl scan Detect installed tools and compare against the profile
profilectl diff Show what would change if the profile were applied
profilectl check Verify all symlinks and tools are in the expected state
profilectl profiles List available profiles
profilectl status Show current profile and system state
Selecting a profile
profilectl --profile work sync
Or set the environment variable:
export PCTL_PROFILE=work
profilectl sync
Profiles
Profiles live in profiles/<name>.toml and describe what a machine should look like:
name = "default"
[[links]]
src = "config/zsh/.zshrc"
dst = "~/.zshrc"
[[links]]
src = "config/git/.gitconfig"
dst = "~/.gitconfig"
[tools]
brew = ["starship", "ripgrep", "bat", "eza"]
cargo = ["cargo-nextest"]
Profiles support inheritance via extends:
name = "work"
extends = "default"
[[links]]
src = "config/zsh/.zshrc.work"
dst = "~/.zshrc"
[tools]
brew = ["awscli", "terraform"]
The work profile inherits all links and tools from default, then adds or overrides its own.
Project Structure
dotfiles/
├── profiles/
│ └── default.toml # Default profile (symlinks + tools)
├── config/
│ ├── zsh/ # Zsh config files
│ ├── git/ # Git config files
│ └── shell/ # Starship prompt config
├── crates/
│ ├── profilectl/ # Binary entry point
│ ├── profilectl-cli/ # Clap subcommands
│ ├── profilectl-config/ # Profile schema and loader
│ ├── profilectl-interactive/ # Inquire TUI
│ └── profilectl-types/ # Shared types and errors
├── scripts/
│ └── release_pypi.py # PyPI thin-wrapper publish script
└── Cargo.toml # Workspace root
See crates/README.md for a description of each crate.
Release Pipeline
Releases are fully automated:
cargo release patch --executeonmain- git-cliff generates
CHANGELOG.md, cargo-release commits and tags - cargo-dist builds binaries for macOS (aarch64 + x86_64), Linux (x86_64), and Windows (x86_64)
- GitHub Release is created with shell/PowerShell installers
- PyPI thin-wrapper package is published via OIDC trusted publishing
Contributing
- Fork the repository
- Create a feature branch from
main - Open a pull request — CI runs
cargo fmt,cargo clippy, andcargo test
License
MIT — see LICENSE.
Made with ❤️ by Carlos Ferreyra
Metadata
Release files for profilectl 0.1.5
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| profilectl-0.1.5.tar.gz | 3.0 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| profilectl-0.1.5-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 6.9 kB
Release files / profilectl-0.1.5.tar.gz
| Download URL | profilectl-0.1.5.tar.gz |
|---|---|
| Size | 3.0 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
fd69351b29c82491ec67e755aa671a0b5cdae6d2a561e38ebfa94efce28837c4
|
|
BLAKE2b-256 checksum How to use checksums |
8ed855af2aa37ec94ce03dc479605a8f0186261d68c511484310230e96f7b655
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Apr 24, 2026.
Transparency logRelease files / profilectl-0.1.5-py3-none-any.whl
| Download URL | profilectl-0.1.5-py3-none-any.whl |
|---|---|
| Size | 3.9 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
2a66f5615292bf4d8b033980ce04550e49c77d6e796c44ee62def00c97d937cf
|
|
BLAKE2b-256 checksum How to use checksums |
491ee2ccd7fdf3629a97af27e280d44b475ffe97d8aaef1fb0af0ac81cae6b71
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Apr 24, 2026.
Transparency log