Skip to main content

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-key controls the key Git uses for SSH remotes through GIT_SSH_COMMAND.
  • --gh names an isolated gh config directory through GH_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>.toml is the declaration you edit.
  • ~/.asprofile/generated/<profile>.{zsh,bash} is generated and sourced by asprofile 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 use changes 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 gh inside the profile's isolated GH_CONFIG_DIR.
  • ~/.asprofile and per-profile gh directories are created with 0700 permissions.

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


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

asprofile-0.2.1.tar.gz (17.9 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

asprofile-0.2.1-py3-none-any.whl (18.0 kB view details)

Uploaded Python 3

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

Hashes for asprofile-0.2.1.tar.gz
Algorithm Hash digest
SHA256 1f646186e03e737482260203dd93975e2bc4159316ee5efbffe080c04e909260
MD5 8eaa9158c15e6b9d9ba68ba42e08b284
BLAKE2b-256 e720d0a23005005631bcd9fdbe4d3b649c8c45851027931b028ce11c4b6bdf59

See more details on using hashes here.

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

Hashes for asprofile-0.2.1-py3-none-any.whl
Algorithm Hash digest
SHA256 a5aed2d4aad46ffa0c244b3bbb3440e8ecc6151f9d00f5ed22805acea3c1fcc2
MD5 3c70e650363eab189de47504df0eabdd
BLAKE2b-256 59237f099ad1f9460a922e2c6adc7f94ba8392f8670a14cbcd92fc350e092757

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page