naj the git profile manager https://github.com/dotinx/naj
Find a file
inx 593c5f8f7f
fix: critical patches for ssh signing, profile switching, and subdir support
fix: critical patches for ssh signing, profile switching, and subdir support

This release addresses several critical issues discovered during E2E testing:

- **fix(exec):** Prevent crash in Exec Mode when using SSH signing.
  - Sanitizer now resets `gpg.format` to "openpgp" and `gpg.ssh.program` to "ssh-keygen" instead of empty strings (which caused Git to exit with code 128).
- **fix(switch):** Correctly replace active profile instead of appending.
  - Now cleans up existing Gosh include paths before adding the new one to prevent ambiguous identity resolution.
- **fix(core):** Support running Gosh from deep subdirectories.
  - Replaced manual `.git` folder check with `git rev-parse` to correctly detect repository root.
- **security:** Hardened Blind Injection defaults to align with Git 2.52+ strictness.
2026-01-28 15:56:54 +08:00
scripts fix: critical patches for ssh signing, profile switching, and subdir support 2026-01-28 15:56:54 +08:00
src fix: critical patches for ssh signing, profile switching, and subdir support 2026-01-28 15:56:54 +08:00
tests feat(core): implement secure multi-identity management system 2026-01-27 15:22:21 +08:00
.gitignore feat(build): add cross compiling script 2026-01-27 17:12:32 +08:00
Cargo.toml fix: critical patches for ssh signing, profile switching, and subdir support 2026-01-28 15:56:54 +08:00
LICENSE chore: setup rust project 2026-01-27 15:01:08 +08:00
README.md feat(build): add cross compiling script 2026-01-27 17:12:32 +08:00

Gosh (Git Operations SHell)

Gosh is a lightweight, secure, and idempotent wrapper for Git, written in Rust. It solves the chaos of managing multiple Git identities (Work vs. Personal) by strictly isolating configurations and preventing accidental identity leaks.

🚀 Features

  • 🛡️ Fail-Safe Security: Uses "Blind Injection" to forcibly wipe global identity keys before applying a profile. If your profile lacks a key, Gosh fails securely rather than falling back to your global ~/.gitconfig.
  • Ephemeral Execution: Run commands like gosh work commit without modifying any files on disk. Perfect for one-off fixes.
  • 💾 Persistent Switching: Permanently bind a repository to an identity using Git's native [include] directive.
  • 🛠️ Zero Config Setup: Automatically handles clone and init setup, applying the correct identity immediately.
  • 📂 Portable Profiles: Profiles are stored in ~/.config/gosh/profiles/, designed to be synced via a private Git repository.

📦 Installation

From Source

cargo install --path .

📖 Usage

1. Management: Create Identities

Gosh manages identities as "Profiles".

# Syntax: gosh -c <Name> <Email> <ProfileID>
gosh -c "Alice Work" "alice@company.com" "work"
gosh -c "Alice Hobby" "alice@gmail.com" "personal"

# List all profiles
gosh -l

# Edit a profile (e.g., to add signingkey or sshCommand)
gosh -e work

When you clone or init a repository, Gosh automatically sets up the local config.

# Clones the repo and immediately binds it to the "work" profile
gosh work clone git@github.com:company/backend.git

# Inside the repo, you can now just use standard git
cd backend
git config user.email # Output: alice@company.com

3. Workflow B: One-off Commands (Exec Mode)

Run a command with a specific identity without modifying the repository config.

# Temporarily commit as "personal" in a work repo (e.g., fixing a typo)
gosh personal commit -m "Fix typo"

# Verification
gosh personal config user.email

4. Workflow C: Switch Identity (Persistent)

Change the identity bound to an existing repository.

cd my-repo
gosh work

# If the repo has "dirty" config (manually set user.name), force overwrite it:
gosh work -f

⚙️ Configuration

Gosh follows the XDG Base Directory specification.

  • Config File: ~/.config/gosh/gosh.toml
  • Profiles: ~/.config/gosh/profiles/*.gitconfig

On the first run, Gosh will automatically create these directories and a default configuration file.

Environment Variables

  • GOSH_CONFIG_PATH: Override the config directory (Useful for NixOS or testing).
  • GOSH_MOCKING=1: Dry-run mode. Prints the constructed git command to stderr instead of executing it.

🔒 Security Design: Blind Injection

In Exec Mode, Gosh does not read your local configuration to decide what to override. Instead, it aggressively injects empty values for sensitive keys before applying your profile.

Example command generated by Gosh:

git \
  -c user.name="" \       # 1. Wipe potential leaks
  -c user.email="" \
  -c user.signingkey="" \
  -c commit.gpgsign=false \
  -c include.path=~/.config/gosh/profiles/work.gitconfig \ # 2. Apply Profile
  commit ...

This ensures that if your "work" profile is missing a GPG key, Git will error out ("Secret key not available") rather than silently using your personal GPG key from ~/.gitconfig.

📦 Build Artifacts

Use a machine running Linux to build artifacts for all targets. rustup, cross, and podman/docker are required.

Run build.sh to build artifacts for all targets.

📄 License

BSD 2-Clause License