Skip to main content

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:

  1. cargo release patch --execute on main
  2. git-cliff generates CHANGELOG.md, cargo-release commits and tags
  3. cargo-dist builds binaries for macOS (aarch64 + x86_64), Linux (x86_64), and Windows (x86_64)
  4. GitHub Release is created with shell/PowerShell installers
  5. PyPI thin-wrapper package is published via OIDC trusted publishing

Contributing

  1. Fork the repository
  2. Create a feature branch from main
  3. Open a pull request — CI runs cargo fmt, cargo clippy, and cargo 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)

Source distribution for profilectl 0.1.5
File Size Uploaded
profilectl-0.1.5.tar.gz 3.0 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for profilectl 0.1.5
File Interpreter ABI Platform
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 log

Release 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

Release history Release notifications | RSS feed

This release

0.1.5 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page