Switch tool identity (git, gh, ssh, env) per shell window.
Project description
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).
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file asprofile-0.2.1.tar.gz.
File metadata
- Download URL: asprofile-0.2.1.tar.gz
- Upload date:
- Size: 17.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.15
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
1f646186e03e737482260203dd93975e2bc4159316ee5efbffe080c04e909260
|
|
| MD5 |
8eaa9158c15e6b9d9ba68ba42e08b284
|
|
| BLAKE2b-256 |
e720d0a23005005631bcd9fdbe4d3b649c8c45851027931b028ce11c4b6bdf59
|
File details
Details for the file asprofile-0.2.1-py3-none-any.whl.
File metadata
- Download URL: asprofile-0.2.1-py3-none-any.whl
- Upload date:
- Size: 18.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.15
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a5aed2d4aad46ffa0c244b3bbb3440e8ecc6151f9d00f5ed22805acea3c1fcc2
|
|
| MD5 |
3c70e650363eab189de47504df0eabdd
|
|
| BLAKE2b-256 |
59237f099ad1f9460a922e2c6adc7f94ba8392f8670a14cbcd92fc350e092757
|