asprofile
Switch Git, SSH, GitHub CLI, and custom environment identity per shell window.
asprofile lets you keep separate work, personal, client, or automation identities
active in different terminals at the same time. It does this by generating shell
snippets from small TOML profile declarations and sourcing those snippets into only
the shell you choose.
No global Git config is changed. No shared "current profile" file is written. No other terminal is affected.
Why use it?
If you use more than one identity on the same machine, you often need several things to change together:
| Concern | What asprofile sets |
|---|---|
| Git author and committer | GIT_AUTHOR_*, GIT_COMMITTER_* |
| Git SSH key | GIT_SSH_COMMAND |
| GitHub CLI account | GH_CONFIG_DIR |
| Other per-identity tools | variables from the profile's [env] table |
Because those values live in the current process environment, one terminal can commit
and push as work while another terminal commits and pushes as personal.
Install
Install asprofile as a command-line tool:
uv tool install asprofile
Other options:
pipx install asprofile
python -m pip install --user asprofile
asprofile requires Python 3.11 or newer and supports zsh and bash.
Quickstart
Install the shell integration once:
asprofile init
exec "$SHELL"
Create a profile:
asprofile add work \
--name "Ada Lovelace" \
--email "ada@bigcorp.example" \
--ssh-key ~/.ssh/id_work \
--gh ada-bigcorp
Use it in the current shell:
asprofile use work
asprofile current
From this shell, Git commits use Ada's author and committer identity, Git SSH
operations use ~/.ssh/id_work, and gh uses an isolated config directory for the
ada-bigcorp account.
To return the shell to a clean state:
asprofile unuse
GitHub CLI login
SSH and GitHub CLI authentication are separate.
--ssh-keycontrols the key Git uses for SSH remotes throughGIT_SSH_COMMAND.--ghnames an isolatedghconfig directory throughGH_CONFIG_DIR.
After creating a profile with --gh, log in once for that profile:
asprofile gh-login work
That runs gh auth login with the profile's isolated GH_CONFIG_DIR. asprofile
does not read, copy, or store GitHub tokens.
Commands
asprofile init [shell] install shell integration for zsh or bash
asprofile add <profile> --name N --email E [--ssh-key PATH] [--gh ACCOUNT]
asprofile list list profiles; marks the active one with *
asprofile use <profile> activate a profile in the current shell
asprofile unuse clear the active profile from the current shell
asprofile current show the active profile and identity
asprofile exec <profile> -- <cmd> run one command under a profile
asprofile edit <profile> edit a profile TOML, then regenerate it
asprofile regen [profile] regenerate one profile, or all profiles
asprofile gh-login <profile> run gh auth login for a profile
asprofile remove <profile> delete a profile declaration and generated snippets
asprofile uninstall remove the shell integration block
asprofile --version
use and unuse are shell functions installed by asprofile init, because they
must modify the current shell. All other commands are regular CLI subcommands.
Profile files
A profile has two files:
~/.asprofile/profiles/<profile>.tomlis the declaration you edit.~/.asprofile/generated/<profile>.{zsh,bash}is generated and sourced byasprofile use.
asprofile add writes both files. If you edit or create a TOML file by hand, run
asprofile regen <profile> before using it.
Example profile:
name = "Ada Lovelace"
email = "ada@bigcorp.example"
ssh_key = "~/.ssh/id_work" # optional
gh = "ada-bigcorp" # optional
[env] # optional
SOME_TOKEN_DIR = "$HOME/.asprofile/sometool/work"
The generated shell snippet exports values like these:
export GIT_AUTHOR_NAME="Ada Lovelace"
export GIT_AUTHOR_EMAIL="ada@bigcorp.example"
export GIT_COMMITTER_NAME="Ada Lovelace"
export GIT_COMMITTER_EMAIL="ada@bigcorp.example"
export GIT_SSH_COMMAND="ssh -i $HOME/.ssh/id_work -o IdentitiesOnly=yes"
export GH_CONFIG_DIR="${ASP_HOME:-$HOME/.asprofile}/gh/ada-bigcorp"
export ASP_PROFILE="work"
ASP_HOME defaults to ~/.asprofile. Set it before running asprofile if you want
profiles and generated snippets stored somewhere else.
Editing profiles
Use edit for the common path:
asprofile edit work
It opens the profile declaration in $EDITOR and regenerates the shell snippets when
the editor exits.
Use regen when the TOML has already changed:
asprofile regen work # regenerate one profile
asprofile regen # regenerate every profile
One-shot commands
Use exec when you want a single command to run under a profile without switching
the current shell:
asprofile exec work -- git push
asprofile exec personal -- gh repo list
Prompt integration
asprofile use exports ASP_PROFILE, but it does not modify your prompt. Add it
yourself if you want a visible reminder.
For bash:
PS1='[${ASP_PROFILE:-none}] '"$PS1"
For zsh:
setopt prompt_subst
PROMPT='[${ASP_PROFILE:-none}] '$PROMPT
Validation rules
Profile names and gh labels are intentionally conservative: use letters, digits,
_, and -.
ssh_key is a path reference only. It may contain letters, digits, ., _, -, /,
and ~. A leading ~ is rewritten to $HOME in generated shell snippets.
Values in [env] may use simple $NAME references, such as $HOME, but not command
substitutions, ${...} expansions, quotes, backticks, backslashes, control
characters, or multiline values. This keeps generated snippets safe to source and
keeps asprofile use and asprofile exec behavior consistent.
Security model
asprofile usechanges only the current shell environment.- Git identity is set through environment variables, not global Git config.
- SSH keys are referenced by path only; they are never copied or logged.
- GitHub CLI tokens stay with
ghinside the profile's isolatedGH_CONFIG_DIR. ~/.asprofileand per-profileghdirectories are created with0700permissions.
Development
From a local clone:
python -m venv .venv
. .venv/bin/activate
python -m pip install -e ".[dev]"
The development extra installs the test and lint tools used by the project.
Uninstall
Remove the shell integration block from your shell rc file:
asprofile uninstall
This leaves ~/.asprofile in place so your profile declarations and isolated gh
config directories are not deleted unexpectedly.
License
Copyright 2026 Persydos AI LLC.
Licensed under the Apache License, Version 2.0. See LICENSE for the full
text and NOTICE for attribution requirements. Source files carry SPDX
headers (SPDX-License-Identifier: Apache-2.0).
Metadata
Release files for asprofile 0.2.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| asprofile-0.2.1.tar.gz | 17.9 kB | Without provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| asprofile-0.2.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 35.9 kB
Release files / asprofile-0.2.1.tar.gz
| Download URL | asprofile-0.2.1.tar.gz |
|---|---|
| Size | 17.9 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
1f646186e03e737482260203dd93975e2bc4159316ee5efbffe080c04e909260
|
|
BLAKE2b-256 checksum How to use checksums |
e720d0a23005005631bcd9fdbe4d3b649c8c45851027931b028ce11c4b6bdf59
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.11.15
|
Release files / asprofile-0.2.1-py3-none-any.whl
| Download URL | asprofile-0.2.1-py3-none-any.whl |
|---|---|
| Size | 18.0 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
a5aed2d4aad46ffa0c244b3bbb3440e8ecc6151f9d00f5ed22805acea3c1fcc2
|
|
BLAKE2b-256 checksum How to use checksums |
59237f099ad1f9460a922e2c6adc7f94ba8392f8670a14cbcd92fc350e092757
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.11.15
|
Security for asprofile 0.2.1
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.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.