Metadata-Version: 2.4
Name: asprofile
Version: 0.2.1
Summary: Switch tool identity (git, gh, ssh, env) per shell window.
License-Expression: Apache-2.0
License-File: LICENSE
License-File: NOTICE
Requires-Python: >=3.11
Provides-Extra: dev
Requires-Dist: pytest>=8; extra == 'dev'
Requires-Dist: ruff>=0.6; extra == 'dev'
Description-Content-Type: text/markdown

# 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:

```sh
uv tool install asprofile
```

Other options:

```sh
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:

```sh
asprofile init
exec "$SHELL"
```

Create a profile:

```sh
asprofile add work \
  --name "Ada Lovelace" \
  --email "ada@bigcorp.example" \
  --ssh-key ~/.ssh/id_work \
  --gh ada-bigcorp
```

Use it in the current shell:

```sh
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:

```sh
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:

```sh
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

```sh
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:

```toml
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:

```sh
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:

```sh
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:

```sh
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:

```sh
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`:

```bash
PS1='[${ASP_PROFILE:-none}] '"$PS1"
```

For `zsh`:

```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:

```sh
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:

```sh
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](LICENSE) for the full
text and [NOTICE](NOTICE) for attribution requirements. Source files carry SPDX
headers (`SPDX-License-Identifier: Apache-2.0`).
