Init & Setup
Installation, shell integration, repository setup, and configuration.
Installation
curl -fsSL https://raw.githubusercontent.com/krondor-corp/jig/main/install.sh | bash
Or build from source:
git clone https://github.com/krondor-corp/jig
cd jig
cargo install --path crates/jig-cli
Running the daemon as a service
On Linux, jig daemon install writes a system unit, so it needs root. Who
runs the install decides which binary the service runs and who can update it.
You have sudo, and the daemon is yours. Install jig as yourself
(~/.local/bin), then point sudo at that binary — sudo does not search
your PATH:
sudo "$(command -v jig)" daemon install
The unit runs your own binary. To upgrade:
jig update && jig daemon restart
An admin runs the daemon for a user without sudo. The admin installs jig
as root, into /usr/local/bin, and installs the daemon from that binary:
curl -fsSL https://raw.githubusercontent.com/krondor-corp/jig/main/install.sh | sudo INSTALL_DIR=/usr/local/bin bash
sudo /usr/local/bin/jig daemon install --as dev
The unit runs the root-owned binary where it is. The user cannot update it,
and jig update says so. The user should not install a copy of their own,
because the daemon will never run it. To upgrade, the admin re-runs the
installer and anyone runs jig daemon restart, which needs no root: it asks
the daemon to exit and the service brings it back on the new binary.
jig daemon status warns when the daemon’s version differs from your CLI’s,
which usually means the service runs a different binary from the one on
your PATH.
Shell Integration
Quick setup
jig shell-setup
This detects your shell and adds integration automatically. Use --dry-run to preview changes.
Manual setup
# For bash (~/.bashrc)
eval "$(jig shell-init bash)"
# For zsh (~/.zshrc)
eval "$(jig shell-init zsh)"
# For fish (~/.config/fish/config.fish)
jig shell-init fish | source
This enables the jig command with directory-changing support and tab completion.
Tab completion
jig <TAB> # Shows: create list open remove exit config spawn ps...
jig open <TAB> # Shows available worktrees
jig remove <TAB> # Shows available worktrees
How the -o flag works
The jig shell function wraps the binary. When you use open or the -o flag, the binary outputs a cd command that the shell function evals — that’s why jig open can change your directory.
Troubleshooting
If type jig shows a binary path instead of “jig is a shell function”, the shell wrapper isn’t active. The -o flag won’t change directories and tab completion may not work.
Fix: Ensure the eval line comes AFTER your PATH is set:
# ~/.zshrc or ~/.bashrc
export PATH="$HOME/.cargo/bin:$PATH"
eval "$(jig shell-init zsh)"
Since jig is a shell function, which jig shows the function definition. Use jig which to find the binary path.
Initialize a Repository
cd ~/projects/my-app
jig init
This scaffolds:
my-project/
├── AGENTS.md # Project guide — points agents at docs/
├── jig.toml # jig spawn configuration
├── docs/
│ └── index.md # Agent instructions (key files, conventions, how to build/test)
└── <agent-config>/
├── settings # Permissions (git, gh, file ops, etc.)
└── skills/
├── check/ # /check — run build/test/lint
├── draft/ # /draft — push and create draft PR
└── issues/ # /issues — discover and manage work items
Init also registers the repo in ~/.config/jig/repos.json, the list of repos the daemon watches and -g commands span. Re-running jig init in an already-initialized repo refreshes its hooks and registers it if it isn’t yet.
If files already exist, init skips them. Use --force to overwrite, --backup to save existing files first:
jig init --force --backup
Auditing with --audit
Let the agent populate your docs automatically:
jig init --audit
This runs the agent as a one-shot foreground process to audit the codebase and fill in the skeleton docs — it blocks your terminal until the audit finishes. Pass extra instructions:
jig init --audit "We use pnpm, not npm. The API is actix-web."
Combine with backup to give the agent your existing files as reference:
jig init --force --backup --audit
What each file does
| File | Purpose |
|---|---|
AGENTS.md |
Entry point agents read. Points to docs/ for details. |
docs/index.md |
Core instructions: project structure, build commands, conventions. |
| Agent config | Permissions and settings for your agent framework. |
| Skills | Slash commands available in agent sessions (/check, /draft, /issues). |
jig.toml |
Spawn and issue configuration (see below). |
Configuration
jig.toml
The primary config file, committed to your repo:
[worktree]
base = "origin/main" # Base branch for new worktrees
on_create = "npm install" # Command to run after worktree creation
copy = [".env", ".env.local"] # Gitignored files to copy into new worktrees
[agent]
type = "claude" # Agent framework (claude, codex, cursor)
model = "opus" # Passed verbatim to --model; omit to use the agent's own default
[issues]
provider = "linear" # Issue provider
[issues.linear]
profile = "work" # References ~/.config/jig/config.toml profile
team = "ENG" # Linear team key
projects = ["Backend"] # Optional project filter
[triage]
enabled = true # Enable triage auto-spawn (default: false)
model = "sonnet" # Model for triage agents (passed verbatim; omit for agent default)
timeout_seconds = 600 # Max triage duration
jig.local.toml
Machine-specific overrides that shouldn’t be committed. Useful for setting a Linear profile per-developer:
# jig.local.toml — gitignored, not shared with team
[issues.linear]
profile = "personal" # use a different Linear profile on this machine
Deep-merged on top of jig.toml: tables merge recursively, scalars and arrays replace. jig init adds jig.local.toml to .gitignore automatically.
Global config
Override settings globally via jig config:
jig config base origin/develop # Set base branch for current repo
jig config base --global origin/main # Set global default
jig config on-create 'npm install' # Set on-create hook
jig config # View current config
jig config --list # List all configuration
Resolution order: repo-specific jig.toml > global config > hardcoded fallback (origin/main).
Copying gitignored files
Files like .env are gitignored but needed in worktrees. Configure in jig.toml:
[worktree]
copy = [".env", ".env.local", ".secrets"]
Files are copied from repo root to new worktrees before the on_create hook runs. Missing files are silently skipped.
Hook timeouts
on_create is killed if it runs too long — 10 minutes by default — and the spawn fails with a clear error instead of hanging.
This matters most for the daemon, which runs one spawn at a time. A hook that never returns (an install waiting on a dead network, a command that stops for a prompt) would otherwise stop auto-spawn indefinitely, with the daemon still reporting healthy.
Give a slow hook more room by writing it as a table instead of a string:
[worktree.on_create]
command = "pnpm install --frozen-lockfile"
timeout = 1800 # seconds
timeout = "none" disables the limit. Only do that where a person is watching and can interrupt it — never on a machine running the daemon unattended.
The same applies to the notification hook in ~/.config/jig/config.toml:
[notify.exec]
command = "~/.config/jig/hooks/notify.sh"
timeout = 10
The plain string form still works everywhere and picks up the default:
on_create = "npm install"
Git remote timeouts
Fetching and pushing are bounded, in ~/.config/jig/config.toml:
[git]
timeout = 600 # seconds a fetch or push may take, or "none"
This bounds the whole command, not idle time — a legitimately slow fetch of a large repo counts against it, so set it above your slowest real fetch rather than near it. It exists because a remote that accepts a connection and then goes quiet would otherwise hang the daemon’s sync and spawn work indefinitely.
Authentication is whatever your git already does: ~/.ssh/config and its per-host IdentityFile, the agent, the keychain, credential helpers, deploy keys, HTTPS tokens. jig runs git fetch and git push rather than speaking the protocols itself, so there is nothing separate to configure — if git fetch works in that repo, jig works.
Machine name
Each daemon reports which machine it runs on, shown by jig daemon status:
[fleet]
name = "devbox" # defaults to the hostname
Beside the name, jig mints a node id once into ~/.config/jig/node_id. It survives restarts, renames and hostname changes. Delete the file to give the machine a new identity.
The same section turns on the daemon’s local web view (web = true, web_port = 7477); see Monitoring.
Iterating after init
jig init is a first pass. Iterate on the generated docs — ask your agent to improve docs/index.md, or edit by hand. Consider adding:
- Code patterns — error handling, naming, module structure
- Dev workflows — local environment setup, migrations, seed data
- PR criteria — what must pass before merge
- Architecture decisions — why things are structured this way
The skills (/check, /draft, /issues) are also generic defaults. Customize them for your project’s actual build commands and workflows.