gpx-cli-0.1.0 is not a library.
gpx
gpx (Git Profile Extension) automatically switches Git and SSH identities across different repositories/directories.
Scope
- Unix platforms (macOS / Linux)
- Users who need to switch identities between personal/corporate and multi-account repositories
Install
-
Install from crates.io:
-
Build from source:
Quick Start
-
Initialize the include entry:
-
Write
config.tomlin the config directory (see the example below). -
Check which rules apply to the current directory:
-
Apply the current profile:
-
Check status and diagnostics:
Config File Paths
- Config:
$XDG_CONFIG_HOME/gpx/config.toml(default:~/.config/gpx/config.toml) - Compatible
.gitconfig-style config with lower priority than.toml:$XDG_CONFIG_HOME/gpx/config - Git config cache:
$XDG_CACHE_HOME/gpx/git/... - SSH config cache:
$XDG_CACHE_HOME/gpx/ssh/gpx_ssh.conf - State:
$XDG_STATE_HOME/gpx/state.toml
Config Example
[]
= "personal"
= "first-match" # first-match | highest-score
= "global-active" # global-active | repo-local
[]
= "Alice Chen"
= "alice@corp.com"
[]
= "~/.ssh/id_ed25519_work"
= true
[]
= "Alice"
= "me@example.com"
[]
= "~/.ssh/id_ed25519_personal"
[]
= true
= true
= "abort-once" # continue | abort-once
[]
= true
[]
= false
[]
= false
[]
= "work"
= 200
= "~/code/company/**"
[]
= "work"
= 180
= "github.com"
= "corp-org"
Config Reference
core.defaultProfile- Required: Recommended
- Default:
<none> - Allowed: existing profile name, e.g.
personal,work - Notes: Used as fallback when no rule matches in
check,apply, andrun. If unset and no rule matches, resolution fails with an error instead of silently choosing an identity.
core.ruleMode- Required: No
- Default:
first-match - Allowed:
first-match,highest-score - Notes:
first-matchuses declaration order only.highest-scorecomparespriorityfirst and then matcher specificity; unresolved ties are treated as conflicts and require config changes.
core.mode- Required: No
- Default:
global-active - Allowed:
global-active,repo-local - Notes: Controls write target for
gpx apply.global-activeupdates one global active include shared by all repos;repo-localwrites include settings into the current repo/worktree context.
profile.<name>.user.name- Required: No
- Default:
<none> - Allowed: any non-empty string, e.g.
Alice Chen - Notes: Compiled into the profile include as Git
user.name. Useful when separate profiles require explicit author identity per repo.
profile.<name>.user.email- Required: No
- Default:
<none> - Allowed: email string, e.g.
alice@corp.com - Notes: Compiled into the profile include as Git
user.email. This is usually the primary identity field teams validate in commits.
profile.<name>.user.signingkey- Required: No
- Default:
<none> - Allowed: key id/fingerprint string
- Notes: Compiled as Git
user.signingkeyfor commit/tag signing workflows. Leave unset if signing is not required for that profile.
profile.<name>.gpg.format- Required: No
- Default:
<none> - Allowed: string, e.g.
openpgp - Notes: Optional
gpg.*extension field written into the profile include. Configure this only when your signing backend differs across profiles.
profile.<name>.ssh.key- Required: No
- Default:
<none> - Allowed: SSH private key path, e.g.
~/.ssh/id_ed25519_work - Notes:
~is expanded before use. The key path is used for generated SSH include files and for temporary SSH command injection inrunmode.
profile.<name>.ssh.identitiesOnly- Required: No
- Default:
false - Allowed:
true,false - Notes: When
true, emitsIdentitiesOnly yesso SSH avoids offering unrelated agent keys, which helps prevent wrong-account auth on multi-key machines.
hook.shell- Required: No
- Default:
false - Allowed:
true,false - Notes: Enables shell-hook installation intent in config. It does not install hooks automatically; run
gpx hook install --shell ...to actually install.
hook.git- Required: No
- Default:
false - Allowed:
true,false - Notes: Enables git-hook installation intent in config. Actual hook files are created by
gpx hook install --git.
hook.fixPolicy- Required: No
- Default:
continue - Allowed:
continue,abort-once - Notes: Applies to hook-triggered auto-fix flow (
--hook-mode).continuekeeps current Git action running after identity correction;abort-oncestops once so the next command runs with corrected identity from the start.
run.allowProfileOverride- Required: No
- Default:
false - Allowed:
true,false - Notes: Governs whether
gpx run --profile <name> -- ...can force a profile. Whenfalse,runmust use rule/default resolution and explicit override is rejected.
worktree.allowSharedFallback- Required: No
- Default:
false - Allowed:
true,false - Notes: Only relevant in
repo-localmode for linked worktrees. Ifextensions.worktreeConfigis disabled,trueallows fallback to shared--localinclude (affecting all worktrees);falseblocks write and asks for explicit fix.
ssh.dynamicMatch- Required: No
- Default:
false - Allowed:
true,false - Notes: When enabled, generates SSH
Match exec "gpx ssh-eval ..."blocks for directory-aware identity selection. Default isfalseto keep SSH behavior predictable and avoid extra per-connection command execution overhead.
rule.<name>.profile- Required: Yes (per rule)
- Default: N/A
- Allowed: existing profile name
- Notes: Target profile selected when this rule matches. Validation fails if the referenced profile does not exist.
rule.<name>.priority- Required: No
- Default:
0 - Allowed: integer, e.g.
200,180,-10 - Notes: Used only by
highest-scoremode. Larger values win before specificity checks; negative values are valid for low-priority fallback rules.
rule.<name>.match.path- Required: Conditionally
- Default:
<none> - Allowed: glob path string, e.g.
~/code/company/** - Notes: Matches against normalized absolute current working directory. This matcher works even outside a Git repo, so it is useful for early directory-based profile decisions.
rule.<name>.match.remoteHost- Required: Conditionally
- Default:
<none> - Allowed: host string, e.g.
github.com - Notes: Compared against host parsed from repository remotes (for example
github.com, internal Git hostnames). Effective only when repository context and remotes are available.
rule.<name>.match.remoteOrg- Required: Conditionally
- Default:
<none> - Allowed: org/user string, e.g.
corp-org - Notes: Compared against org/user segment parsed from remote URL path. Useful for separating identities on the same host by organization namespace.
rule.<name>.match.fileExists- Required: Conditionally
- Default:
<none> - Allowed: file name/path at repo root, e.g.
.gpx-personal - Notes: Checks file existence at repository root (not arbitrary parent traversal). This is useful for explicit opt-in marker files committed per repo.
- Rule composition
- Required: N/A
- Default: N/A
- Allowed: N/A
- Notes: Each rule must define at least one
match.*. If a rule defines multiple matchers, all must pass (logical AND); this lets one rule combine path, remote, and marker constraints precisely.
Commands
gpx init
gpx doctor
gpx status [--verbose]
gpx list [profiles|rules] [--json]
gpx check [--cwd <path>] [--json]
gpx apply [--cwd <path>] [--profile <name>] [--dry-run]
gpx hook install [--shell bash|zsh|fish|nushell|tcsh|elvish] [--git]
gpx hook uninstall [--shell bash|zsh|fish|nushell|tcsh|elvish] [--git]
gpx run [--profile <name>] -- <git args...>
gpx -- <git args...> # gpx run -- <git args...>
Behavior
- Supported rule conditions:
match.path,match.remoteHost,match.remoteOrg,match.fileExists - If one rule defines multiple
match.*conditions, all of them must match - Falls back to
core.defaultProfilewhen no rule matches listshows configuredprofiles/rules; use--jsonfor machine-readable outputrunmode does not write any config; it only injects environment variables for the current Git command- Whether
--profilecan force override is controlled byrun.allowProfileOverride
Submodule and Worktree
- Submodules apply configuration independently based on each repository context
- In
repo-localmode:- If
extensions.worktreeConfigis enabled, write--worktree include.path - If it is disabled and
worktree.allowSharedFallback=false, writes are rejected with remediation guidance - If
worktree.allowSharedFallback=true, it falls back to shared--local(which affects all worktrees)
- If
Hook
- Shell hook: automatic scripts for
bash/zsh/fish; integration templates fornushell/tcsh/elvish - Git hook: installs
pre-commit,pre-push, andpost-checkout hook.fixPolicy:continue: continue after fixabort-once: exit this time after fix, then run Git action on next attempt
SSH Dynamic Matching (Optional)
Disabled by default. After enabling ssh.dynamicMatch=true, gpx apply generates Match exec "gpx ssh-eval ..." blocks to select identities dynamically by current directory.