# acct command reference

> Directory-scoped GitHub identity and auth. One folder. One GitHub account. One identity. No leaks.

- Human docs: https://acct-web.vercel.app/docs
- This file: https://acct-web.vercel.app/docs.md
- npm package: `acct-sh`
- CLI binary: `acct` (also installs `git-credential-acct`)
- Repo: https://github.com/abdull-ah-med/acct

Official `gh` documents automatic switching by directory as out of scope. acct owns that gap.

Do not confuse acct with `gh auth switch` (global), git `user.name`/`user.email` alone (identity ≠ auth), or GitHub Apps.

## Install

```bash
npm install -g acct-sh
acct
```

Bare `acct` prints the tip sheet. Then:

```bash
acct init \
  --id work \
  --user your-work-user \
  --email you@company.com \
  --name "Your Name" \
  --bind ~/Work

eval "$(acct hook zsh)"
```

`--import-gh` is optional on init. HTTPS and `acct exec` follow `gh auth token --user` for that profile. Use `--import-gh` to seed the keychain immediately, or `--stdin` for a PAT that must not track gh.

## Resolution order

How cwd picks an account. Local always wins. Ambient `ACCT_PROFILE` does not override git HTTPS or hooks.

1. **CLI --profile** — Explicit, process-local. Affects gh / status / exec. Does not rebind git HTTPS.
2. **Nearest .acct** — Walks up from cwd. An empty profile in that file means unbound and wins over parent bindings.
3. **Longest binding** — Directory trees from acct bind / init. More specific paths beat broader ones.
4. **Unbound** — No acct identity. Strict mode blocks managed ops instead of guessing.

Repo-local `.acct` is YAML `{ profile: work }`. An empty `profile` means this tree is unbound, even inside a bound parent.

## Start

Install the package, then run bare acct for the tip sheet.

### `acct`

`acct [--help] [--version]`

With no arguments, prints the welcome tip sheet (npm hides postinstall output). Use --help for the full command list.

```bash
npm install -g acct-sh
acct
acct --help
```

### `acct init`

`acct init --id <id> --user <githubUser> --email <email> --name <name> [options]`

Create a profile, bind a directory tree, wire includeIf identity, and install enforce hooks. This is the usual first command after install.

```bash
acct init \
  --id work \
  --user your-work-user \
  --email you@company.com \
  --name "Your Name" \
  --bind ~/Work
```

Flags:

- `--id <id>` (required): Profile id, e.g. work or personal.
- `--user <githubUser>` (required): GitHub username for this profile.
- `--email <email>` (required): Commit email (user.email).
- `--name <name>` (required): Commit name (user.name).
- `--host <host>`: GitHub host. Default github.com.
- `--protocol <https|ssh>`: Preferred clone style. Default https.
- `--bind <dir>`: Directory tree to bind. Default: current directory.
- `--import-gh`: Seed the OS keychain from gh auth token --user. Optional — HTTPS and acct exec already follow gh for that user.
- `--global-hooks`: Set core.hooksPath globally. Discouraged; replaces hooks in every repo.
- `--force`: Overwrite an existing non-acct core.hooksPath in the bind directory.

Notes:

- New profiles start in strict enforce mode.
- After init, add a shell hook so gh follows the directory on every cd.

## Profiles

A profile is one GitHub user, git identity, and credential set.

### `acct profile add`

`acct profile add --id <id> --user <githubUser> --email <email> --name <name> [options]`

Create a profile without binding a folder. Bind it afterwards with acct bind.

```bash
acct profile add \
  --id personal \
  --user you-home \
  --email you@home \
  --name "Your Name"
```

Flags:

- `--id <id>` (required): Profile id.
- `--user <githubUser>` (required): GitHub username.
- `--email <email>` (required): Commit email.
- `--name <name>` (required): Commit name.
- `--host <host>`: GitHub host. Default github.com.
- `--protocol <https|ssh>`: Preferred protocol. Default https.
- `--import-gh`: Import a token from gh into the OS keychain.

### `acct profile list`

`acct profile list`

Print every profile as id, user@host, email, and protocol.

```bash
acct profile list
```

### `acct profile show`

`acct profile show <id>`

Print one profile as JSON. Does not include the token.

```bash
acct profile show work
```

### `acct profile remove`

`acct profile remove <id>`

Delete the profile, its stored token, and includeIf artifacts. Bindings that pointed at it should be unbound first.

```bash
acct profile remove work
```

### `acct profile token`

`acct profile token <id> (--import-gh | --stdin)`

Store a token in the OS keychain. One of --import-gh or --stdin is required.

```bash
acct profile token work --import-gh
printf '%s' "$PAT" | acct profile token work --stdin
```

Flags:

- `--import-gh`: Import from gh auth token --user and keep following gh on refresh.
- `--stdin`: Read a PAT from stdin. Sets followGh: false so gh will not overwrite it.

Notes:

- Default path: HTTPS and acct exec follow gh auth token --user. After gh auth refresh you usually do not need --import-gh again.
- Use --stdin for a dedicated PAT that must not track gh.

### `acct profile ssh-key`

`acct profile ssh-key <id> (--generate | --path <path>) [--protocol https|ssh]`

Generate an ed25519 key for the profile, or attach an existing private key. HTTPS isolation stays installed unless you pass --protocol.

```bash
acct profile ssh-key work --generate
acct profile ssh-key work --path ~/.ssh/id_work
```

Flags:

- `--generate`: Create an ed25519 key. Defaults protocol to ssh.
- `--path <path>`: Attach an existing private key.
- `--protocol <https|ssh>`: Set preferred protocol. Generate defaults to ssh if omitted.

## Trees

Longest matching bound path wins. Leave the tree and that account stops applying.

### `acct bind`

`acct bind <dir> <profileId> [--enforce strict|warn|off]`

Map a directory tree to an existing profile and refresh includeIf rules.

```bash
acct bind ~/Personal personal
```

Flags:

- `--enforce <mode>`: Override enforce for this binding only: strict, warn, or off.

### `acct unbind`

`acct unbind <dir>`

Remove a directory → profile binding. The profile itself is kept.

```bash
acct unbind ~/Downloads
```

## Inspect

When something feels off, run these before changing config.

### `acct status`

`acct status [--profile <id>]`

Dump how cwd resolved: reason, binding, profile, identity, token presence, and the auth principal. If unhealthy, prints what is wrong, commands to run, and whether commit or push will go through. Exits 1 on error findings.

```bash
acct status
```

Flags:

- `--profile <id>`: Show this profile for the gh principal. Does not rebind git HTTPS — directory / .acct still win.

Notes:

- Ambient ACCT_PROFILE is ignored for git auth. A warning is printed if it disagrees with cwd.

### `acct whoami`

`acct whoami [--profile <id>]`

One line: expected GitHub user vs actual login vs commit email. Prints unbound outside a bound tree. Exits 1 on mismatch.

```bash
acct whoami
```

Flags:

- `--profile <id>`: Explicit profile for the gh plane.

### `acct doctor`

`acct doctor [--online]`

Scan credential-helper competition, missing install blocks, orphan bindings, sticky GH_TOKEN, enforce fallthrough, and keyring availability. Also diagnoses the cwd profile when unhealthy.

```bash
acct doctor
acct doctor --online
```

Flags:

- `--online`: Call gh api to verify ambient GH_TOKEN against the cwd profile.

### `acct ssh-test`

`acct ssh-test <id>`

Test SSH auth for a profile against github.com using that profile's key.

```bash
acct ssh-test work
```

## Run

Git HTTPS always follows the directory. These inject GH_TOKEN for gh only.

### `acct exec`

`acct exec [--profile <id>] [--allow-cross-profile] <command...>`

Run a command with the profile GH_TOKEN. Refuses gh auth switch / login / token because those mutate global gh state. Git HTTPS still follows cwd / .acct, not --profile.

```bash
acct exec gh pr list
acct exec --profile work --allow-cross-profile gh api user
```

Flags:

- `--profile <id>`: Inject this profile's token for gh. Does not rebind the git credential helper.
- `--allow-cross-profile`: Required when --profile differs from the cwd binding.

### `acct clone`

`acct clone <url> [dir] [--profile <id>]`

git clone with the cwd profile's GH_TOKEN in the environment. Git credentials still follow the directory binding.

```bash
acct clone https://github.com/org/repo.git
```

Flags:

- `--profile <id>`: Inject GH_TOKEN for helpers that honor it. Git still uses the cwd binding.

## Enforce

strict blocks, warn prints, off does nothing. Local always beats global.

### `acct enforce`

`acct enforce <strict|warn|off|on>`

Set the default enforcement mode. on is an alias for strict. A binding can override this with acct bind --enforce.

```bash
acct enforce strict
```

Notes:

- In strict, a missing profile token or mismatched gh principal blocks push.
- A commit still uses includeIf name/email, not gh. Raw gh without acct exec can still be the wrong user — that is the leak risk.

### `acct install`

`acct install [--global] [--force]`

Wire includeIf git identity and set core.hooksPath on the current repo (local by default).

```bash
acct install
```

Flags:

- `--global`: Set core.hooksPath globally. Discouraged; replaces hooks in every repo.
- `--force`: Overwrite an existing non-acct core.hooksPath in this repo.

### `acct uninstall`

`acct uninstall [--restore-backup]`

Remove the acct-managed gitconfig block and unset global core.hooksPath. OS helpers (osxkeychain, wincred, libsecret) may still answer for github.com — doctor will say so.

```bash
acct uninstall --restore-backup
```

Flags:

- `--restore-backup`: Restore the pre-acct gitconfig backup if one exists.

## Shell

The hook re-resolves from cwd on every prompt. Sticky ACCT_PROFILE is stripped.

### `acct hook`

`acct hook <bash|zsh|fish|powershell>`

Print a shell hook. Eval it from your shell startup so cd rebinds env (or clears it when unbound).

```bash
eval "$(acct hook zsh)"
eval "$(acct hook bash)"
acct hook fish | source
acct hook powershell | Out-String | Invoke-Expression
```

### `acct shell-env`

`acct shell-env [--powershell]`

Print env exports for the cwd profile. Used by the shell hook; you rarely run this yourself.

```bash
acct shell-env
```

Flags:

- `--powershell`: Emit PowerShell syntax.

### `acct wrap-install`

`acct wrap-install`

Install optional PATH shims so gh is invoked as acct exec gh. Then add the wrap-path export to your shell.

```bash
acct wrap-install
eval "$(acct wrap-path)"
```

### `acct wrap-path`

`acct wrap-path [--powershell]`

Print the PATH export for wrap shims. Installs the shims if they are missing.

```bash
eval "$(acct wrap-path)"
```

Flags:

- `--powershell`: Emit PowerShell syntax.

## Internal

Called by git hooks. Do not run these by hand unless you are debugging.

### `acct hook-run`

`acct hook-run <pre-commit|pre-push>`

Internal entry for enforce hooks. pre-commit checks commit identity; pre-push checks auth. On failure, prints the block message plus a status diagnosis.

```bash
acct hook-run pre-push
```

## Environment

Config: `config.yaml` under the config dir (`~/.config/acct`, `%APPDATA%\acct` on Windows, or `$XDG_CONFIG_HOME/acct`). Tokens live in the OS keychain, never in that file. File backend: `ACCT_SECRET_BACKEND=file` → `secrets.json` (mode 0600).

- `ACCT_FOLLOW_GH`: Set 0 / false / off to stop following gh auth token --user. File backend already does not follow gh unless you set 1.
- `ACCT_SECRET_BACKEND`: Set file for plaintext secrets.json under the config dir (mode 0600). Use in CI / headless hosts without a keyring.
- `ACCT_CONFIG_DIR`: Override the config directory. Default: ~/.config/acct, %APPDATA%\acct on Windows, or $XDG_CONFIG_HOME/acct.
- `ACCT_PROFILE`: Ambient profile id. Ignored for git credential helper and hooks. Directory / .acct win. The shell hook strips this before resolve.
- `ACCT_SKIP_POSTINSTALL`: Skip the npm postinstall tip sheet. Also skipped in CI.
- `ACCT_NODE_PATH`: Override the node binary baked into git hooks. Hooks otherwise use process.execPath, never which node.
- `ACCT_DEBUG`: Print sanitized debug lines to stderr. Token values are always [REDACTED].

## Further reading

- Invariants: https://github.com/abdull-ah-med/acct/blob/main/docs/invariants.md
- Threat model: https://github.com/abdull-ah-med/acct/blob/main/docs/threat-model.md
- LLM index: https://acct-web.vercel.app/llms.txt
