Introduction
git-paw (Parallel AI Worktrees) orchestrates multiple AI coding CLI sessions across git worktrees from a single terminal using tmux.
Working with AI coding assistants like Claude, Codex, or Gemini is powerful — but what if you could run them in parallel across multiple branches at once? That’s exactly what git-paw does.
The Problem
You have a feature branch, a bugfix branch, and a refactoring branch. You want an AI assistant working on each one simultaneously. Normally you’d need to:
- Open multiple terminals
- Create git worktrees manually
- Navigate to each worktree
- Launch your AI CLI in each one
- Juggle between them
The Solution
With git-paw, you run a single command:
git paw
git-paw will:
- Detect which AI CLIs you have installed (Claude, Codex, Gemini, Aider, etc.)
- Prompt you to pick branches and a CLI (or different CLIs per branch)
- Create git worktrees for each selected branch
- Launch a tmux session with one pane per branch, each running your chosen AI CLI
- Persist the session state so you can stop, resume, or recover after crashes
Key Features
- One command to go from zero to parallel AI sessions
- Smart start — reattaches to active sessions, recovers crashed ones, or launches fresh
- Per-branch CLI selection — use Claude on one branch and Gemini on another
- Session persistence — stop and resume without losing your place
- Custom CLI support — register any AI CLI binary, not just the built-in ones
- Presets — save branch + CLI combos in config for one-command launch
- Non-interactive mode — pass
--cliand--branchesflags for scripting - Dry run — preview what git-paw will do before it does it
How It Works
┌──────────────────────────────────────────────────────┐
│ tmux session │
│ ┌────────────────────┐ ┌────────────────────────┐ │
│ │ feat/auth → claude │ │ feat/api → claude │ │
│ │ │ │ │ │
│ │ (git worktree) │ │ (git worktree) │ │
│ │ │ │ │ │
│ ├────────────────────┤ ├────────────────────────┤ │
│ │ fix/bug → gemini │ │ refactor/db → aider │ │
│ │ │ │ │ │
│ │ (git worktree) │ │ (git worktree) │ │
│ │ │ │ │ │
│ └────────────────────┘ └────────────────────────┘ │
└──────────────────────────────────────────────────────┘
Each pane runs in its own git worktree, so there are no branch conflicts. Your AI assistants work independently and in parallel.
Requirements
- Git (2.20+ recommended for worktree improvements)
- tmux (any recent version)
- At least one AI coding CLI installed (see Supported AI CLIs)
- macOS or Linux (Windows via WSL only)
Next Steps
- Install git-paw
- Quick Start: Same CLI Mode — get running in 2 minutes
- Quick Start: Per-Branch CLI Mode — mix different AI CLIs
Installation
Prerequisites
Before installing git-paw, ensure you have:
- Git 2.20 or later
- tmux — any recent version
Installing tmux
macOS:
brew install tmux
Ubuntu / Debian:
sudo apt install tmux
Fedora:
sudo dnf install tmux
Arch Linux:
sudo pacman -S tmux
Install git-paw
From crates.io (recommended)
cargo install git-paw
Via Homebrew
brew install bearicorn/tap/git-paw
Shell installer
curl --proto '=https' --tlsv1.2 -LsSf https://github.com/bearicorn/git-paw/releases/latest/download/git-paw-installer.sh | sh
From source
git clone https://github.com/bearicorn/git-paw.git
cd git-paw
cargo install --path .
Verify installation
git-paw --version
You should see output like:
git-paw 0.1.0
Since git-paw is named with the git- prefix, git recognizes it as a subcommand. Both of these work:
git-paw --help
git paw --help
Platform Support
| Platform | Support |
|---|---|
| macOS (ARM / Apple Silicon) | Full support |
| macOS (x86_64 / Intel) | Full support |
| Linux (x86_64) | Full support |
| Linux (ARM64 / aarch64) | Full support |
| Windows | WSL only |
Windows (WSL)
git-paw requires tmux, which is not natively available on Windows. Use Windows Subsystem for Linux (WSL):
# Install WSL (PowerShell as admin)
wsl --install
# Then inside WSL:
sudo apt install tmux
cargo install git-paw
All git-paw features work inside WSL. Your AI CLIs must also be installed within the WSL environment.
Install an AI CLI
git-paw needs at least one AI coding CLI installed. See Supported AI CLIs for the full list. Some popular options:
# Claude Code
npm install -g @anthropic-ai/claude-code
# OpenAI Codex
npm install -g @openai/codex
# Aider
pip install aider-chat
Next Steps
Quick Start: Same CLI Mode
This walkthrough shows how to launch git-paw with the same AI CLI on all branches — the most common workflow.
Prerequisites
- git-paw installed
- tmux installed
- At least one AI CLI installed (e.g.,
claude) - A git repository with multiple branches
Step 1: Navigate to your repo
cd ~/projects/my-app
Step 2: Launch git-paw
git paw
Step 3: Select your mode
git-paw presents a mode picker:
? How would you like to assign CLIs to branches?
> Same CLI for all branches
Different CLI per branch
Select Same CLI for all branches and press Enter.
Step 4: Select branches
A multi-select list of all your branches appears with fuzzy search:
? Select branches (space to toggle, enter to confirm):
[ ] main
[x] feat/auth
[x] feat/api
[ ] fix/typo
[x] refactor/db
Use arrow keys to navigate, Space to toggle, and Enter to confirm.
Step 5: Select your CLI
Pick which AI CLI to use on all selected branches:
? Select AI CLI:
> claude
codex
gemini
Step 6: git-paw does the rest
git-paw now:
- Creates a git worktree for each selected branch
- Creates a tmux session named
paw-my-app - Opens one pane per branch
- Launches your chosen CLI in each pane
- Saves the session state for later recovery
Creating worktrees...
✓ my-app-feat-auth (feat/auth)
✓ my-app-feat-api (feat/api)
✓ my-app-refactor-db (refactor/db)
Launching tmux session: paw-my-app
Pane 1: feat/auth → claude
Pane 2: feat/api → claude
Pane 3: refactor/db → claude
Attaching to session...
You’re now inside a tmux session with three panes, each running Claude in its own worktree:
┌─── feat/auth → claude ────────┬─── feat/api → claude ─────────┐
│ │ │
│ Claude is ready to help... │ Claude is ready to help... │
│ │ │
├─── refactor/db → claude ──────┴────────────────────────────────┤
│ │
│ Claude is ready to help... │
│ │
└─────────────────────────────────────────────────────────────────┘
Mouse mode is enabled by default — click a pane to switch to it, or drag borders to resize.
Non-interactive shortcut
Skip all prompts by passing flags:
git paw start --cli claude --branches feat/auth,feat/api,refactor/db
What’s next
- Switch panes: Click with mouse, or use
Ctrl-bthen arrow keys - Detach: Press
Ctrl-b dto detach from tmux (session keeps running) - Reattach: Run
git pawagain — it detects the active session and reattaches - Stop: Run
git paw stopto kill tmux but keep worktrees - Purge: Run
git paw purgeto remove everything
See the User Guide for the full details.
Quick Start: Per-Branch CLI Mode
This walkthrough shows how to assign different AI CLIs to different branches — useful when you want to compare AI assistants or use specialized tools for specific tasks.
Scenario
You have three branches and want to use:
- Claude for the auth feature (complex logic)
- Gemini for the API work (lots of boilerplate)
- Aider for the database refactor (incremental edits)
Step 1: Launch git-paw
cd ~/projects/my-app
git paw
Step 2: Select per-branch mode
? How would you like to assign CLIs to branches?
Same CLI for all branches
> Different CLI per branch
Step 3: Select branches
? Select branches (space to toggle, enter to confirm):
[ ] main
[x] feat/auth
[x] feat/api
[x] refactor/db
Step 4: Assign a CLI to each branch
git-paw prompts you for each branch individually:
? Select CLI for feat/auth:
> claude
codex
gemini
aider
? Select CLI for feat/api:
claude
codex
> gemini
aider
? Select CLI for refactor/db:
claude
codex
gemini
> aider
Step 5: Watch it launch
Creating worktrees...
✓ my-app-feat-auth (feat/auth)
✓ my-app-feat-api (feat/api)
✓ my-app-refactor-db (refactor/db)
Launching tmux session: paw-my-app
Pane 1: feat/auth → claude
Pane 2: feat/api → gemini
Pane 3: refactor/db → aider
Attaching to session...
The tmux session shows each pane with its branch and CLI clearly labeled in the pane border:
┌─── feat/auth → claude ────────┬─── feat/api → gemini ─────────┐
│ │ │
│ Claude is ready to help... │ Gemini is ready... │
│ │ │
├─── refactor/db → aider ───────┴────────────────────────────────┤
│ │
│ Aider v0.x loaded... │
│ │
└─────────────────────────────────────────────────────────────────┘
Comparing approaches
Per-branch mode is great for:
- A/B testing AI assistants — give the same task to Claude and Gemini, compare results
- Specialization — use a code-generation-focused tool for boilerplate and a reasoning-focused tool for complex logic
- Trying new tools — test a new AI CLI on one branch while using your trusted tool on others
Recovery
Session state captures the per-branch CLI assignments. If your terminal closes or tmux crashes:
git paw
git-paw detects the saved session, recreates tmux, and relaunches each branch with its assigned CLI — no re-selection needed.
Next Steps
- User Guide — session management, presets, dry-run, and more
- Configuration — save per-branch presets in config
Quick Start: Supervisor Mode
This walkthrough shows how to launch git-paw in supervisor mode — git-paw’s hands-off, spec-driven workflow where a supervisor agent orchestrates several coding agents in parallel, runs tests between merges, and writes a final session report.
What Supervisor Mode Does
Supervisor mode (git paw start --supervisor) launches every pending spec as its own coding agent in a background tmux pane and gives you an interactive supervisor agent in the foreground pane. The supervisor automatically launches all agents per spec, runs the configured test_command between merges, walks branches in topological order based on declared dependencies, writes a .git-paw/session-summary.md when the run is complete, and auto-approves common safe permission prompts (e.g. cargo test, git commit, broker curl calls) so the run can proceed unattended.
Prerequisites
- The standard git-paw prerequisites (git-paw installed, tmux, an AI CLI on
PATH, a git repo). [broker] enabled = truein your config — supervisor mode requires the coordination broker.- A
[supervisor]section is recommended but optional. If it is missing, git-paw prompts for the supervisor CLI, the test command, and the agent approval level on first run. - A specs directory configured via
[specs](default:specs/) containing at least one pending spec.
Smallest Runnable Example
1. Create one OpenSpec-format spec
mkdir -p specs/add-greeting
cat > specs/add-greeting/tasks.md <<'MD'
## Add a greeting helper
- [ ] Add `pub fn greet(name: &str) -> String` to `src/lib.rs`.
- [ ] Add a unit test asserting `greet("paw") == "hello, paw"`.
- [ ] Run `cargo test` and make sure it passes.
MD
2. Configure broker + supervisor
.git-paw/config.toml:
[broker]
enabled = true
port = 9119
[specs]
dir = "specs"
type = "openspec"
[supervisor]
enabled = true
cli = "claude"
test_command = "cargo test"
agent_approval = "auto"
3. Launch
git paw start --supervisor
git-paw creates a worktree per spec, opens a tmux session with the supervisor in pane 0, the dashboard in pane 1, and one coding agent per spec in the remaining panes (pane 2 onwards). The supervisor injects its boot prompt automatically; you only need to chat with it for high-level approvals.
When every agent has reported verified and the supervisor has merged each branch in topological order, git-paw writes .git-paw/session-summary.md and exits.
Skipping Supervisor for One Session
If your project sets [supervisor] enabled = true (the recommended setup for active development), the supervisor runs by default for every git paw start. To skip the supervisor for a single session — e.g. for a quick debug-only run or a one-off branch flip — without editing the config, pass --no-supervisor:
# Project config says [supervisor] enabled = true, but we want a plain session
git paw start --no-supervisor --cli claude --branches feat/quick-fix
--no-supervisor is the highest-precedence step in the supervisor mode resolution chain — it wins over both [supervisor] enabled = true in config and any prompt. It is mutually exclusive with --supervisor; passing both fails at parse time.
The flag only affects the current session. Your config is untouched, so the next git paw start returns to supervisor mode as configured.
Key Config Knobs
The full reference lives in Configuration → Supervisor. The fields you will reach for most often:
| Field | What it controls |
|---|---|
[supervisor].enabled | Default to supervisor mode without passing --supervisor. |
[supervisor].cli | Which AI CLI runs as the supervisor (falls back to default_cli). |
[supervisor].test_command | Command run after each agent reports done and again after every merge. |
[supervisor].agent_approval | "manual", "auto", or "full-auto" — translates into CLI permission flags. |
[supervisor.auto_approve].enabled | Master switch for git-paw’s safe-prompt auto-dismisser. |
[supervisor.auto_approve].safe_commands | Project-specific command prefixes appended to the built-in safe list. |
[supervisor.auto_approve].approval_level | "off", "conservative", or "safe" preset for the auto-approve whitelist. |
[supervisor.common_dev_allowlist].enabled | Seeds Claude’s allowed_bash_prefixes with a curated preset of safe dev-loop commands on supervisor start. Default true. |
[supervisor.common_dev_allowlist].extra | Project-specific prefix patterns appended to the built-in preset (e.g. ["pnpm test", "deno fmt"]). |
See Configuration → Broker for [broker] settings and Configuration → Dashboard if you want the live broker-message panel turned on.
Broker Wire Format
Every coordination message the supervisor and its agents exchange goes through
the broker as a JSON envelope of the form
{"type": "agent.<variant>", "agent_id": "<slug>", "payload": {...}}. The
canonical examples below come from src/broker/messages.rs. agent_id slugs
must be lowercase alphanumeric + - / _ (no slashes — feat/auth is the
git branch name; feat-auth is the slug form the broker accepts).
agent.status (auto-published by the filesystem watcher whenever an agent’s
worktree changes; the manual form below is an escape hatch):
curl -s -X POST "$GIT_PAW_BROKER_URL/publish" \
-H "Content-Type: application/json" \
-d '{"type":"agent.status","agent_id":"feat-auth","payload":{"status":"working","modified_files":["src/auth.rs"],"message":"wiring JWT verifier"}}'
agent.artifact (auto-published by the post-commit hook with the committed
files; manual form is the escape hatch for code-less tasks):
curl -s -X POST "$GIT_PAW_BROKER_URL/publish" \
-H "Content-Type: application/json" \
-d '{"type":"agent.artifact","agent_id":"feat-auth","payload":{"status":"done","exports":["AuthClient"],"modified_files":[]}}'
agent.blocked, agent.intent, agent.question, agent.feedback, and
agent.verified round out the seven shipped variants — see the full reference
with payload-field semantics in Agent Coordination.
Where to Look When Things Go Wrong
When a supervisor run misbehaves, three places have everything you need:
- Dashboard pane (pane 1). With
[broker] enabled = truethe dashboard runs in pane 1 of the supervisor session and updates every second. Use it to spot which agent isblocked, which isworking, and how long it has been since each agent’s last status update. See the Dashboard chapter for status-symbol meanings and controls. - Supervisor pane (pane 0). The supervisor CLI runs here and prints feedback inline as it walks agents through the merge plan. Scroll back with tmux’s copy mode if you need to inspect earlier reasoning.
.git-paw/session-summary.md. Written by the supervisor when the run exits. Contains per-branch test results, merge order, and any agents that were skipped. If the supervisor exited early, this file tells you why..git-paw/broker.log. A JSONL audit trail of every message the broker handled —agent.status,agent.artifact,agent.blocked,agent.intent,agent.question,agent.feedback, andagent.verified. Tail it live withtail -f .git-paw/broker.logto watch coordination as it happens. The file is flushed every five seconds; see Agent Coordination for the full schema.
If you need to inspect an individual agent’s pane history, run tmux capture-pane -p -t <session>:<window>.<pane> against the session printed at launch.
Governance
If your project has existing governance docs (ADRs, DoD, security checklist,
test strategy, constitution), point the supervisor at them via the
[governance] table in .git-paw/config.toml. When set, those paths are
injected into the supervisor’s boot prompt and the supervisor consults each doc
as a sub-step of its spec-audit step. Findings flow through the existing
agent.feedback errors path — no new wire format. See the Governance
chapter for the full config, what the supervisor
checks per doc, and illustrative starting-point examples for each doc type.
What’s Next
- User Guide → Agent Coordination — broker message types and how agents talk to each other.
- User Guide → Dashboard — dashboard pane status table (pane 1 in supervisor mode, pane 0 otherwise), controls, and configuration.
- User Guide → Governance — pointing the supervisor at your project’s existing governance docs.
- Configuration → Supervisor — every supervisor and
auto_approvefield with defaults.
User Guide
This guide covers the full range of git-paw features beyond the quick starts.
Starting Sessions
Interactive start
Running git paw (or git paw start) with no flags launches the interactive flow:
- Mode selection — same CLI for all branches, or different CLI per branch
- Branch selection — multi-select with fuzzy search
- CLI selection — single pick (uniform) or per-branch assignment
Smart start behavior
git paw start inspects the current repo and decides what to do:
| State | Behavior |
|---|---|
| Active tmux session exists | Reattaches immediately |
| Saved session, tmux dead (crash/reboot) | Auto-recovers: reuses worktrees, recreates tmux, relaunches CLIs |
| No session | Full interactive launch |
You never need to think about whether to “start” or “resume” — just run git paw.
Non-interactive start
Skip prompts with flags:
# Specify both CLI and branches — no prompts at all
git paw start --cli claude --branches feat/auth,feat/api
# Specify just CLI — still prompted for branches
git paw start --cli claude
# Specify just branches — still prompted for CLI
git paw start --branches feat/auth,feat/api
Using presets
Define named presets in your config (see Configuration):
git paw start --preset backend
This uses the branches and CLI defined in the [presets.backend] section of your config.
CLI Modes
Same CLI for all branches
The default mode. Every branch gets the same AI CLI. Best for:
- Working on related features with your preferred tool
- Batch processing branches with a single assistant
Different CLI per branch
Assign a different CLI to each branch. Best for:
- Comparing AI assistants side by side
- Using specialized tools for specific tasks
- Trying a new CLI on one branch while keeping your usual tool on others
Session Management
Checking status
git paw status
Displays the current session state:
Session: paw-my-app
Status: 🟢 active
Created: 2025-01-15T10:30:00Z
Worktrees:
feat/auth → claude (../my-app-feat-auth)
feat/api → claude (../my-app-feat-api)
refactor/db → aider (../my-app-refactor-db)
Status indicators:
- 🟢 active — tmux session is running
- 🟡 stopped — session state saved, tmux not running (recoverable)
- No session — nothing saved for this repo
Stopping a session
git paw stop
This kills the tmux session but preserves:
- Git worktrees (with any uncommitted work)
- Session state file (branch/CLI assignments)
Run git paw later to recover the session with the same setup.
Purging a session
git paw purge
The nuclear option. Removes:
- Tmux session
- All git worktrees created by git-paw
- Session state file
Requires confirmation. Use --force to skip:
git paw purge --force
Dry Run
Preview what git-paw will do without executing:
git paw start --dry-run
Or with flags:
git paw start --cli claude --branches feat/auth,feat/api --dry-run
This runs the detection, selection, and planning steps, then prints the session plan and exits without creating worktrees or tmux sessions.
Tmux Navigation
Once inside a git-paw tmux session:
| Action | Keys |
|---|---|
| Switch pane | Click with mouse, or Ctrl-b + arrow key |
| Resize pane | Drag border with mouse, or Ctrl-b Ctrl-arrow |
| Detach (keep running) | Ctrl-b d |
| Scroll up | Ctrl-b [ then arrow keys, q to exit |
| Zoom pane (fullscreen toggle) | Ctrl-b z |
Mouse mode is enabled by default, so clicking and dragging just works. You can disable it in your config.
One Session Per Repo
git-paw manages one session per repository. If you run git paw in a repo that already has a session, it reattaches rather than creating a second session.
To work with multiple repos simultaneously, open separate terminals and run git paw in each repo directory.
Session Lifecycle
This chapter covers what git paw start does to your worktrees on each
launch (or relaunch), and how to control its behaviour when the defaults
don’t fit.
Rebase on start
Every git paw start rebases each existing agent branch onto the
repository’s default branch (whatever origin/HEAD tracks — typically
main) before opening or reopening that branch’s worktree. This
keeps agents starting from current main, which matters when the
supervisor (you) advances main while agents are still working on their
branches.
Why this is the default:
- A supervisor session typically lands commits on
mainwhile one or more agents are running onfeat/*branches. Without rebasing on start, every subsequent agent commit chains from the stale baseline, forcing a per-branch rebase at merge time. - The rebase is cheap when there’s nothing to do:
git rebaseexits zero with no rewrite when the branch is already up to date. - The branch ref is updated even in the resume case —
git paw starton a session whose worktrees already exist on disk picks up the newmaincommits transparently.
Rebases that don’t happen:
- A brand-new branch (one git-paw creates via
git worktree add -bduring this launch) is not rebased. It’s already at the current default-branch tip by construction. - If the repo has no
origin/HEAD(a rare brand-new repo with no remote), the rebase step errors out cleanly. Workaround: run with--no-rebase, or push the default branch tooriginand setorigin/HEADfirst.
Opting out: --no-rebase
Pass --no-rebase when you want the pre-v0.6 behaviour — agent branches
opened at their current SHA with no rebase attempt:
git paw start --no-rebase
git paw start --no-rebase --cli claude --branches feat/auth,feat/api
git paw start --no-rebase --supervisor # combines with other flags
Use cases:
- You are deliberately working against a stale baseline (e.g. an agent is reproducing a bug on a specific historical commit).
- An external tool has pinned a pre-rebase SHA on the agent branch and rewriting history would break it.
- You’re scripting against the pre-v0.6 launch contract and don’t want the new default behaviour.
Rebase conflicts
If the rebase hits a conflict — typically because both main and the
agent branch modified the same line of the same file — git paw start:
- Runs
git rebase --aborton the affected branch. - Leaves the branch at its pre-rebase HEAD (no half-rebased state survives).
- Exits with an error like
Error: rebase onto main failed: <git's stderr listing the conflicting files>.
When you see this error:
cdinto the affected agent’s worktree (typically at../<project>-<branch-slug>/).- Inspect the conflicting files git named in the error.
- Either reconcile manually (e.g.
git rebase mainfollowed by resolving conflicts andgit rebase --continue), or decide the change should land via a merge commit instead. - Once the branch is in a clean state, rerun
git paw start(with or without--no-rebasedepending on what you decided).
The conflict-abort path is intentional and not configurable — leaving a branch half-rebased poisons every subsequent git operation against it, which is far worse for the agent in that pane than a clean error at launch time.
What rebase does NOT do
- It does not
git fetchorgit pullformain. The rebase target is whateverorigin/HEADtracks locally; the user owns the remote-sync decision. - It does not rewrite the working tree files inside a surviving
worktree. After a rebase-on-resume, the worktree directory’s files
may diverge from the branch’s new HEAD until the agent does its own
checkout or pull inside the worktree. This is the standard
git rebasecaveat —git statusfrom inside the pane will surface it. - It does not rebase one agent branch onto another agent branch. Only
feat/<change>onto the repository’s default branch. - It does not loop or retry on failure. One attempt, abort on conflict, surface the error.
Resume vs. fresh launch
The rebase step runs in both flows:
- Fresh launch: branch exists locally, no worktree yet. Branch is
rebased onto
main, then the worktree is created at the rebased SHA. - Resume (worktree already on disk from a prior session): branch
is rebased in the existing worktree, the existence check confirms
the worktree is registered for that branch, and
git paw startreturns success with the worktree’s branch ref now pointing at the rebased HEAD.
If you’re debugging a launch and want to know whether the rebase
modified anything, git rev-parse <branch> from the main repo before
and after git paw start will show the SHA change (or lack thereof).
Spec-Driven Launch
The --from-all-specs and --specs flags let you define branches, CLI assignments, and prompts in spec files instead of using interactive selection. git-paw reads spec files from a configured directory, creates worktrees for each pending spec, and launches AI CLIs with the spec content injected into each worktree’s AGENTS.md.
Quick Example
# Initialize repo config (creates .git-paw/config.toml)
git paw init
# Add spec files to your specs/ directory, then launch every discovered spec
git paw start --from-all-specs
# Narrow to specific specs without editing config
git paw start --specs add-auth,fix-session
# Open a multi-select picker (requires an interactive terminal)
git paw start --specs
Picking specs at launch time
You have three ways to control which specs are launched:
--from-all-specs— launches every discovered spec across the configured backend.--specs NAME[,NAME...]— comma-separated list of spec names. Mirrors the existing--branches feat/a,feat/bsyntax. Unknown names exit with the discovered-set listed as candidates so you can correct quickly.--specs(bare, no values) — opens a multi-select picker showing every discovered spec. Each row shows the unit identifier; for Spec Kit features that decompose into multiple worktrees, the row also shows a worktree-count hint (e.g.003-user-list — 3 worktrees: 2 [P] + 1 phase/).
--from-all-specs and --specs are mutually exclusive — they express opposing intents — and clap rejects any invocation that combines them.
Picker requires a TTY
The bare --specs form requires an interactive terminal. When stdin is not a TTY (CI, scripted invocation, redirected input), git-paw exits with an actionable error pointing at the explicit forms:
error: --specs without values requires an interactive terminal
Use `--specs NAME[,NAME...]` to narrow explicitly, or
`--from-all-specs` to launch every discovered spec.
Name resolution rules
--specs NAME matches against the discovered set using these strategies in order:
- Exact match on the spec id (case-sensitive). Matches OpenSpec change names, Markdown filename stems, or Spec Kit decomposed entry ids like
003-user-list-T009. - Spec Kit feature-name match — the value matches a Spec Kit feature directory prefix (e.g.
003-user-list). All decomposed entries belonging to that feature are launched together. - Spec Kit numeric prefix — a digits-only value (e.g.
003) matches a unique feature directory whose name starts with003followed by a non-digit boundary. Ambiguous prefixes (two features both starting with003) are rejected with the candidate list.
Unknown names error out before any worktrees are created. The error message includes the unresolved name AND the discovered candidate list. There is no partial start.
Spec Formats
git-paw supports three spec formats: OpenSpec (directory-based), Markdown (file-based), and Spec Kit (.specify/-based, GitHub Spec Kit).
OpenSpec Format (default)
Each pending change lives in its own subdirectory under the specs directory. The subdirectory name becomes the branch identifier.
specs/
add-auth/
tasks.md # Required — main prompt
specs/
jwt/spec.md # Optional — supplementary spec
fix-pagination/
tasks.md
Discovery is by archive status, not task completion. --from-all-specs includes every change subdirectory under specs/ except anything under specs/archive/. A change with all tasks marked - [x] in its tasks.md is still picked up — task-completion is a progress tracker, not a discovery filter. After completing and verifying a change, run:
openspec archive <change-name>
before the next git paw start --from-all-specs invocation. openspec archive moves the change directory under specs/archive/<date>-<change>/ and syncs its delta specs into the main specs at specs/<capability>/spec.md. The next session won’t spawn a worktree for it.
tasks.md contains the prompt content sent to the AI CLI. It supports optional YAML frontmatter:
---
paw_cli: claude
---
## Implement JWT Authentication
Add JWT token support to the auth module.
The paw_cli field overrides the CLI for this specific spec. If omitted, the default resolution chain applies (see CLI Resolution below).
Supplementary spec files in specs/<name>/spec.md are appended to the prompt with section headers. File ownership can be declared with “Files owned:” or “Owned files:” followed by a markdown list.
Markdown Format
Flat .md files in the specs directory. Each file uses YAML frontmatter to control status and branch mapping.
specs/
add-auth.md
fix-pagination.md
design-notes.md # ignored — no paw_status: pending
Example file (specs/add-auth.md):
---
paw_status: pending
paw_branch: add-auth
paw_cli: claude
---
## Implement JWT Authentication
Add JWT token support to the auth module.
Frontmatter Fields
| Field | Required | Description |
|---|---|---|
paw_status | Yes | Must be "pending" to be included. Other values ("done", "in-progress") are ignored. |
paw_branch | No | Branch name suffix. Falls back to filename stem if absent. |
paw_cli | No | CLI override for this spec. |
Only files with paw_status: pending are picked up.
Spec Kit Format
Spec Kit projects place each feature in its own directory under .specify/specs/<feature>/, alongside an optional .specify/memory/constitution.md for project-level rules.
.specify/
memory/
constitution.md # Optional — project rules / governance
specs/
001-room-setup/
spec.md # Feature requirements
plan.md # Implementation plan
tasks.md # Required — task list with phases
checklists/ # Optional — advisory validation criteria
security.md
002-poker-voting/
spec.md
plan.md
tasks.md
Auto-detection. When .specify/specs/ exists at the repo root and you have no [specs] section in .git-paw/config.toml, git paw start --from-all-specs defaults to specs.type = "speckit" with specs.dir = ".specify/specs". git paw init also detects .specify/ and writes the matching [specs] section to the generated config so the choice is locked.
You can override with --specs-format:
# Force Spec Kit even when [specs] config says otherwise
git paw start --from-all-specs --specs-format speckit
# Force OpenSpec on a project that has a `.specify/` folder
git paw start --from-all-specs --specs-format openspec
tasks.md decomposition. Spec Kit’s tasks.md files use ## Phase N: <Name> headings and - [ ] T<NNN> task lines. git-paw decomposes the current phase (the first phase with any incomplete task) into one worktree per kind:
- Each incomplete
[P]-marked task → its own worktree ontask/<task-id>-<slug>(one agent per task, parallel). - All remaining incomplete non-
[P]tasks → one consolidated worktree onphase/<feature>-<phase-slug>(one agent works through them sequentially, since the absence of[P]indicates shared files or context).
## Phase 2: Foundational
- [ ] T009 [P] Contract test POST /auth/otp/request → task/t009-contract-test-...
- [ ] T010 [P] Contract test POST /auth/otp/verify → task/t010-contract-test-...
- [ ] T011 Setup database schema ┐
- [ ] T012 Create auth tables ├ phase/<feature>-foundational
- [ ] T013 Seed test data ┘
In this example, one feature directory produces three worktrees and three branches. This “one Spec Kit feature → multiple branches” model is intentional — [P] tasks parallelise across worktrees; non-[P] tasks sequence within a single worktree.
Phase advancement. Phases earlier than the current one are assumed complete (all - [x]). Phases later than the current one are deferred — they only produce worktrees on a future scan, after every task in the current phase has been ticked off. Fully completed features (every task in every phase is - [x]) are skipped silently.
Boot prompts. Each Spec Kit worktree’s AGENTS.md contains:
- Feature Context — the full
spec.mdcontent. - Implementation Plan — the full
plan.mdcontent (omitted when absent). - Validation Criteria (advisory) — each
checklists/<file>.mdcontent under its own heading. Checklists are advisory in this release; full enforcement is planned for v1.0.0. - Your Task — the single task description (
task/...worktrees) or the ordered task list plus sequential-execution +- [x]writeback +agent.artifact(withstatus: "done") instructions (phase/...worktrees).
Task writeback. Agents working in a phase/... worktree flip - [ ] to - [x] in the worktree’s tasks.md as they complete each task. The writeback may be committed alongside the task’s code change or as a separate commit. Per-line edits across worktrees are merged by git in the normal way; the conflict-detection layer catches the pathological case of two worktrees racing on the same task ID.
Constitution wiring. When .specify/memory/constitution.md exists, git-paw exposes its path via the SpecKit backend’s detect_constitution probe. A future [governance.constitution] config slot (the governance-config change) will consume this path automatically, so projects that already have a Spec Kit constitution get governance configured for free.
Configuration
Configure spec scanning in .git-paw/config.toml (or the global config):
# Default CLI for spec-mode launches (bypasses picker when set).
default_spec_cli = "my-cli"
# Prefix for spec-derived branch names (default: "spec/").
branch_prefix = "spec/"
# Spec scanning configuration.
[specs]
dir = "specs" # Directory containing spec files (relative to repo root)
type = "openspec" # "openspec" (default), "markdown", or "speckit"
The interpretation of dir depends on the format:
openspec— directory of change subdirectories (<dir>/<change>/tasks.md).markdown— directory of.mdfiles (<dir>/<spec>.md).speckit— directory of feature subdirectories (<dir>/<feature>/tasks.md); typically.specify/specs.
Branch Naming
Branch names depend on the format:
- OpenSpec:
<branch_prefix><id>where ID is the subdirectory name.specs/add-auth/with prefixspec/becomes branchspec/add-auth. - Markdown:
<branch_prefix><id>where ID ispaw_branch(if set) or the filename stem.specs/add-auth.mdwith prefixspec/becomes branchspec/add-auth. - Spec Kit: branch prefix is
task/orphase/depending on the entry kind;branch_prefixis not applied. Example:.specify/specs/003-user-list/tasks.mdwith task- [ ] T009 [P] Add login formproduces branchtask/t009-add-login-form.
CLI Resolution
When a spec-mode launch runs, CLIs are resolved in priority order:
--cliflag (highest) — applies to all specs, no promptpaw_cliin spec — per-spec override from frontmatterdefault_spec_cliin config — fills remaining specs without promptdefault_cliin config — pre-selects in picker for remaining- Interactive picker (lowest) — prompts for any unresolved specs
# Override all specs to use claude
git paw start --from-all-specs --cli claude
# Use per-spec paw_cli and default_spec_cli from config
git paw start --from-all-specs
# Narrow to a subset
git paw start --specs add-auth,fix-session --cli claude
# Preview without executing
git paw start --from-all-specs --dry-run
git paw start --specs add-auth --dry-run
Combining --from-all-specs with supervisor mode
--from-all-specs --supervisor (or --from-all-specs with [supervisor] enabled = true
in your config) engages the supervisor flow against the discovered specs.
git-paw scans the configured specs directory, creates one worktree per spec,
launches the dashboard pane and per-spec agent panes, and starts the supervisor
CLI in your foreground terminal — same supervisor architecture as
--branches-driven sessions, just with branches discovered from specs.
# Spec-driven session with supervisor watching
git paw start --from-all-specs --supervisor
# Same outcome via [supervisor] enabled = true in .git-paw/config.toml
git paw start --from-all-specs
# Skip supervisor for this session even if enabled in config
git paw start --from-all-specs --no-supervisor
When [broker] enabled = true (the default in supervisor mode), each spec
agent pane receives a boot block via tmux send-keys carrying its
BRANCH_ID, broker URL, and curl-publish patterns. This applies to both
spec-mode-only (--from-all-specs without supervisor) and supervisor mode.
Non-interactive launches
If git paw start is invoked from a non-interactive terminal — CI, scripted
invocation, or a harness tool that pipes stdin — git-paw skips the auto-attach
step and prints an attach hint instead:
Session 'paw-myproject' started in detached mode.
Attach with: tmux attach -t paw-myproject
For supervisor mode in a non-interactive context, the foreground supervisor CLI is also skipped (Claude/Codex etc. need a TTY to run interactively). The session, dashboard pane, and agent panes are all created; you can attach later from a real terminal and start the supervisor manually:
tmux attach -t paw-myproject
# in another terminal, in the repo root:
cd /path/to/repo && claude
Session Logging
git-paw can capture the full terminal output of each AI CLI pane to log files. This lets you review what happened in a session after it ends.
Enabling Logging
Add the [logging] section to your .git-paw/config.toml (or global config):
[logging]
enabled = true
When enabled, git-paw uses tmux pipe-pane to capture each pane’s output to a log file when a session starts.
Log Storage
Logs are stored under .git-paw/logs/ organized by session:
.git-paw/logs/
paw-my-project/
feat--add-auth.log
fix--pagination.log
Branch names are sanitized for filenames — / becomes -- (e.g., feat/add-auth becomes feat--add-auth.log).
The git paw init command automatically adds .git-paw/logs/ to .gitignore so logs are never committed.
Replaying Logs
Use git paw replay to view captured logs.
List available sessions and branches
git paw replay --list
Shows all sessions and their logged branches.
Replay a branch
git paw replay feat/add-auth
Branch names are fuzzy-matched — you can use the original branch name, the sanitized filename, or a partial match.
By default, ANSI escape codes are stripped for clean text output.
Replay with colors
git paw replay feat/add-auth --color
Preserves ANSI colors and pipes through less -R for scrollable colored output.
Replay from a specific session
git paw replay feat/add-auth --session paw-my-project
By default, the most recent session is used. Use --session to specify an older one.
Flags
| Flag | Description |
|---|---|
--list | List available log sessions and branches |
--color | Display with ANSI colors via less -R |
--session <name> | Session to replay from (defaults to most recent) |
AGENTS.md Injection
AGENTS.md is the full source of truth for an agent’s working context. When
git-paw launches a session, it generates an AGENTS.md in each worktree
containing the project’s root AGENTS.md content plus a managed git-paw
section that carries the entire spec body for the agent’s assigned change:
proposal, design (when present), task list, and any spec deltas. The agent
reads the spec from AGENTS.md plus openspec/changes/<id>/, not from the
boot prompt.
Boot-Prompt-Full-Body Model
Earlier versions of git-paw embedded a condensed spec excerpt inside the
supervisor-mode boot prompt itself (“Branch + CLI + Spec content + Owned
files”). In v0.5.0 the supervisor-mode boot prompt is intentionally short:
it points the agent at AGENTS.md and at the change directory
openspec/changes/<id>/, and tells the agent to read those files before
acting.
The benefits of this split:
- The spec body lives in a markdown file the agent can re-read at any time, not in volatile boot-prompt context.
- The boot prompt becomes small enough to remain in the agent’s working context for the entire session, even after long conversations.
- Manual operators can pre-stage the boot block at the pane input line via paste, the same way the supervisor stages it programmatically.
- The same generator (
src/agents.rs::setup_worktree_agents_mdor its v0.5.0 successor) writes the same content in both supervisor mode and broker-only mode, so the agent’s experience does not depend on which mode launched it.
How It Works
- Worktrees. When a session starts, each worktree gets its own
AGENTS.mdplaced at the worktree root. The file is overwritten on everygit paw startso the spec body never goes stale. - Exclusion. Worktree
AGENTS.mdfiles are added to the worktree’s.git/info/excludeso they never appear ingit statusor get committed alongside the agent’s work.
Markers
git-paw manages its section using HTML comment markers so the rest of the
file (a hand-written project AGENTS.md, for example) is preserved across
launches:
<!-- git-paw:start — managed by git-paw, do not edit manually -->
(git-paw content here — full spec body)
<!-- git-paw:end -->
Content between these markers is replaced on each launch. Content outside the markers is preserved. If no markers exist, the section is appended to the end of the file.
Worktree AGENTS.md Content
Each worktree’s AGENTS.md includes:
- The root repo’s
AGENTS.mdcontent (if any), preserved verbatim. - A git-paw section between the markers carrying:
- Branch name and assigned CLI for this worktree.
- Full spec body — proposal, design, tasks, and any spec deltas from
openspec/changes/<id>/. The exact set depends on what the change directory contains; missing files (design.md is often optional) are silently skipped. - Owned files list (from OpenSpec file-ownership declarations) when declared.
- Boot block with the broker
curlcommands the agent uses to self-report status, artifacts, blockers, intents, and questions.
The supervisor-mode boot prompt does not duplicate any of this content — it
points at the file. If a change is updated on disk during a session (e.g.
the supervisor edits tasks.md to mark a task complete), the worktree’s
AGENTS.md is regenerated on the next git paw start invocation rather
than live-patched mid-session.
Agent Coordination
When multiple AI agents work in parallel, they benefit from knowing what the others are doing. The coordination broker is a lightweight HTTP server that lets agents share status updates, publish artifacts, and flag blockers – all without touching git.
Enabling the Broker
Add a [broker] section to your .git-paw/config.toml:
[broker]
enabled = true
When you run git paw start, pane 0 becomes a dashboard instead of an agent pane. The dashboard hosts the broker and displays a live status table.
How Agents Discover the Broker
git-paw sets the GIT_PAW_BROKER_URL environment variable in every agent pane. Agents use this URL to send and receive messages. A typical value is http://127.0.0.1:9119.
When skill templates are enabled (the default), each agent’s AGENTS.md also contains curl commands for interacting with the broker, so agents know how to use it without any manual setup.
Boot-Prompt Injection
To ensure reliable agent self-reporting, git-paw automatically injects a standardized boot instruction block into every agent’s initial prompt. This boot block contains pre-expanded curl commands for four essential operations:
1. REGISTER - Immediate Status Publication
Agents automatically publish their working status with a “booting” message as their very first action:
curl -s -X POST http://127.0.0.1:9119/publish \
-H "Content-Type: application/json" \
-d '{"type":"agent.status","agent_id":"feat-auth","payload":{"status":"working","message":"booting","modified_files":[]}}'
2. DONE - Task Completion Reporting
The primary completion path is git commit. The git-paw post-commit hook auto-publishes agent.artifact { status: "committed" } with modified_files derived from git diff HEAD~1 --name-only, so agents working on code changes do not publish anything manually — they commit and the hook reports on their behalf.
The boot block retains a manual agent.artifact { status: "done" } curl as a fallback for code-less tasks (docs-only updates handled outside the worktree, planning notes, exploration tasks where the artifact is information reported to the broker). The block warns agents NOT to publish manual done while their worktree has uncommitted changes — they should commit instead.
curl -s -X POST http://127.0.0.1:9119/publish \
-H "Content-Type: application/json" \
-d '{"type":"agent.artifact","agent_id":"feat-auth","payload":{"status":"done","exports":[],"modified_files":[]}}'
3. BLOCKED - Dependency Waiting Notification
Agents can properly declare when they’re waiting on dependencies:
curl -s -X POST http://127.0.0.1:9119/publish \
-H "Content-Type: application/json" \
-d '{"type":"agent.blocked","agent_id":"feat-api","payload":{"needs":"auth token format","from":"feat-auth"}}'
4. QUESTION - Uncertainty Escalation (Critical)
Agents are instructed to publish questions and wait for answers rather than guessing:
curl -s -X POST http://127.0.0.1:9119/publish \
-H "Content-Type: application/json" \
-d '{"type":"agent.question","agent_id":"feat-auth","payload":{"question":"Should the JWT use RS256 or HS256 signing?"}}'
IMPORTANT: The boot block explicitly instructs agents: “DO NOT CONTINUE UNTIL YOU RECEIVE AN ANSWER!”
Boot Block Injection Modes
- Supervisor Mode: Boot block is prepended to each agent’s task prompt before injection
- Manual Broker Mode: Boot block is pre-filled into each agent pane’s input line (user pastes task after boot instructions)
Paste Handling
The boot block includes instructions for proper paste handling, particularly the requirement to send an additional Enter key after paste operations to ensure full content processing.
Benefits
- Reliable Monitoring: Agents self-report immediately on boot
- Consistent Behavior: All agents follow the same coordination pattern
- No Permission Prompts: Pre-expanded curl commands avoid shell variable expansion issues
- Supervisor Visibility: Questions and blockers surface to the dashboard promptly
- Audit Trail: All boot operations are logged in the broker log
Message Types
Every broker message uses the same JSON envelope:
{
"type": "agent.<variant>",
"agent_id": "<slug>",
"payload": { ... }
}
<variant> is one of seven shipped values; <slug> is the agent’s slugified
branch name (lowercase alphanumeric + - / _; slashes from a branch name
like feat/auth become hyphens — feat-auth). The seven variants are
agent.status, agent.artifact, agent.blocked, agent.intent,
agent.question, agent.feedback, and agent.verified; src/broker/messages.rs
is the source of truth for the payload schemas.
agent.statusandagent.artifactare normally automatic. The filesystem watcher publishesagent.status(withmodified_files) whenever a tracked file changes in a worktree, and the post-commit git hook publishesagent.artifactwithstatus: "committed"and the committed file list every time an agent commits. The manualcurlexamples below are escape hatches for cases where the automatic publishers do not apply (e.g. code-less tasks or heartbeat injection during read-only investigation).
Status
An agent reports what it is currently doing along with any files it has already modified in this work step.
curl -s -X POST "$GIT_PAW_BROKER_URL/publish" \
-H "Content-Type: application/json" \
-d '{"type":"agent.status","agent_id":"feat-auth","payload":{"status":"working","modified_files":["src/auth.rs"],"message":"implementing login endpoint"}}'
Artifact
An agent shares the result of a commit (or the analogous output of a code-less
task) so peers can see exports and modified files. The modified_files array
is what the conflict detector watches for in-flight overlap.
curl -s -X POST "$GIT_PAW_BROKER_URL/publish" \
-H "Content-Type: application/json" \
-d '{"type":"agent.artifact","agent_id":"feat-auth","payload":{"status":"committed","exports":["AuthClient"],"modified_files":["src/auth.rs","src/auth/client.rs"]}}'
Blocked
An agent declares that it is waiting on something specific from another agent
(or external resource). from names the agent that can unblock it.
curl -s -X POST "$GIT_PAW_BROKER_URL/publish" \
-H "Content-Type: application/json" \
-d '{"type":"agent.blocked","agent_id":"feat-api","payload":{"needs":"auth token format","from":"feat-auth"}}'
Intent
An agent declares which files it plans to modify before any edit lands. The
broker conflict detector reads agent.intent to flag forward conflicts when
two agents target overlapping paths. valid_for_seconds is the TTL after which
consumers MAY treat the intent as stale.
curl -s -X POST "$GIT_PAW_BROKER_URL/publish" \
-H "Content-Type: application/json" \
-d '{"type":"agent.intent","agent_id":"feat-auth","payload":{"files":["src/auth.rs","src/auth/client.rs"],"summary":"wire AuthClient","valid_for_seconds":900}}'
Question
An agent escalates an uncertainty to the supervisor inbox. The asking agent blocks at its prompt until a typed reply arrives.
curl -s -X POST "$GIT_PAW_BROKER_URL/publish" \
-H "Content-Type: application/json" \
-d '{"type":"agent.question","agent_id":"feat-auth","payload":{"question":"Should the JWT use RS256 or HS256 signing?"}}'
Feedback
A supervisor (or the broker’s auto-emitted [conflict-detector] voice) sends
a list of error messages to a target agent. The target agent_id field on the
envelope is the receiver; from inside the payload is the sender.
curl -s -X POST "$GIT_PAW_BROKER_URL/publish" \
-H "Content-Type: application/json" \
-d '{"type":"agent.feedback","agent_id":"feat-auth","payload":{"from":"supervisor","errors":["missing rustdoc on AuthClient::new","test for HS256 path is failing"]}}'
Verified
A supervisor confirms that an agent’s work has passed every verification gate.
The agent_id is the agent whose work was verified; verified_by names the
verifier.
curl -s -X POST "$GIT_PAW_BROKER_URL/publish" \
-H "Content-Type: application/json" \
-d '{"type":"agent.verified","agent_id":"feat-auth","payload":{"verified_by":"supervisor","message":"all five gates pass"}}'
Polling for Messages
Agents poll for messages from other agents using cursor-based pagination. The since parameter is a sequence number – the broker returns only messages with a sequence greater than the given value.
# First poll -- get all messages
curl -s "$GIT_PAW_BROKER_URL/messages/feat-auth?since=0"
The response includes a last_seq field. Pass this value as since on the next poll to get only new messages:
# Subsequent poll -- only new messages since last check
curl -s "$GIT_PAW_BROKER_URL/messages/feat-auth?since=42"
This cursor-based approach is lossless – no messages are missed between polls, regardless of timing.
Checking Overall Status
The /status endpoint returns a summary of all agents and their latest state:
curl -s "$GIT_PAW_BROKER_URL/status"
Multi-Repo Considerations
Each git-paw session runs its own broker. If you have multiple repos running sessions simultaneously, each needs a unique port:
# In repo-a/.git-paw/config.toml
[broker]
enabled = true
port = 9119
# In repo-b/.git-paw/config.toml
[broker]
enabled = true
port = 9120
The default port is 9119. The broker always binds to 127.0.0.1 (localhost only) and should never be exposed to the network.
Automatic Conflict Detection (v0.5.0)
When supervisor mode is active, the broker runs an in-process conflict
detector that auto-emits agent.feedback (tagged [conflict-detector] in the
errors array) and, for unresolved in-flight conflicts, escalates to the
supervisor inbox via agent.question. Three failure shapes are detected:
- Forward conflicts — two agents publish
agent.intentwith overlappingfiles. Both receiveagent.feedbacklisting the other agent and the overlapping paths. Toggle with[supervisor.conflict] warn_on_intent_overlap. - In-flight conflicts — an agent publishes
agent.statusoragent.artifactwhosemodified_filesoverlap with another agent’s active intent or recent status. The broker waits[supervisor.conflict] window_seconds(default 120) for one side to retract; if both sides keep modifying, the detector escalates to the supervisor inbox viaagent.question. - Ownership violations — an agent’s
modified_filesincludes a path the spec marks as owned by another change. The violator receivesagent.feedback; if[supervisor.conflict] escalate_on_violation = truethe supervisor inbox also receives a follow-upagent.question.
See the Conflict Detection chapter for the full
walkthrough — failure shapes, the [conflict-detector] tag, supervisor inbox
routing, and the configuration knobs.
Audit Trail
The broker writes all messages to .git-paw/broker.log as JSONL (one JSON object per line). This file is flushed every 5 seconds and provides a complete audit trail of agent communication.
The log file is automatically cleaned up by git paw purge. It is also covered by the .gitignore entry that git paw init creates.
Working Heartbeat
The broker’s filesystem watcher publishes agent.status whenever a file in a
worktree changes, which keeps the dashboard’s last_seen timestamp fresh during
active editing. The watcher cannot observe read-only tool uses (file reads,
greps, searches), permission-prompt waits, or LLM-only deliberation between tool
calls — so a long read-heavy investigation looks stuck on the dashboard even
though the agent is making progress.
To bridge that gap, the embedded coordination skill instructs agents to publish
a lightweight agent.status heartbeat every 5 tool uses while actively working:
curl -s -X POST http://127.0.0.1:9119/publish \
-H "Content-Type: application/json" \
-d '{"type":"agent.status","agent_id":"feat-auth","payload":{"status":"working","message":"reviewing auth tests","modified_files":[]}}'
The heartbeat reuses the existing agent.status shape — no new wire format is
introduced. The broker merges heartbeats with watcher-driven updates without
conflict.
Commit Cadence
The bundled coordination skill teaches a per-group commit cadence. When a
change has an OpenSpec-style tasks.md with numbered groups (## 1.,
## 2., …), the agent commits after every - [ ] item in a group is
- [x] — one group, one commit (by default) — before starting the next
group.
The skill bounds uncommitted work to roughly ten files at a time. If a
single group exceeds that mid-implementation, the agent splits into multiple
commits using a (part N of M) suffix:
feat(coverage): close per-scenario gaps for v0.5.0 (part 1 of 2)
feat(coverage): close per-scenario gaps for v0.5.0 (part 2 of 2)
Each commit uses a conventional-commit prefix (feat(<scope>):,
fix(<scope>):, docs(<scope>):, test(<scope>):, chore(<scope>):) — the
scope is typically the change name’s key word.
Per-group cadence protects against agent crashes, conflict mediation, and
/clear resets losing unbounded work, and it maps cleanly to the post-commit
hook’s agent.artifact { status: "committed" } event sequence the supervisor
consumes during verification.
Terminal Action — Commit Then Publish, Never Archive
The bundled coordination skill defines the coding agent’s terminal action as:
- A commit. The post-commit git hook auto-publishes
agent.artifact { status: "committed" }with the committed file list. For code changes this is the canonical “done” signal. - A manual
agent.artifact { status: "done" }(rare). Used only for code-less tasks or to announce namedexportspeers should cherry-pick.
The skill is explicit that the coding agent SHALL NOT invoke
/opsx:verify <change-id> or /opsx:archive <change-id> — both are
off-limits for the coding agent and are the supervisor’s job:
- Verification runs the supervisor’s five-gate framework (testing → regression
→ spec audit → doc audit → security audit) against the committed branch.
Self-verification by the coding agent bypasses gates and produces a
premature
agent.verifiedthe supervisor never reviewed. - Archiving happens on the release branch during the supervisor’s cherry-pick
- merge flow, not on the agent’s feature branch. Archiving from a feature branch leaves the change directory deleted on an unmerged branch and produces confused history.
This is a paw-specific rule for the bundled coordination skill. Single-agent
workflows that self-verify can override the rule via the standard skill
resolution chain (a user override at
<config_dir>/git-paw/agent-skills/coordination.md wins over the bundled
default).
Identifier Forms — Branch vs agent_id
Two related forms of an agent identifier appear throughout the broker protocol:
- Branch name — the original git ref (e.g.
feat/no-supervisor-flag). Used ingit checkout,git worktree,git push, and any other git command. agent_id— the dashed slug form (e.g.feat-no-supervisor-flag). Used in every/publishpayload, every/messages/<id>URL, and thetargetfield ofagent.feedbackandagent.questionpayloads.
agent_id is the slugified form of the branch name. The conversion (named
slugify_branch in the source) lowercases the input, replaces every character
outside [a-z0-9_] with -, collapses runs of -, trims leading and trailing
-, and falls back to the literal agent if the result is empty.
Match the form to the context: dashed agent_id in any JSON going to or coming
from the broker; slashed branch name in any shell command involving git.
Stash Hygiene in Worktrees
When multiple worktrees run side-by-side, every worktree shares the same
underlying git stash list. A git stash pop invoked without inspection can pop
an entry created by a different worktree, conflict with your in-progress
changes, and wipe work. The embedded coordination skill teaches agents three
rules:
- List before pop —
git stash listfirst; inspect every entry’s branch label and timestamp. - Inspect before pop —
git stash show -p stash@{N}to read the patch contents of the specific entry before popping. - Pop only your own — only pop entries you authored on the current
worktree. If authorship is uncertain, leave the stash alone and escalate via
agent.question.
Blind git stash pop is a data-loss pattern in a multi-worktree session and is
not recommended.
Supervisor Acknowledgement of agent.question
When an agent publishes agent.question, it blocks at its prompt waiting for a
typed reply. v0.5.0 agents do not poll their inbox for agent.feedback
responses, so a supervisor that only publishes agent.feedback to the broker
will see its answer recorded on the dashboard while the asking agent stays
blocked indefinitely.
The supervisor skill therefore instructs supervisors (both human and LLM) to
both publish agent.feedback and send the answer text to the asking
agent’s tmux pane via tmux send-keys. This dual write is transitional;
MCP-mediated inbox access in v0.6.0 will let agents consume agent.feedback
directly and remove the second step.
Spec Kit Consolidated Worktrees
When git-paw drives a Spec Kit project (.specify/specs/<feature>/), each feature’s current phase decomposes into multiple worktrees:
- One worktree per
[P]-marked task (branch prefixtask/). These are parallelisable. - One consolidated worktree per non-
[P]task group (branch prefixphase/). Non-[P]tasks share files or context, so a single agent works through them sequentially.
The embedded coordination skill picks up on the branch prefix:
task/<task-id>-<slug>branches: the agent runs the standard “before/while editing” coordination pattern for a single task.phase/<feature>-<phase-slug>branches: the agent:- Works through the listed tasks in
tasks.mdorder. - Flips
- [ ]to- [x]for each completed task in the worktree’stasks.md. The writeback can be a separate commit or bundled with the task’s code change. - Publishes
agent.intentfor the union of files across the next 1–2 tasks (with a generous TTL) rather than one publish per task. - Publishes
agent.artifactwithstatus: "done"only when every listed task shows- [x]intasks.md. Partial completion is not “done”.
- Works through the listed tasks in
When tasks.md is the merge-conflict surface between worktrees, git’s line-level merge handles per-task checkbox flips automatically. If two worktrees ever flip the same task ID, conflict detection (via agent.intent overlap) catches it upstream.
Workflow phases
The bundled coordination skill structures an agent’s editing work into two phases that mirror the skill’s “Before you start editing” and “While you’re editing” sections.
Before you start editing
Before touching any file, the agent:
- Reads the spec or task description in full to understand the scope.
- Publishes
agent.intentlisting the specific files it plans to modify, a one-line summary, and a TTL in seconds (default900= 15 minutes). This advertises ownership to the broker conflict detector so forward conflicts are caught before any edit lands. - Polls its inbox once for warnings or overlapping peer intents — not a busy loop, a single poll.
- Decides on overlap: if a peer’s intent already covers the same
files, the agent picks among wait (peer’s TTL is short, work is
small), split (narrow the file list to avoid overlap, re-publish
agent.intentwith the reduced scope), or escalate (publishagent.questiondescribing the overlap so the supervisor or human can decide). If no overlap is reported, the agent proceeds to edit immediately — there is no explicit go-ahead to wait for.
While you’re editing
Once editing is underway, the agent keeps the intent honest and asks rather than racing:
- Re-publish intent on scope growth. If the in-progress work touches
files that were not in the original
agent.intent, the agent re-publishesagent.intentwith the expandedfileslist before touching the new files. The re-published intent replaces the previous claim for downstream consumers. - Question on peer overlap. If a peer’s
agent.intentarrives in the inbox naming a file in the same module the agent is editing, the agent sendsagent.questiondescribing the overlap and pauses edits on the contested file. Silently racing the peer to a commit is forbidden.
The agent MUST NOT:
- Perform pairwise check-ins on every change — the broker is not a chat channel and peers are not waiting for status pings.
- Wait for an explicit go-ahead from peers when no conflict signal exists — silence from the broker means “no overlap detected”, not “permission pending”.
- Block on broker silence — if
agent.intentpolling returns no overlap, the agent proceeds.
Supervisor
This chapter mirrors the user-facing prose for the bundled
assets/agent-skills/supervisor.md skill — the doctrine the supervisor agent
runs against in supervisor mode. Sections here document the same rules the
embedded skill teaches, so users reading the mdBook can understand supervisor
behaviour without opening the skill file directly.
For the launcher-level “how do I start supervisor mode” walkthrough, see Quick Start: Supervisor Mode. For the broker-side message contract the supervisor exchanges with coding agents, see Agent Coordination.
Resolve Pane to Agent via pane_current_path
Before the supervisor tmux capture-panes or tmux send-keyss a specific
agent, it needs the pane index for that agent. The bundled supervisor skill
is explicit that pane indices are NOT alphabetical by agent_id, NOT in
the CLI-argument order from git paw start --specs A B C, and SHALL NOT be
inferred from git paw status output or the dashboard’s row order (both
of those are sorted alphabetically by the broker, which has no relationship
to the launcher’s internal scan order).
The canonical resolution command queries tmux directly:
tmux display-message -t paw-<project>:0.<pane> -p '#{pane_current_path}'
The output is the pane’s working directory. For coding-agent panes that is
the agent’s worktree path, whose basename ends in <project>-feat-<branch>
— the authoritative agent_id (with the slash form feat/<branch> for git
operations). A pane whose pane_current_path ends in myproj-feat-auth
belongs to agent feat-auth.
The supervisor agent builds the {pane_index → agent_id} map once per
session and reuses it; re-resolution only happens when the supervisor
notices an inconsistency.
The bundled .git-paw/scripts/sweep.sh invokes this command on every sweep
iteration. If the helper is missing for any reason, the supervisor falls
back to invoking tmux display-message directly — this is the documented
escape hatch.
The supervisor MUST NOT use git paw status output (or the dashboard’s row
order) as a mapping source — both are sorted alphabetically by the broker
and have no relationship to the launcher’s pane assignment. Always resolve
via pane_current_path first.
Spec audit governance sub-step
When a project’s .git-paw/config.toml lists governance documents under
[supervisor].governance.docs, the supervisor reads each doc as part of the
Spec Audit gate and flags drift between the diff and the doc’s checklist.
The five canonical doc-checklist examples are:
- DoD (Definition of Done) — walk each
- [ ]item against branch state. - ADRs (Architectural Decision Records) — verify new architectural decisions (new deps, new patterns) have a matching ADR.
- security.md — walk each security checklist item against the diff.
- test-strategy.md — check that test composition matches the documented strategy.
- constitution.md — check the diff against documented principles (e.g. “no panics in library code”).
Findings surface as standard agent.feedback errors tagged [doc audit]
mixed in with other doc-audit gaps. See Governance for the
config schema and how the supervisor reads each doc.
Common dev-command allowlist
A bundled preset whitelists routine dev commands so the supervisor stops
escalating every cargo test, cargo build, git commit, git push,
mdbook build, or broker curl on 127.0.0.1. The preset is on by default
and ships with the launcher.
To opt out for a session, set:
[supervisor.common_dev_allowlist]
enabled = false
To extend the preset with project-specific patterns (e.g. just, nox, a
custom test runner), use the extra field:
[supervisor.common_dev_allowlist]
enabled = true
extra = ["just check", "nox -s tests"]
extra patterns are prefix-matched against the captured command line, the
same way the built-in patterns are. See
Configuration for the full schema.
Repo-configurable gate commands
The supervisor’s five verification gates each invoke a configurable command
substituted from [supervisor] keys at session boot. The seven keys are:
test_commandlint_commandbuild_commandfmt_check_commanddoc_build_commandspec_validate_commandsecurity_audit_command
When a key is missing or empty, the placeholder renders as (not configured)
in the supervisor skill and the supervisor gracefully skips the tooling
invocation for that gate — the gate’s manual review still applies. See
Configuration for defaults and examples.
Broker-side conflict detector
Starting with v0.5.0 the broker auto-detects three failure shapes between
parallel agents and emits agent.feedback (and, where configured,
agent.question) on the supervisor’s behalf. All auto-emitted messages
begin with the [conflict-detector] token so the supervisor can distinguish
detector output from human-typed feedback. The three failure shapes are:
- Forward conflict — two agents publish overlapping
agent.intentdeclarations. - In-flight conflict — two agents’ filesystem-watched
modified_filessets overlap on the same file. - Ownership violation — an agent’s
modified_filesinclude a file inside another agent’s active intent.
See Conflict Detection for the algorithm, configuration, and escalation behaviour.
Learnings aggregator
When [supervisor.learnings] enabled = true, the supervisor session
records deterministic friction signals (sandbox warnings, approval
patterns, recurring errors) into a markdown file you can review after the
run. See Learnings Mode for the file format and how to
opt in.
When the user types in your pane
The supervisor pane is interactive — the user can type at any time while the autonomous monitoring loop is running. The supervisor finishes the current step (spec audit, test run), responds, then resumes the loop. User input is a high-priority interrupt, not a replacement for the loop.
Each kind of user input maps to an existing mechanism — the supervisor does not invent new channels:
- Status question (“how’s feat-auth going?”, “anything blocked?”) —
answered conversationally in the pane using
sweep.sh status,sweep.sh inbox, andsweep.sh capture <pane>. Nothing is published to the broker — this is a conversation with the user, not a session-wide event. - Directive (“ask feat-auth to use bcrypt”, “tell feat-api to skip
the migration”) — published as
agent.feedbackto the named agent with the[directive]gate prefix, plus a conversational confirmation to the user. - Judgment-call ask (“should we merge feat-a before feat-b?”) — the
supervisor applies its normal escalation rules. If the user has already
provided enough information to decide, the supervisor answers in the
pane using its reasoning.
agent.questiononly fires when the call is genuinely ambiguous beyond what the user just provided — typically when the user is asking because they don’t know either.
The mechanisms (curl /status, tmux capture-pane, agent.feedback,
tmux send-keys, agent.question) are unchanged. The addition is when
to use which in response to user input.
Merge orchestration
Once every spec’d agent has published agent.verified (or the user
explicitly asks for a merge), the supervisor runs the merge orchestration
loop. v0.5.0 removed the Rust auto-merge loop; merging is now the
supervisor’s responsibility, performed with the existing shell + curl
tools.
Trigger. Either every spec’d agent has published agent.verified, or
the user has explicitly requested the merge.
Merge order. The supervisor reads the broker’s message log
(/messages/supervisor) and builds a dependency graph from agent.blocked
events: each event from agent X with payload.from = Y is an edge “X
depends on Y”. The supervisor then topologically sorts the graph: agents
with no incoming edges merge first; dependents follow.
Per-branch merge. For each branch in topological order, the supervisor
checks out main and runs:
git merge --ff-only feat/<branch>
Never a merge commit — fast-forward only. If --ff-only fails (the branch
diverges from main, or there is a conflict), the supervisor SKIPS that
branch and publishes agent.feedback to the owning agent asking them to
rebase or resolve. On a successful fast-forward, the supervisor runs the
configured {{TEST_COMMAND}}; if tests fail, the supervisor reverts the
merge with git reset --hard <prev-HEAD> and publishes agent.feedback
tagged [regression].
Cycle handling. If the dependency graph has a cycle, the supervisor
does NOT merge any branch in the cycle. Instead, it publishes
agent.question to the human and waits for guidance before continuing.
Final summary. When the loop completes, the supervisor publishes a
final agent.status summarising which branches merged cleanly, which were
skipped (and why), and any regressions encountered.
Dashboard
When the broker is enabled, one tmux pane runs the dashboard instead of an agent CLI. In supervisor mode the dashboard lives at pane 1 (pane 0 hosts the supervisor CLI itself); in broker-only mode (broker on, supervisor off) the dashboard lives at pane 0. Either way it renders the same live status table that updates every second, giving you an at-a-glance view of what each agent is doing.
The dashboard is observation-only — the only keystroke it handles is q to quit. Human input (questions, directives, replies to agent.question events) happens in the supervisor pane itself; the dashboard simply renders broker state.
What the Dashboard Pane Shows
The dashboard renders a table with one row per agent. When a supervisor pane is running, its row is pinned to the top with a horizontal-line divider beneath it; coding-agent rows follow in alphabetical order:
┌────────────┬────────┬────────────┬─────────┬──────────────────────────────┐
│ Agent │ CLI │ Status │ Time │ Summary │
├────────────┼────────┼────────────┼─────────┼──────────────────────────────┤
│ supervisor │ claude │ 🔵 watching│ 12s ago │ session online │
│ ────────── │ ────── │ ────────── │ ─────── │ ──────────────────────────── │
│ feat-api │ claude │ 🟡 blocked │ 1m 05s │ waiting for auth token format│
│ feat-auth │ claude │ 🔵 working │ 3m 22s │ implementing login endpoint │
│ fix-typo │ gemini │ 🟢 done │ 8m 41s │ done — all typos fixed │
└────────────┴────────┴────────────┴─────────┴──────────────────────────────┘
When no supervisor pane is running (e.g. --no-broker is not in play but no --supervisor was passed, or during the boot window before the supervisor has finished self-registering), the divider is not rendered and coding agents fill rows alphabetically from the top.
Status Symbols
| Symbol | Meaning |
|---|---|
| 🔵 | Working – agent is actively processing |
| 🟢 | Done/verified – agent has completed its task |
| 🟣 | Committed – agent has committed work |
| 🟡 | Blocked – agent is waiting on something |
| ⚪ | Idle / unknown phase – agent has not reported a recognised status |
The Time column shows elapsed time since the agent’s last status update. The Summary column shows the most recent status or blocked message body.
Supervisor row, cli field, and phase field
The supervisor row’s Status column does not show the wire-message type label that a coding-agent row shows. Instead the supervisor publishes a phase field on its agent.status messages (e.g. baseline, watching, approving, answering, merging, summary), and the dashboard prefers that label when rendering its row. This avoids the misleading status=feedback label the supervisor would otherwise show when it publishes agent.feedback to a coding agent.
The supervisor pane is also not a watch target, so the broker cannot infer its cli from the watch-target map. To populate the CLI column for the supervisor row, the supervisor self-registration agent.status includes a cli field (e.g. "cli":"claude"). The broker upserts that value into its internal CLI map when it receives the message. Coding agents do not need to publish cli — the broker populates their CLI from the watch-target map at startup.
When the supervisor row appears
The supervisor row appears after the supervisor pane’s CLI has booted and published its first self-registration agent.status — typically within 3-5 seconds of git paw start --supervisor returning. There is no phantom supervisor row at launch time; if the supervisor pane fails to start, the row simply never appears. Aborted launches (non-TTY skip, missing CLI on PATH, system-level pane spawn failure) leave the agent table free of a misleading supervisor entry.
Controls
Press q to quit the dashboard. This shuts down the broker and terminates the dashboard process in the dashboard pane. The agent panes continue running – they simply lose the ability to communicate via the broker.
Broker Messages Panel
When enabled, the dashboard shows a broker messages panel at the bottom, displaying recent communication between agents and the broker for at-a-glance observability.
Enabling the Panel
Add this to your .git-paw/config.toml:
[dashboard]
show_message_log = true
Message Types
The panel shows six types of broker messages:
| Symbol | Type | Meaning |
|---|---|---|
| 📤 | Status | Agent status updates |
| 📦 | Artifact | Shared files/artifacts |
| 🚧 | Blocked | Agent blocked requests |
| ✅ | Verified | Supervisor verification |
| 💬 | Feedback | Supervisor feedback |
| ❓ | Question | Agent questions |
Example Layout
┌──────────┬────────┬────────┬─────────┬──────────────────────────────┐
│ Agent │ CLI │ Status │ Time │ Summary │
├──────────┼────────┼────────┼─────────┼──────────────────────────────┤
│ feat/auth│ claude │ 🔵 │ 3m 22s │ implementing login endpoint │
│ feat/api │ claude │ 🟡 │ 1m 05s │ waiting for auth token format│
│ fix/typo │ gemini │ 🟢 │ 8m 41s │ done — all typos fixed │
└──────────┴────────┴────────┴─────────┴──────────────────────────────┘
[14:30:22] agent-0 📤 working on login endpoint
[14:29:45] agent-1 📦 shared auth_schema.json
[14:28:10] agent-2 🚧 blocked: need API spec format
Each message shows timestamp (HH:MM:SS), agent ID, message type symbol, and content. The panel shows the 20 most recent messages.
Relationship to the Broker
The dashboard and broker run in the same process (git paw __dashboard). The dashboard reads from shared state that the broker’s HTTP handlers (and the watcher, conflict detector, and learnings aggregator subsystems) write to. There is no separate broker process to manage.
Replying to agent questions
Earlier dashboard versions included a “Questions” panel and a “Reply to” input field for human-typed answers to agent.question events. The panel was removed in v0.5.0 because the supervisor pane is the natural input surface — typed questions and replies go through tmux send-keys and the supervisor agent’s own curl machinery, not through the dashboard.
agent.question messages still flow through the broker. The supervisor pane polls the supervisor inbox, reads incoming questions, and replies via tmux send-keys to the asking agent’s pane (and via agent.feedback to the broker for the audit log). See the Supervisor mode chapter and the embedded supervisor.md skill for the reply flow.
See the v0.5.0 changelog for the removal note.
Pause and Resume
git paw pause is the soft-stop verb for short breaks (lunch, a
meeting, end-of-day). It freezes the running session without losing
agent state, so you can resume mid-conversation an hour later by
running git paw start.
The three teardown verbs
git-paw v0.5.0 ships three verbs for taking a session down:
| Verb | What it kills | What survives | Use when |
|---|---|---|---|
pause | Tmux client attach, broker process | Tmux session, all CLI panes (in RAM) | Short break — you’ll resume in minutes/hours |
stop | Tmux session, every CLI pane | Worktrees and branches on disk | Longer break — you want RAM back, OK with fresh CLIs later |
purge | Everything (tmux, worktrees, state) | Nothing | You’re done with the project, or you want to start clean |
A future git paw hibernate (v1.0.0) will snapshot tmux state and
each CLI’s conversation to disk, then kill the processes — combining
pause’s state preservation with stop’s RAM release.
What pause does, mechanically
When you run git paw pause:
- Every tmux client attached to the session is detached
(
tmux detach-client -s <session>). - The dashboard pane only is killed (
tmux kill-pane -t :0.<idx>), which causes the__dashboardsubprocess to exit, which drops theBrokerHandle, which gracefully shuts down the broker and flushesbroker.log. - The session state file flips from
status: activetostatus: paused. - Every coding-agent CLI pane keeps running. Their in-memory conversation, their CLI process, and the worktree they’re working in are untouched.
git paw status shows the paused state with a blue indicator and a
“run git paw start to resume” hint.
The RAM trade-off
Pause is fast and state-preserving, but the CLI processes stay allocated. A typical Claude Code instance holds ~300 MB, so a 10-pane session is roughly 3–5 GB of RAM sitting idle while paused.
Pick the right verb based on duration:
- Pause is right for short breaks where instant resume matters more than RAM.
- Stop is right for long breaks where you’d rather get the RAM
back. Resuming via
git paw startspawns fresh CLI processes — you lose conversation context but the worktrees and branches carry over. - Hibernate (future v1.0.0) will be both: state preserved AND RAM released.
Resuming a paused session
git paw start
When git paw start detects a paused session that’s still alive in
tmux, it takes the restart-from-pause path:
- Re-creates the dashboard pane at its saved index.
- Sends the
git paw __dashboardcommand to spawn the broker subprocess again. - Flips session status back to
active. - Re-attaches your tmux client.
Cost: one tmux pane spawn + one broker boot. No worktree creation, no CLI process spawn, no boot-prompt injection. The agent panes are exactly as you left them — open conversations intact, prompt buffer intact.
If the tmux server died while paused (rare — typically only happens
on machine reboot or tmux kill-server), git paw status shows
the session as stopped instead, and git paw start falls through to
the normal cold-recovery path (fresh CLI spawn).
Idempotency
git paw pause is safe to run repeatedly:
- Pausing an already-paused session prints “Session ‘NAME’ is already paused.” and exits 0 without changing state.
- Pausing a stopped session prints “Session ‘NAME’ is already stopped; pause has no effect.” and exits 0.
- Pausing with no session for the current repo prints “No active session for this repo.” and exits 0.
Future: per-CLI cold resume (drift 61)
For CLIs that support --continue / --resume (Claude Code, etc.),
v1.0.0 will extend the cold-recovery path so git paw start after a
stop can also restore conversation context — by spawning the CLI
with the resume flag. That solves the long-break case without
holding RAM, complementing pause for the short-break case.
See also
git paw stop— the destructive teardown verb with its new confirmation prompt.git paw purge— the full reset (removes worktrees and branches).- Dashboard — what the dashboard pane shows while the session is active.
Skill Templates
git-paw uses standardized agent skills following the agentskills.io specification. Skills are directories containing a SKILL.md file with YAML frontmatter and optional resource subdirectories.
Standard Location
Skills are loaded from .agents/skills/ in your project directory. git-paw walks up the directory tree from the current working directory to find this location.
my-project/
└── .agents/
└── skills/
├── coordination/
│ ├── SKILL.md # Main skill file
│ ├── scripts/ # Optional: Executable scripts
│ ├── references/ # Optional: Documentation
│ └── assets/ # Optional: Templates/resources
└── supervisor/
├── SKILL.md
└── scripts/
Skill Format
Each skill must contain a SKILL.md file with YAML frontmatter:
---
name: my-skill
description: A brief description of what this skill does
license: MIT
compatibility: git-paw v0.4.0+
---
## My Skill Instructions
This skill helps agents with {{BRANCH_ID}} workflows...
Required Fields
name: Skill name (max 64 chars, lowercase letters/numbers/hyphens only)description: Clear description of the skill’s purpose (max 1024 chars)
Optional Fields
license: License informationcompatibility: Version compatibilitymetadata: Custom metadata object
Placeholders
Skills support these placeholders that get replaced at runtime:
{{BRANCH_ID}}- Slugified branch name (e.g.,feat/http-broker→feat-http-broker){{PROJECT_NAME}}- Project name for tmux session{{GIT_PAW_BROKER_URL}}- Full broker URL{{SKILL_NAME}}- Name from YAML frontmatter{{SKILL_DESCRIPTION}}- Description from YAML frontmatter
Supervisor gate-command placeholders
The embedded supervisor skill uses seven additional placeholders fed from
[supervisor].*_command keys in .git-paw/config.toml. Each gate-command
template renders verbatim into the skill prose where the supervisor agent
reads it:
{{TEST_COMMAND}}←[supervisor].test_command— gate 1 (Testing) test runner{{LINT_COMMAND}}←[supervisor].lint_command— gate 1 lint sub-step{{BUILD_COMMAND}}←[supervisor].build_command— gate 1 build sub-step{{FMT_CHECK_COMMAND}}←[supervisor].fmt_check_command— gate 1 formatter check{{DOC_BUILD_COMMAND}}←[supervisor].doc_build_command— gate 4 (Doc audit){{SPEC_VALIDATE_COMMAND}}←[supervisor].spec_validate_command— gate 3 (Spec audit){{SECURITY_AUDIT_COMMAND}}←[supervisor].security_audit_command— gate 5 (Security audit)
(not configured) graceful skip. When a key is omitted from
[supervisor], the matching placeholder substitutes to the literal string
(not configured) in the rendered skill. The supervisor agent treats that
sentinel as “skip the tooling invocation for this gate” and continues with
the gate’s manual review only (e.g. the OWASP-category diff scan still runs
for the security gate, the spec scenario coverage check still runs for the
spec gate). Pre-v0.5.x configs that only set test_command continue to
render the remaining gates as (not configured) and the supervisor agent
runs them as manual-only — no behavior change for those configs.
{{CHANGE_ID}} is per-invocation, not per-render. Spec validators
typically take a change name as argument (e.g. openspec validate my-change-id --strict). To support that, the spec_validate_command
template MAY embed the literal substring {{CHANGE_ID}}. git-paw does
not substitute {{CHANGE_ID}} at session boot — it passes through the
render verbatim. The supervisor agent expands it at verification time using
the change name it is currently auditing. This matches how {{BRANCH_ID}}
behaves for coding agents (per-agent, not per-render).
Resource Subdirectories
Skills can include optional resource subdirectories:
scripts/- Executable scripts referenced by the skillreferences/- Detailed documentation and referencesassets/- Templates, configuration files, and other resources
Example structure:
.agents/skills/my-skill/
├── SKILL.md # Main instructions (< 500 lines)
├── scripts/
│ └── setup.sh # Executable helper script
├── references/
│ └── api-reference.md # Detailed API documentation
└── assets/
└── config-template.json
Creating Custom Skills
To add a custom skill:
# Create skill directory structure
mkdir -p .agents/skills/my-skill
# Create SKILL.md with proper frontmatter
cat > .agents/skills/my-skill/SKILL.md << 'EOF'
---
name: my-skill
description: Custom workflow for our team
license: MIT
compatibility: git-paw v0.4.0+
---
## Custom Team Workflow
Follow these steps for {{BRANCH_ID}}:
1. Analyze requirements
2. Implement solution
3. Test thoroughly
4. Document changes
EOF
# Add optional resource directories
mkdir -p .agents/skills/my-skill/scripts
mkdir -p .agents/skills/my-skill/references
Skill Resolution
git-paw searches for skills in this order:
.agents/skills/<name>/SKILL.md(walking up directory tree from current directory)- Embedded defaults (compiled into git-paw binary)
The first match wins. If no skill is found, resolution fails with an error.
Validation
Skills are validated against the agentskills.io specification:
- Required
nameanddescriptionfields must be present - YAML frontmatter must be valid
- Skill directory must contain SKILL.md file
- Clear error messages for validation failures
Examples
See the agentskills.io specification for more examples and best practices.
Migration from Older Versions
If you’re upgrading from git-paw v0.2.x or earlier:
- Move skills from
~/.config/git-paw/agent-skills/to.agents/skills/ - Convert single
.mdfiles to directory structure with SKILL.md - Add required YAML frontmatter to each skill
- Organize related resources into subdirectories
The new standardized format improves interoperability and enables skill sharing across different AI systems that support the agentskills.io standard.
When Skills Are Not Injected
Skill templates are only injected when the broker is enabled ([broker] enabled = true). If the broker is disabled, no coordination instructions are added to AGENTS.md.
Boot-Prompt Injection
In addition to skill template injection, git-paw automatically injects a standardized boot instruction block into every agent’s initial prompt. This ensures reliable agent self-reporting even if skill templates are not used or if agents don’t read the AGENTS.md file thoroughly.
The boot-prompt injection includes pre-expanded curl commands for all essential coordination operations (register, done, blocked, question) and is active in both supervisor and manual broker modes. See the Coordination documentation for details.
Governance
git-paw can read your team’s existing governance documents as context for the supervisor agent — ADRs, a test strategy, a security checklist, a Definition of Done, and a project constitution. You point at the docs in .git-paw/config.toml; git-paw does not generate or vendor any of them.
Why governance docs
The supervisor is an LLM. It does the right thing more often when it can see the rules the team has already written down: which architectural decisions are settled, what tests are expected, what security review looks like, what “done” actually means. Without that context the supervisor has to infer from the diff alone, and inference drifts.
git-paw’s stance on governance is deliberately thin:
- You own the documents. Their structure, format, and rubric are whatever your team already uses (Scrum, XP, OWASP,
adr-tools, Spec Kit, hand-rolled). git-paw does not template them. - You opt in per doc. Empty
[governance]table, all fieldsNone, no behaviour change from v0.4. Add only the docs you have. - The supervisor applies judgment. There is no
[governance.gates]table and no per-doc enforcement switch. The supervisor reads each configured doc as context during its audit and surfaces relevant findings viaagent.feedback.
Pointing at your docs
Add [governance] to .git-paw/config.toml:
[governance]
adr = "docs/adr"
test_strategy = "docs/test-strategy.md"
security = "docs/security-checklist.md"
dod = "docs/definition-of-done.md"
constitution = ".specify/memory/constitution.md"
All five fields are optional. List only the docs you have. Paths are resolved relative to the repository root; absolute paths are accepted as-is. A missing file does not break config-load — the runtime flags it if the supervisor tries to read it.
For Spec Kit projects, governance.constitution auto-wires to .specify/memory/constitution.md when [specs] type = "speckit". You only need to set constitution explicitly if you keep it somewhere else, or want to disable the auto-wiring (set it to "").
See Configuration → Governance for the full field reference and merging rules.
Illustrative examples
The shapes below are examples, not templates. git-paw never reads structure — only the content of the file you point at. Use whatever format your team already uses.
ADR-0001 — Adopt PostgreSQL for the primary store
# ADR-0001: Adopt PostgreSQL for the primary store
Status: Accepted
Date: 2026-02-14
Deciders: backend team
## Context
We need a primary datastore for user, session, and billing tables.
Options considered: PostgreSQL, MySQL, CockroachDB, DynamoDB.
## Decision
We will use PostgreSQL 16 hosted on our existing managed service.
## Consequences
- All new schema lives in PostgreSQL; we will not introduce a second
relational store without a follow-up ADR.
- Migrations go through `sqlx-migrate`; ad-hoc DDL in code review is
rejected by default.
- Read replicas are an operational concern, not an application one —
applications connect through the connection pool, not directly to
replicas.
A typical ADR directory has one file per decision (0001-postgres.md, 0002-event-bus.md, …). Whether you use Nygard, MADR, or your own headings does not matter — git-paw passes the directory pointer to the supervisor, which reads the files it finds.
Definition of Done
# Definition of Done
A change is "done" when every box below is checkable:
- [ ] All new behaviour has at least one test covering the happy path
and one covering the failure mode.
- [ ] `just check` passes locally and in CI.
- [ ] Public functions have rustdoc comments.
- [ ] If a config field was added, the configuration docs section
that owns it is updated.
- [ ] If a CLI flag was added, `--help` text and `cli-reference.md`
are updated.
- [ ] If user-visible behaviour changed, the changelog has an entry.
- [ ] The PR description names the spec/issue it implements and
lists any deviations.
Anything left unchecked goes in the PR description as a known
follow-up with an owner.
Security checklist
# Security Checklist
For every change touching authentication, authorisation, network I/O,
or persisted data:
- [ ] User input is validated at the boundary (HTTP handler or CLI
arg parser), not in the business logic.
- [ ] Secrets never appear in logs, error messages, telemetry, or
stack traces. The redaction helpers in `crate::log::redact`
are applied at the producer side.
- [ ] No new dependency on `unsafe` crates without a written
justification in the PR description.
- [ ] If the change introduces a new external request, the URL is
built with a typed builder, never with `format!` over user
input.
- [ ] Authorization checks happen before side effects — never after.
Test strategy
# Test Strategy
## Pyramid
We invest most heavily in fast, deterministic tests:
- **Unit tests** (`#[cfg(test)] mod tests {}`) — pure logic, no I/O.
Every public function in `src/` has at least one.
- **Integration tests** (`tests/`) — exercise CLI boundaries with
`assert_cmd`. Use real filesystems via `tempfile`, never mocks.
- **End-to-end smoke tests** (`tests/e2e/`) — kicked off in CI for
the happy path of each subcommand. Slow and few; tagged with
`#[ignore]` so contributors can opt in locally.
## What we do not test
- Generated output of `--help` strings (already covered by clap).
- Rendering loops in the TUI — covered manually via the smoke list
in `docs/src/user-guide/dashboard.md`.
## Test data
Always synthesise — never copy production data, even anonymised, into
fixtures. Fixtures live under `tests/fixtures/` and are kept small
enough to read at a glance.
Constitution (Spec Kit-style)
# Project Constitution
## Spec-driven
No behaviour ships without a spec. The spec is the contract; the
implementation matches the spec; the tests assert the spec. If the
implementation drifts from the spec, the spec is updated first and
re-reviewed.
## Behavioural tests, not implementation tests
Tests assert observable inputs and outputs. Tests do not assert
internal struct field values, internal function calls, or mock
interactions.
## One commit per logical change
Every commit builds, passes `just check`, and is independently
revertable. PRs may contain multiple commits, but no commit may leave
the tree broken.
Spec Kit users typically keep this file at .specify/memory/constitution.md; git-paw auto-detects it when [specs] type = "speckit".
What the supervisor does
When the supervisor verifies an agent’s change, it reads the configured governance documents alongside the diff. Findings flow through the existing agent.feedback channel — the supervisor does not crash or block on governance, it surfaces what it sees and lets the agent respond.
The runtime side of this — boot-prompt injection of the governance doc paths and the supervisor’s audit handling — lives in the parallel governance-context capability. This chapter and the [governance] config table are the path-pointer slot only.
Rollout suggestion
Adopt incrementally — there is no requirement to fill in all five paths at once:
- Start with the doc you already have. Point
governance.dodat your existing DoD, orgovernance.constitutionat your principles doc. - Run a supervised session. Note which findings feel useful and which feel noisy.
- Add the next doc. Each pointer narrows the gap between what the supervisor knows and what the team already agreed on.
- If the team does not have one of these docs at all, write the smallest version you can live with rather than copying a template. The supervisor reads what you wrote — not a generic checklist.
You do not need a full governance framework to benefit from this. A two-paragraph DoD pointed at by governance.dod is more valuable than a perfect-but-empty [governance] table.
Learnings Mode
Learnings mode records deterministic friction signals from a supervisor
session into a markdown file you can review after the run. It is an opt-in
v0.5.0 feature: it requires supervisor mode to be active and the
[supervisor] learnings = true flag to be set explicitly. The output is
file-only in v0.5.0; a programmatic agent.learning broker variant is
deferred to v0.6.0.
Contents
- Why
- Enabling Learnings Mode
- Output File
- The Five Categories
- Sample Output
- Flush Cadence
- Roadmap:
agent.learning(v0.6.0)
Why
Supervisor runs absorb a lot of recurring friction silently: sandbox warnings the agent retries past, approvals you reflexively click, brief stuck states, conflicts caught and resolved before they hit your eyes. Each event is too small to interrupt for, but the pattern is the most useful signal git-paw can surface for tool, prompt, or process improvement.
Learnings mode aggregates those events into five deterministic categories and writes them to a markdown file you can read between sessions — turning silent friction into something you can act on.
Enabling Learnings Mode
Set the master switch on the [supervisor] table (default false):
[supervisor]
enabled = true
learnings = true
The subsystem only activates when supervisor mode itself is active. With
[supervisor] enabled = false (or no [supervisor] section), the
learnings = true value is parsed and ignored — no aggregation runs and
no file is written.
Output File
When active, the learnings subsystem writes to:
.git-paw/session-learnings.md
The file lives at the repository root (next to .git-paw/broker.log and
the session state). It is:
- Append-only across sessions. Subsequent supervisor runs add new entries below previous ones; nothing is overwritten or pruned.
- Human-readable markdown. No JSON or binary; you can
tail,grep, or open it in any editor between sessions. - Not committed by default.
git paw initadds it to the project’s.gitignorealongside the other.git-paw/runtime files.
The Five Categories
v0.5.0 tracks five deterministic categories. Each entry includes a timestamp, the agent involved (when applicable), and a one-line summary.
1. Stuck duration
An agent’s last_seen exceeds the configured stall threshold without
producing a new agent.status, agent.artifact, or agent.intent
message. Records how long the agent was stuck and what the supervisor
or auto-approver did to recover it (sweep, pane capture, no-op).
Trigger condition: (now - agent.last_seen) > stall_threshold AND the
agent’s most recent status is non-terminal (done, verified, blocked,
and committed are excluded; those are intentional resting states).
2. Recovery-cycle count
How many auto-approve sweeps (or supervisor-driven tmux send-keys
recovery actions) were needed before the agent published a fresh status
message. A high count for a single agent across a run usually means the
auto-approve allowlist is missing a prefix that agent’s CLI keeps tripping
on.
Trigger condition: incremented once per sweep dispatch against a pane; flushed when the agent finally publishes a non-stale message.
3. Forward conflicts
Two agents declared agent.intent payloads with overlapping files
before either committed. Records the agent pair and the overlapping paths.
Use this category to spot specs that were decomposed too coarsely (two
parallel agents both expected to own the same file).
Trigger condition: [supervisor.conflict] warn_on_intent_overlap = true
AND the broker conflict detector emitted [conflict-detector]-tagged
agent.feedback for the overlap.
4. In-flight conflicts
Two agents have overlapping modified_files in active agent.status or
agent.artifact payloads — the second agent committed (or is about to)
while the first still considers the path active. Records the agent pair,
the overlapping paths, and whether the conflict resolved within
[supervisor.conflict] window_seconds or escalated to the supervisor
inbox via agent.question.
Trigger condition: any in-flight overlap (forward intent already missing
or expired). Escalation is recorded separately when
window_seconds elapses without resolution.
5. Ownership violations
An agent’s modified_files includes a path the spec marks as owned by
another change. Records the violating agent, the touched path, and the
owning change ID. Use this category to spot agents that drifted out of
their declared scope — usually a sign the spec body in AGENTS.md did
not make the ownership boundary obvious enough.
Trigger condition: ownership match against the OpenSpec / Markdown / Spec Kit ownership declaration parsed at session start.
Sample Output
A short illustrative excerpt (timestamps abbreviated for readability):
# Session learnings — paw-myproject
## 2026-05-13 14:30 — supervisor run start
### Stuck duration
- 14:32:18 — feat-auth — stuck for 42s after permission prompt;
recovered by auto-approve sweep (`cargo test` allowlist hit).
- 14:38:51 — feat-api — stuck for 118s on rebase conflict prompt;
recovered manually after supervisor `tmux send-keys`.
### Recovery-cycle count
- feat-auth — 3 sweeps before fresh status.
- feat-api — 7 sweeps; investigate auto-approve prefixes.
### Forward conflicts
- feat-auth ↔ feat-api — overlap on `src/auth/middleware.rs`
(warned via agent.feedback; both retracted before commit).
### In-flight conflicts
- feat-api ↔ feat-billing — overlap on `src/router.rs`;
resolved by feat-billing pause within window_seconds.
### Ownership violations
- feat-api modified `src/auth/jwt.rs` (owned by add-auth);
blocked at agent.feedback; escalated to supervisor inbox.
## 2026-05-13 16:05 — supervisor run start
...
The exact section ordering and bullet shape may evolve across patch releases; the category set and the underlying triggers above are stable for the v0.5.0 release.
Flush Cadence
The aggregator buffers entries in memory and flushes to disk on an interval (default 60s):
[supervisor.learnings_config]
flush_interval_seconds = 60
A shorter interval makes the file fresher (useful when you want to
tail -f the file in another terminal); a longer interval batches more
entries per write. The file is also flushed at supervisor shutdown so
nothing is lost between sessions even if the interval has not elapsed.
See Configuration → Learnings mode tuning for the field reference.
Roadmap: agent.learning (v0.6.0)
v0.5.0 ships learnings as file output only. The agent.learning broker
variant — a wire-format message agents and tools can publish and consume
via the broker — is intentionally deferred to v0.6.0 alongside MCP-mediated
inbox access. Until then, downstream consumers should parse the markdown
file rather than poll the broker.
Conflict Detection
When supervisor mode is active, the broker runs an in-process conflict
detector that watches for three failure shapes across parallel agents.
Detected conflicts surface as [conflict-detector]-tagged agent.feedback
delivered to the involved agents, and — for unresolved in-flight shapes —
as agent.question escalations to the supervisor inbox. The detector is
automatic; you only opt out by setting [supervisor] enabled = false (or
tuning the knobs in [supervisor.conflict]).
Contents
- The Three Failure Shapes
- The
[conflict-detector]Tag - Supervisor Inbox Routing
- Interaction with the Filesystem Watcher
- Configuration Knobs
The Three Failure Shapes
Forward conflict
Two agents publish agent.intent payloads whose files arrays overlap.
The conflict is forward because it surfaces before either agent commits
— intent is the early-warning channel.
Trigger. Any non-empty intersection between two active intents (an
intent stays active until its valid_for_seconds TTL expires, the agent
publishes a fresh intent, or the agent commits).
Action. Each agent receives an agent.feedback with the
[conflict-detector] tag in its errors[0], naming the peer and listing
the overlapping paths. Neither side blocks; the receiving agents decide
how to retract or reshape their plans.
Toggle. [supervisor.conflict] warn_on_intent_overlap (default
true). When false, the detector still records intents (so in-flight
detection keeps working) but no agent.feedback fires for forward shape.
In-flight conflict
One agent publishes agent.status or agent.artifact whose
modified_files overlap with another agent’s active intent — or another
agent’s recent status / artifact. The conflict is in-flight because at
least one side is already writing.
Trigger. Any non-empty intersection between an agent.status /
agent.artifact modified_files array and another agent’s active intent
or status (whichever is freshest).
Action. Both agents receive [conflict-detector]-tagged
agent.feedback. The detector starts a window_seconds timer; if no
side retracts before it elapses, the detector escalates to the supervisor
inbox via agent.question (see Supervisor Inbox Routing).
Window. [supervisor.conflict] window_seconds (default 120).
Ownership violation
An agent’s modified_files (in agent.status or agent.artifact)
touches a path that the spec marks as owned by a different change. The
ownership map is built once at session start from the change directories’
Files owned: / Owned files: declarations.
Trigger. Any path in modified_files matches an ownership entry that
points to a change other than the sending agent’s.
Action. The violator receives agent.feedback describing the touched
path and the owning change. When
[supervisor.conflict] escalate_on_violation = true (default), the
supervisor inbox also receives a follow-up agent.question so a human
can decide whether to override the boundary or block the work.
The [conflict-detector] Tag
Every auto-emitted agent.feedback from the detector starts its errors
array with a fixed tag:
{
"type": "agent.feedback",
"agent_id": "feat-auth",
"payload": {
"from": "supervisor",
"errors": [
"[conflict-detector] forward conflict: feat-api also declares intent over src/auth/middleware.rs",
"..."
]
}
}
The [conflict-detector] prefix distinguishes detector output from
human-typed supervisor feedback. Agents (and dashboards) that filter or
classify feedback can match on the tag without parsing payload semantics.
The detector publishes from the "supervisor" agent ID (the from field
in the payload) — same source as human-authored supervisor feedback —
because routing and display logic already specialise on the supervisor
identity. The tag, not the source, is the discriminator.
Supervisor Inbox Routing
When an in-flight conflict has not resolved within window_seconds, the
detector escalates to the supervisor by publishing an agent.question
addressed to the supervisor (not to either of the conflicting agents).
The supervisor pane sees the question in its broker inbox and can:
- Type a reply, which the supervisor skill forwards to both involved
agents via
tmux send-keys(the same dual-write pattern documented in Agent Coordination § Supervisor Acknowledgement). - Resolve the conflict directly by editing one agent’s intent or pausing the offending agent until the other side commits.
Ownership-violation escalations follow the same routing. Forward conflicts do not escalate by default — they are advisory.
Interaction with the Filesystem Watcher
The broker’s filesystem watcher publishes agent.status (with a fresh
modified_files array) whenever a tracked file changes in a worktree.
The conflict detector consumes these auto-published status messages, so
in-flight conflicts surface as soon as edits land on disk — no manual
agent.status curl required from the agent.
The watcher is read-only with respect to git (it watches the working
tree, not the index), so the detector sees overlaps the instant a file
is modified, even before git add or git commit. This is the
mechanism that makes “in-flight” meaningfully earlier than the
post-commit hook’s agent.artifact { status: "committed" }.
Configuration Knobs
All knobs live under [supervisor.conflict] in .git-paw/config.toml:
[supervisor.conflict]
window_seconds = 120
warn_on_intent_overlap = true
escalate_on_violation = true
| Field | Default | Description |
|---|---|---|
window_seconds | 120 | Seconds to wait before escalating an unresolved in-flight conflict to the supervisor inbox via agent.question. |
warn_on_intent_overlap | true | Forward-conflict feedback toggle. When false, intents are still tracked but no agent.feedback is emitted on intent overlap. |
escalate_on_violation | true | Ownership-violation escalation toggle. When false, the violator still receives agent.feedback, but no follow-up agent.question lands in the supervisor inbox. |
The [supervisor.conflict] table is fully optional. Setting
[supervisor] enabled = false (or omitting the section) disables the
detector subsystem entirely — no auto-emitted feedback fires regardless
of the values above. See Configuration → Conflict detector tuning
for the canonical field reference.
Configuration
git-paw uses TOML configuration files at two levels, with repo-level settings overriding global ones.
Config File Locations
| Level | Path | Purpose |
|---|---|---|
| Global | ~/.config/git-paw/config.toml | Default CLI, custom CLIs, global presets |
| Per-repo | .git-paw/config.toml (in repo root) | Repo-specific overrides |
Both files are optional. git-paw works with sensible defaults when no config exists.
Full Config Example
# Default CLI used when --cli flag is not provided
default_cli = "my-cli"
# Default CLI for spec-mode launches (--from-all-specs, --specs); bypasses picker when set
# default_spec_cli = "my-cli"
# Prefix for spec-derived branch names (default: "spec/")
# branch_prefix = "spec/"
# Enable mouse mode in tmux sessions (default: true)
mouse = true
# Custom CLI definitions
[clis.my-agent]
command = "/usr/local/bin/my-agent"
display_name = "My Agent"
[clis.local-llm]
command = "ollama-code"
display_name = "Local LLM"
# Named presets for quick launch
[presets.backend]
branches = ["feature/api", "fix/db"]
cli = "claude"
[presets.frontend]
branches = ["feature/ui", "feature/styles"]
cli = "codex"
# Spec scanning configuration
# [specs]
# dir = "specs"
# type = "openspec" # "openspec", "markdown", or "speckit"
# Session logging
# [logging]
# enabled = false
# Agent coordination broker
# [broker]
# enabled = false
# port = 9119
# bind = "127.0.0.1"
# Pointers to user-maintained governance docs (all optional)
# [governance]
# adr = "docs/adr"
# test_strategy = "docs/test-strategy.md"
# security = "docs/security-checklist.md"
# dod = "docs/definition-of-done.md"
# constitution = ".specify/memory/constitution.md"
Settings Reference
default_cli
The AI CLI to use when --cli is not passed and you want to skip the CLI picker.
default_cli = "my-cli"
default_spec_cli
The AI CLI to use by default when launching with --from-all-specs or --specs. When set, skips the CLI picker for any specs that don’t have a paw_cli override.
default_spec_cli = "my-cli"
See Spec-Driven Launch for the full CLI resolution chain.
branch_prefix
Prefix prepended to spec-derived branch names. Defaults to "spec/".
branch_prefix = "spec/"
For example, a spec with ID add-auth produces branch spec/add-auth.
mouse
Enable or disable tmux mouse mode for git-paw sessions. When enabled, you can click panes to switch, drag borders to resize, and scroll with the mouse wheel. This is set per-session and does not affect your other tmux sessions.
mouse = true # default
Custom CLIs
Register custom AI CLIs that aren’t in git-paw’s built-in detection list.
Via config file
[clis.my-agent]
command = "/usr/local/bin/my-agent" # absolute path
display_name = "My Agent" # optional, shown in prompts
[clis.local-llm]
command = "ollama-code" # binary name (resolved via PATH)
display_name = "Local LLM"
Via command line
# Add with absolute path
git paw add-cli my-agent /usr/local/bin/my-agent
# Add with binary name on PATH
git paw add-cli my-agent my-agent
# Add with display name
git paw add-cli my-agent my-agent --display-name "My Agent"
# Remove
git paw remove-cli my-agent
The add-cli and remove-cli commands modify the global config at ~/.config/git-paw/config.toml.
Listing CLIs
git paw list-clis
Shows both auto-detected and custom CLIs with their source:
Name Path Source
claude /usr/local/bin/claude detected
codex /usr/local/bin/codex detected
my-agent /usr/local/bin/my-agent custom
Presets
Presets save branch + CLI combinations for one-command launch.
Defining presets
[presets.backend]
branches = ["feature/api", "fix/db-migration"]
cli = "claude"
[presets.full-stack]
branches = ["feature/api", "feature/ui", "feature/styles"]
cli = "gemini"
Using presets
git paw start --preset backend
This skips all interactive prompts and launches with the preset’s branches and CLI.
Specs
Configure spec file scanning for --from-all-specs and --specs mode.
[specs]
dir = "specs" # Directory containing spec files (relative to repo root)
type = "openspec" # "openspec" (OpenSpec changes), "markdown" (flat .md files), or "speckit" (GitHub Spec Kit)
| Field | Default | Description |
|---|---|---|
dir | "specs" | Directory to scan for spec files |
type | "openspec" | Spec backend: "openspec" (directory-based OpenSpec changes), "markdown" (flat .md files with YAML frontmatter), or "speckit" (GitHub Spec Kit .specify/specs/<feature>/) |
When [specs] is omitted and .specify/specs/ exists at the repo root, the
spec backend auto-detects to type = "speckit" with
dir = ".specify/specs". Use the --specs-format CLI flag to override both
the config value and the auto-detection for a single launch.
See Spec-Driven Launch for format details.
Logging
Configure session output logging.
[logging]
enabled = true
| Field | Default | Description |
|---|---|---|
enabled | false | Whether to capture pane output to log files |
When enabled, logs are written to .git-paw/logs/<session>/ using tmux pipe-pane. See Session Logging for details.
Broker
Configure the HTTP broker for agent coordination. When enabled, git-paw starts a lightweight HTTP server that lets agents share status updates, artifacts, and blocked requests.
[broker]
enabled = true
port = 9119
bind = "127.0.0.1"
| Field | Default | Description |
|---|---|---|
enabled | false | Whether to start the coordination broker |
port | 9119 | HTTP port for the broker server |
bind | "127.0.0.1" | Bind address – never bind to 0.0.0.0 on shared machines |
When the broker is enabled, git-paw injects the GIT_PAW_BROKER_URL environment variable into each agent pane, pointing to http://<bind>:<port>. Agents use this URL to communicate with the broker.
Multi-repo port assignment
If you run git-paw sessions for multiple repositories at the same time, each session needs a different port. Set a unique port in each repo’s .git-paw/config.toml:
# Repo A
[broker]
enabled = true
port = 9119
# Repo B (in its own .git-paw/config.toml)
[broker]
enabled = true
port = 9120
See Agent Coordination for usage details.
Supervisor
Configure the supervisor agent for orchestrating parallel coding sessions. When enabled, the supervisor monitors agents, runs tests, verifies work, and coordinates merges.
[supervisor]
enabled = true
cli = "claude"
test_command = "just check"
lint_command = "cargo clippy -- -D warnings"
build_command = "cargo build"
fmt_check_command = "cargo fmt --check"
doc_build_command = "mdbook build docs/"
spec_validate_command = "openspec validate {{CHANGE_ID}} --strict"
security_audit_command = "cargo audit"
agent_approval = "auto"
| Field | Default | Description |
|---|---|---|
enabled | false | Whether to use supervisor mode by default (can also use --supervisor flag, or override with --no-supervisor for a single session) |
cli | (uses default_cli) | CLI binary for the supervisor agent |
test_command | (none) | Test runner — gate 1 (e.g. "just check", "cargo test", "npm test", "pytest") |
lint_command | (none) | Lint check — gate 1 (e.g. "cargo clippy -- -D warnings", "npm run lint", "ruff check .", "golangci-lint run") |
build_command | (none) | Compile step — gate 1 when build is distinct from test (e.g. "cargo build", "npm run build", "mvn package", "go build ./...") |
fmt_check_command | (none) | Formatter check — gate 1 (e.g. "cargo fmt --check", "prettier --check .", "gofmt -l .", "black --check .") |
doc_build_command | (none) | Documentation build — gate 4 (e.g. "mdbook build docs/", "sphinx-build", "mkdocs build") |
spec_validate_command | (none) | Spec validator — gate 3 (e.g. "openspec validate {{CHANGE_ID}} --strict" for OpenSpec). {{CHANGE_ID}} is substituted by the supervisor agent at verification time with the change name being audited; it is not expanded at config load |
security_audit_command | (none) | Security audit tooling — gate 5 (e.g. "cargo audit", "npm audit", "bandit -r .", "gosec ./...") |
agent_approval | "auto" | Permission level for coding agents: "manual", "auto", or "full-auto" |
Gate-command templating. The seven *_command keys feed the supervisor
skill’s five verification gates (testing, regression analysis, spec audit, doc
audit, security audit). For each key set on this section, the supervisor skill
substitutes the matching {{...}} placeholder at session boot and the
supervisor agent runs the literal command during that gate. For each key
omitted, the placeholder renders as (not configured) and the supervisor
agent skips that tooling step — the gate’s manual review still applies (e.g.
the OWASP-category diff scan for the security gate, the spec scenario
coverage check for the spec gate). Pre-v0.5.x configs that did not name any
of the six new keys continue to work; they just run a less-rigorous
verification cycle until the keys are filled in. A user wanting to explicitly
opt out of a single gate’s tooling can set the field to "(not configured)"
verbatim — the supervisor agent recognises that as the same skip token.
Resolution chain — git-paw picks supervisor mode using the first matching rule:
--no-supervisor→ off (highest precedence; overrides everything below).--supervisor→ on.[supervisor] enabled = true→ on.[supervisor] enabled = false→ off.- No
[supervisor]section +--dry-run→ off. - No
[supervisor]section + interactive TTY → prompts you. - No
[supervisor]section + non-TTY → off.
--supervisor and --no-supervisor are mutually exclusive — passing both produces a parse error.
Approval levels:
| Level | Behavior |
|---|---|
manual | Agents prompt for every action (safest, slowest) |
auto | CLI default behavior — some prompts, some auto-approved |
full-auto | Skip all permission prompts (fastest, agents run unattended) |
The supervisor translates the approval level into CLI-specific flags at launch (e.g. --dangerously-skip-permissions for Claude in full-auto mode).
Auto-approve safe permission prompts
When supervisor mode is enabled, git-paw can automatically approve common,
known-safe permission prompts (cargo test, git commit, broker curl calls, etc.)
in stalled agent panes so the supervisor does not have to dismiss every prompt by hand.
[supervisor.auto_approve]
enabled = true
safe_commands = ["just lint", "just test"]
stall_threshold_seconds = 30
approval_level = "safe"
| Field | Default | Description |
|---|---|---|
enabled | true | Master switch for auto-approval. Set to false to disable. |
safe_commands | [] | Project-specific command prefixes appended to the built-in defaults. |
stall_threshold_seconds | 30 | Seconds an agent’s last_seen must lag before its pane is polled (minimum 5). |
approval_level | "safe" | Coarse preset: "off", "conservative", or "safe". |
Built-in safe commands: cargo fmt, cargo clippy, cargo test, cargo build,
git commit, git push, curl http://127.0.0.1:.
Approval-level presets:
| Preset | Behavior |
|---|---|
off | Forces enabled = false. No detection or approval runs. |
conservative | Drops git push and curl from the effective whitelist. |
safe (default) | Approve every entry in the built-in whitelist plus configured extras. |
How it works: when an agent’s status is non-terminal (done, verified, blocked,
committed are skipped) and its last_seen exceeds the threshold, git-paw runs
tmux capture-pane, classifies the pending command, and either dispatches
BTab Down Enter (if safe) or publishes an agent.question to the supervisor inbox
(if not).
git-paw also seeds .claude/settings.json::allowed_bash_prefixes with the broker
endpoints (/publish, /status, /poll, /feedback) so the first broker call
never hits a permission prompt. Existing entries in that file are preserved.
Common dev-command allowlist
On every supervisor session start, git-paw seeds a curated preset of dev-loop
prefix patterns into .claude/settings.json::allowed_bash_prefixes so agents
do not hit a permission prompt for each variant of cargo build, git commit,
just check, mdbook build, etc. The mechanism is the same one Claude uses
for its “Yes, don’t ask again” flow — but seeded up-front rather than approved
one-by-one.
[supervisor.common_dev_allowlist]
enabled = true
extra = ["pnpm test", "deno fmt"]
| Field | Default | Description |
|---|---|---|
enabled | true | Master switch for the seeder. Set to false to skip seeding entirely. |
extra | [] | Additional project-specific prefix patterns appended to the built-in preset. |
Built-in preset (all v0.5.0 entries):
- Cargo:
cargo build,cargo test,cargo clippy,cargo fmt,cargo check,cargo tree,cargo deny,cargo update - Git (read):
git status,git log,git diff,git show,git fetch - Git (write, non-destructive):
git commit,git push,git pull,git merge,git stash,git add,git restore,git rm - Just:
just(any recipe) - mdBook:
mdbook build - OpenSpec:
openspec validate,openspec new,openspec archive,openspec list,openspec status,openspec instructions - Search (read-only):
find,grep,sed -n
Intentional exclusions: cargo install, cargo run, cargo bench,
git rebase, git reset, git checkout, git push --force, sed without
-n, and non-cargo package managers (npm, pnpm, yarn, deno, bun,
uv, pip, pipx, gem). Add them via extra if you accept the wider
surface for your project.
Behaviour:
- Independent of broker status — non-broker supervisor sessions still benefit.
- Idempotent: re-seeding on session re-attach never duplicates entries.
- Non-fatal: write failures log a warning to stderr and session start continues.
- Targets
<repo>/.claude/settings.jsonalways; also writes~/.claude-oss/settings.jsonwhen that directory pre-exists (the alt-config dogfood pattern) but never creates the directory. - Entries persist after
git paw stop— prune.claude/settings.jsonmanually if you want a clean slate.
Conflict detector tuning
When supervisor mode is enabled, the broker runs an in-process conflict
detector that auto-emits agent.feedback (and optionally agent.question)
on forward, in-flight, and ownership conflicts. See
Agent Coordination § Automatic Conflict Detection for the runtime semantics; the table below
documents the configuration surface.
[supervisor.conflict]
window_seconds = 120
warn_on_intent_overlap = true
escalate_on_violation = true
| Field | Default | Description |
|---|---|---|
window_seconds | 120 | Seconds the detector waits before escalating an unresolved in-flight conflict to the supervisor inbox via agent.question. |
warn_on_intent_overlap | true | Master switch for forward-conflict feedback. When false, two agents declaring overlapping agent.intent files no longer trigger agent.feedback, but the intent tracker still records them (so in-flight and ownership detection continue to work). |
escalate_on_violation | true | Whether ownership violations escalate to the supervisor inbox. When false, the violator still receives agent.feedback, but no follow-up agent.question lands in the supervisor inbox. |
The [supervisor.conflict] table is fully optional. A v0.4 config with
[supervisor] and no [supervisor.conflict] loads cleanly with every field
at the defaults above. Setting [supervisor] enabled = false (or omitting
the section) disables the detector subsystem entirely — no auto-emitted
warnings fire regardless of the values here.
Learnings mode tuning
When supervisor mode is active, the parent [supervisor] learnings = true
flag (default false) activates the learnings subsystem. Entries are
appended to .git-paw/session-learnings.md covering the five deterministic
categories tracked in v0.5.0 (stuck duration, recovery-cycle count, forward
conflicts, in-flight conflicts, ownership violations). The
[supervisor.learnings_config] sub-table tunes the flush cadence; the
master switch lives on the parent table.
[supervisor]
learnings = true
[supervisor.learnings_config]
flush_interval_seconds = 60
| Field | Default | Description |
|---|---|---|
flush_interval_seconds | 60 | How often the learnings aggregator flushes accumulated entries from memory to .git-paw/session-learnings.md. The file is append-only across sessions; a longer interval batches more entries per write. |
See the Learnings Mode chapter for the
category-by-category walkthrough, the output-file format, and the v0.6.0
roadmap for programmatic access via the agent.learning broker variant.
Governance
Point git-paw at your project’s existing governance documents so the supervisor can read them as context. All fields are optional — list only the docs you have.
[governance]
adr = "docs/adr" # directory of ADR files
test_strategy = "docs/test-strategy.md" # single Markdown file
security = "docs/security-checklist.md" # single Markdown file
dod = "docs/definition-of-done.md" # single Markdown file
constitution = ".specify/memory/constitution.md" # single Markdown file
| Field | Kind | Description |
|---|---|---|
adr | directory | Architecture Decision Records. git-paw does not care which convention (Nygard, MADR, adr-tools) — point at the folder where they live. |
test_strategy | file | The team’s test-strategy document. |
security | file | Security checklist (OWASP-style, project-specific, whatever the team uses). |
dod | file | Definition of Done for completed work. |
constitution | file | Project constitution. Spec Kit users normally let this auto-wire (see below). |
git-paw does not dictate the structure, format, or rubric of any of these documents. The supervisor LLM reads them as context and applies judgment during its existing audit flow. There is no [governance.gates] table and no per-doc enforcement switch — gating-per-doc would require git-paw to define “failure” for each doc type, and that is a process choice your team owns.
Paths are stored verbatim and resolved against the repository root at use time. Relative paths point at files inside the repo; absolute paths are accepted as-is. A path that does not exist still loads cleanly — git-paw does not stat the filesystem at config-load. If you point at a missing file, the runtime consumer flags it.
Spec Kit constitution auto-wiring
When governance.constitution is unset AND [specs] type = "speckit", git-paw probes for <specs_dir>/../memory/constitution.md and, if present, populates governance.constitution automatically. This means a typical Spec Kit project (with .specify/specs/ and .specify/memory/constitution.md) gets the constitution wired up without any [governance] entry.
Explicit values always win. If governance.constitution is set to anything — including a path that does not exist or an empty string — auto-wiring is skipped:
[governance]
constitution = "" # disables auto-wiring without deleting the slot
Auto-wiring only runs for the Spec Kit backend. With [specs] type = "openspec", type = "markdown", or no [specs] section, governance.constitution stays whatever the TOML says (defaulting to None).
What the supervisor does with these paths
This [governance] table is the storage slot. The runtime consumer — boot-prompt injection so the supervisor can read each doc and apply it to its audit — lives in the parallel governance-context capability. See the Governance chapter of the user guide for what that looks like end-to-end.
Dashboard
Configure the dashboard TUI rendered in pane 0 when the broker is enabled.
[dashboard]
show_message_log = true
| Field | Default | Description |
|---|---|---|
show_message_log | false | When true, the dashboard renders a scrolling broker-message panel above the prompts section. Useful for watching live agent traffic; leave false for a more compact layout. |
See Dashboard for details.
Multi-repo configuration
Each repository can have its own dashboard settings in .git-paw/config.toml. The repo-level config overrides the global config.
Merging Rules
When both global and repo configs exist, they merge with these rules:
| Field | Merge behavior |
|---|---|
default_cli | Repo wins |
default_spec_cli | Repo wins |
branch_prefix | Repo wins |
mouse | Repo wins |
clis | Maps merge (repo overrides per-key) |
presets | Maps merge (repo overrides per-key) |
specs | Repo wins |
logging | Repo wins |
broker | Repo wins |
supervisor | Repo wins |
dashboard | Repo wins |
governance | Per-field merge (repo wins on each set field, unset fields fall back to global) |
Example: If global config defines [clis.my-agent] and repo config defines [clis.my-agent] with a different command, the repo version wins. But a [clis.other-tool] in global config still appears — maps are merged, not replaced.
Graceful Absence
If no config files exist, git-paw uses defaults:
- No default CLI (prompts for selection)
- Mouse mode enabled
- No custom CLIs
- No presets
Supported AI CLIs
git-paw auto-detects these AI coding CLIs on your PATH:
| CLI | Binary | Description | Install |
|---|---|---|---|
| Claude Code | claude | Anthropic’s AI coding assistant | npm i -g @anthropic-ai/claude-code |
| Codex | codex | OpenAI’s coding agent | npm i -g @openai/codex |
| Gemini CLI | gemini | Google’s Gemini in the terminal | npm i -g @anthropic-ai/gemini-cli |
| Aider | aider | AI pair programming in the terminal | pip install aider-chat |
| Vibe | vibe | Mistral AI’s coding CLI | See project docs |
| Qwen | qwen | Alibaba’s Qwen coding CLI | See project docs |
| Amp | amp | Sourcegraph’s AI coding agent | See project docs |
How Detection Works
git-paw scans your PATH for each known binary name. If found, it records the full path and makes the CLI available for selection.
Detection runs every time you start a session, so newly installed CLIs are picked up automatically.
Adding Custom CLIs
Any AI CLI not in the list above can be registered as a custom CLI:
# Register by path
git paw add-cli my-agent /usr/local/bin/my-agent
# Register by binary name (resolved via PATH)
git paw add-cli my-agent my-agent --display-name "My Agent"
Custom CLIs appear alongside detected ones in the selection prompt. See Configuration for more details.
Deduplication
If a custom CLI has the same binary name as a detected one, the custom definition takes precedence. This lets you override the path or display name of a detected CLI.
Missing CLIs
If a custom CLI’s command cannot be found (the binary doesn’t exist at the specified path and isn’t on PATH), it is excluded from the selection list with a warning. This prevents launching sessions that would immediately fail.
CLI Reference
git-paw is invoked as git paw (or git-paw). Below is the reference for all subcommands and flags.
git paw
Running with no subcommand is equivalent to git paw start.
Parallel AI Worktrees — orchestrate multiple AI coding CLI sessions across git worktrees
Usage: git-paw [COMMAND]
Commands:
start Launch a new session or reattach to an existing one
pause Soft-stop: detach client, stop broker, keep CLIs running
stop Stop the session (kills tmux, keeps worktrees and state)
purge Remove everything (tmux session, worktrees, and state)
status Show session state for the current repo
list-clis List detected and custom AI CLIs
add-cli Register a custom AI CLI
remove-cli Unregister a custom AI CLI
init Initialize the repository for git-paw (creates .git-paw/)
replay Replay a captured pane log (requires session logging)
help Print this message or the help of the given subcommand(s)
Options:
-h, --help Print help
-V, --version Print version
git paw init
Initializes a repository for git-paw. Creates the .git-paw/ directory, a default config.toml, the logs directory, and sets up .gitignore.
Usage: git-paw init
Options:
-h, --help Print help
Running init is idempotent — it’s safe to run multiple times.
What it creates:
.git-paw/config.toml— default configuration.git-paw/logs/— log directory (added to.gitignore)
Example:
git paw init
git paw start
Smart start: reattaches if a session is active, recovers if stopped/crashed, or launches a new interactive session.
Usage: git-paw start [OPTIONS]
Options:
--cli <CLI> AI CLI to use (skips CLI picker)
--branches <BRANCHES> Comma-separated branches (skips branch picker)
--from-all-specs Launch from every discovered spec across all configured formats
--specs [<NAMES>...] Comma-separated spec names; bare flag opens picker (TTY required)
--specs-format <FORMAT> Override spec backend: openspec, markdown, speckit
--dry-run Preview the session plan without executing
--preset <PRESET> Use a named preset from config
--supervisor Run the session in supervisor mode (auto-start agents,
run test_command between merges, write session summary)
--no-supervisor Disable supervisor for this session, overriding any
`[supervisor] enabled = true` in config
--force With `--from-all-specs`/`--specs`, bypass the uncommitted-spec warning
--no-rebase Skip rebasing existing agent branches onto the default branch
-h, --help Print help
| Flag | Accepted values | Purpose |
|---|---|---|
--cli | name of a detected or custom CLI | Skip the interactive CLI picker; assign this CLI to every agent that doesn’t otherwise pin one. |
--branches | comma-separated branches | Skip the interactive branch picker; launch one worktree per branch. |
--from-all-specs | (flag) | Launch every discovered spec across the configured backend. Mutually exclusive with --specs. |
--specs | comma-separated spec names; bare flag opens a multi-select picker (TTY required) | Narrow the session to named specs or open the picker. Mutually exclusive with --from-all-specs. |
--specs-format | openspec, markdown, speckit | Override [specs] type in config and the .specify/ auto-detection for this launch. |
--dry-run | (flag) | Print the session plan; create no worktrees and run no tmux commands. |
--preset | preset name from config | Use a named [presets.<name>] entry. |
--supervisor | (flag) | Force supervisor mode on. Mutually exclusive with --no-supervisor. |
--no-supervisor | (flag) | Force supervisor mode off (highest precedence in the resolution chain). Mutually exclusive with --supervisor. |
--force | (flag) | Bypass the uncommitted-spec validation warning when launching from specs. |
--no-rebase | (flag) | Skip the default-on rebase of existing agent branches onto the repository’s default branch. |
--from-all-specs and --specs are mutually exclusive — one launches every
discovered spec, the other narrows to a subset or opens the picker.
Examples:
git paw start
git paw start --cli claude
git paw start --cli claude --branches feat/auth,feat/api
git paw start --dry-run
git paw start --preset backend
# Launch every discovered spec
git paw start --from-all-specs
git paw start --from-all-specs --cli claude
git paw start --from-all-specs --dry-run
# Narrow to specific specs or open the multi-select picker
git paw start --specs add-auth,fix-session
git paw start --specs # interactive picker (requires a TTY)
# Skip supervisor for this session even when `[supervisor] enabled = true` is set
git paw start --no-supervisor
git paw start --from-all-specs --no-supervisor
Supervisor mode resolution chain
git-paw decides whether to enter supervisor mode using this order (first match wins):
--no-supervisorflag present → supervisor disabled (no prompt, regardless of config).--supervisorflag present → supervisor enabled (no prompt).[supervisor] enabled = truein config → supervisor enabled (no prompt).[supervisor] enabled = falsein config → supervisor disabled (no prompt).- No
[supervisor]section +--dry-run→ supervisor disabled (skip prompt). - No
[supervisor]section + interactive TTY → prompt “Start in supervisor mode?”. - No
[supervisor]section + non-TTY → supervisor disabled (fallback).
--supervisor and --no-supervisor are mutually exclusive at parse time; passing both is rejected by clap before any command runs.
See Spec-Driven Launch for details on spec formats and configuration.
git paw pause
Soft-stops the session: detaches the tmux client, stops the broker, and leaves every CLI pane running in the background. Preserves agent conversation state for instant resume via git paw start. RAM stays allocated (~300 MB per Claude pane).
Use pause for short breaks (lunch, meetings, end-of-day). For longer breaks, use git paw stop to kill the CLIs and release RAM. See Pause and Resume for the full trade-off discussion.
Usage: git-paw pause
Options:
-h, --help Print help
Example:
git paw pause
Idempotent: pausing an already-paused or already-stopped session is a friendly no-op.
git paw stop
Kills the tmux session and every CLI pane process, but preserves worktrees and session state on disk. CLI conversation context is lost. Run git paw start later to recover the session with fresh CLI processes.
v0.5.0 change: stop now prompts for confirmation when stdin is a TTY. Pass --force to skip the prompt (scripts); non-TTY contexts (CI, pipes) bypass the prompt automatically for v0.4 back-compat.
Usage: git-paw stop [OPTIONS]
Options:
--force Skip confirmation prompt
-h, --help Print help
Examples:
git paw stop # prompts in TTY, bypasses in non-TTY
git paw stop --force # always bypasses the prompt
When the session is currently paused, the confirmation prompt additionally warns that continuing will kill the still-running CLIs.
git paw purge
Nuclear option: kills the tmux session, removes all worktrees, and deletes session state. When the broker was enabled, also removes broker.log. Requires confirmation unless --force is used.
Usage: git-paw purge [OPTIONS]
Options:
--force Skip confirmation prompt
-h, --help Print help
Examples:
git paw purge
git paw purge --force
git paw status
Displays the current session status, branches, CLIs, and worktree paths for the repository in the current directory. When the broker is enabled, also shows the broker URL and connected agent count.
Usage: git-paw status
Options:
-h, --help Print help
Example:
git paw status
git paw list-clis
Shows all AI CLIs found on PATH (auto-detected) and any custom CLIs registered in your config.
Usage: git-paw list-clis
Options:
-h, --help Print help
Example:
git paw list-clis
git paw add-cli
Adds a custom CLI to your global config (~/.config/git-paw/config.toml). The command can be an absolute path or a binary name on PATH.
Usage: git-paw add-cli [OPTIONS] <NAME> <COMMAND>
Arguments:
<NAME> Name to register the CLI as
<COMMAND> Command or path to the CLI binary
Options:
--display-name <DISPLAY_NAME> Display name shown in prompts
-h, --help Print help
Examples:
git paw add-cli my-agent /usr/local/bin/my-agent
git paw add-cli my-agent my-agent --display-name "My Agent"
git paw remove-cli
Removes a custom CLI from your global config. Only custom CLIs can be removed — auto-detected CLIs cannot.
Usage: git-paw remove-cli <NAME>
Arguments:
<NAME> Name of the custom CLI to remove
Options:
-h, --help Print help
Example:
git paw remove-cli my-agent
git paw replay
Replay captured session logs. Requires logging to be enabled.
Usage: git-paw replay [OPTIONS] [BRANCH]
Arguments:
[BRANCH] Branch to replay (fuzzy-matched against log filenames)
Options:
--list List available log sessions and branches
--color Display with colors via less -R
--session <SESSION> Session to replay from (defaults to most recent)
-h, --help Print help
Examples:
# List all logged sessions and branches
git paw replay --list
# Replay a branch (stripped of ANSI codes)
git paw replay feat/add-auth
# Replay with colors
git paw replay feat/add-auth --color
# Replay from a specific session
git paw replay feat/add-auth --session paw-my-project
Exit Codes
| Code | Meaning |
|---|---|
| 0 | Success |
| 1 | Error (git, tmux, config, or other failure) |
| 2 | User cancelled (Ctrl+C or empty selection) |
Architecture
This chapter covers git-paw’s internal architecture: module structure, data flow, and key design decisions.
Module Diagram
┌─────────────────────────────────────────────────────────────────┐
│ main.rs │
│ (entry point, dispatch) │
├──────────┬──────────────┬──────────────┬─────────────┬───────────┤
│ cli.rs │ interactive │ config.rs │ error.rs │ dirs.rs │
│ (clap) │ (dialoguer) │ (TOML) │ (PawError) │ (XDG) │
├──────────┴──────────────┴──────────────┴─────────────┴───────────┤
│ │
│ detect.rs git.rs tmux.rs session.rs logging.rs │
│ (PATH scan) (worktrees) (builder) (JSON state) (pane logs) │
│ │
│ agents.rs skills.rs init.rs replay.rs │
│ (AGENTS.md) (skill (project (log │
│ templates) bootstrap) playback) │
├───────────────────────────────────────────────────────────────────┤
│ broker/ supervisor/ specs/ │
│ ├── mod.rs ├── mod.rs ├── mod.rs │
│ ├── server.rs ├── approve.rs ├── openspec.rs│
│ ├── messages.rs ├── auto_approve.rs ├── markdown.rs│
│ ├── delivery.rs ├── curl_allowlist.rs ├── speckit.rs │
│ ├── conflict.rs ├── dev_allowlist.rs └── resolve.rs │
│ ├── learnings.rs ├── layout.rs │
│ ├── watcher.rs ├── permission_prompt.rs │
│ └── publish.rs ├── poll.rs │
│ └── stall.rs │
└───────────────────────────────────────────────────────────────────┘
Module Responsibilities
| Module | File | Purpose |
|---|---|---|
| CLI | src/cli.rs | Argument parsing with clap v4 derive macros. Defines all subcommands, flags (--from-all-specs, --specs, --specs-format, --supervisor, --no-supervisor, --force, …), and help text. |
| Detection | src/detect.rs | Scans PATH for known AI CLI binaries (KNOWN_CLIS). Resolves custom CLIs from config. Merges and deduplicates. |
| Git | src/git.rs | Validates git repos, lists branches (local + remote, deduplicated), creates/removes worktrees, derives safe directory names. |
| Tmux | src/tmux.rs | Builder pattern for tmux operations. Creates sessions, splits panes, sends commands, applies the supervisor-as-pane layout, sets pane titles. |
| Session | src/session.rs | Persists session state to JSON files under ~/.local/share/git-paw/sessions/. Atomic writes, crash recovery. |
| Config | src/config.rs | Parses TOML from global (~/.config/git-paw/config.toml) and per-repo (.git-paw/config.toml). Merges with repo-wins semantics. |
| Interactive | src/interactive.rs | Terminal prompts via dialoguer. Mode picker, branch multi-select, CLI picker. Skips prompts when flags are provided. |
| Error | src/error.rs | PawError enum with thiserror. Actionable error messages and distinct exit codes. |
| Dirs | src/dirs.rs | In-tree platform XDG path helper. Replaces the upstream dirs crate (removed in v0.5.0 for license reasons); see AGENTS.md § Dependencies. |
| Agents | src/agents.rs | Generates worktree AGENTS.md files; manages the <!-- git-paw:start … end --> marker region; supports the boot-prompt-full-body model. |
| Skills | src/skills.rs | Loads standardized agent skills from .agents/skills/ following the agentskills.io specification. Injects coordination + supervisor instructions into worktree AGENTS.md. |
| Init | src/init.rs | git paw init bootstrap. Creates .git-paw/, default config, logs directory, gitignore entries. Auto-detects .specify/ for Spec Kit. |
| Replay | src/replay.rs | git paw replay. Reads pane logs from .git-paw/logs/ and either strips ANSI or pipes through less -R. |
| Logging | src/logging.rs | Per-pane log capture via tmux pipe-pane. Files at .git-paw/logs/<session>/<branch>.log. |
| Broker | src/broker/ | HTTP coordination server (axum) with watcher + conflict detector + learnings subsystems. Detail below. |
| Supervisor | src/supervisor/ | Supervisor-mode subsystems (auto-approve, dev allowlist, stall sweeps, permission prompts, pane layout). Detail below. |
| Specs | src/specs/ | Spec scanning. Three backends (openspec, markdown, speckit); resolve.rs is the dispatch entry point. |
src/broker/ modules
| File | Purpose |
|---|---|
src/broker/mod.rs | Public surface (start/stop entry points, shared state types). |
src/broker/server.rs | axum HTTP server: /publish, /messages/:agent_id, /status. |
src/broker/messages.rs | BrokerMessage enum + payload types + slug validation. Source of truth for the wire format used in user-facing examples. |
src/broker/publish.rs | Validation + sequence assignment for incoming /publish calls. |
src/broker/delivery.rs | Routing layer: which inboxes a message lands in (broadcast, supervisor inbox, targeted delivery). |
src/broker/watcher.rs | Filesystem watcher that auto-publishes agent.status (with modified_files) whenever a tracked file changes in a worktree. |
src/broker/conflict.rs | Forward / in-flight / ownership conflict detection. Auto-emits [conflict-detector]-tagged agent.feedback and escalates via agent.question. |
src/broker/learnings.rs | Opt-in learnings subsystem. Aggregates the five deterministic categories and flushes to .git-paw/session-learnings.md. |
src/dashboard.rs (top-level, not inside src/broker/) renders the dashboard
pane — the live status table and the optional message-log panel — by reading
the shared broker state. The dashboard pane sits at pane index 1 in supervisor
mode (see the layout diagram below) and at pane 0 in non-supervisor broker
mode.
src/supervisor/ modules
| File | Purpose |
|---|---|
src/supervisor/mod.rs | Supervisor boot — composes the subsystems below and drives the supervisor pane. |
src/supervisor/approve.rs | Generic approval/feedback decision plumbing shared by the auto-approver. |
src/supervisor/auto_approve.rs | Safe-command auto-approver against stalled panes (approval_level, safe_commands, sweeps). |
src/supervisor/curl_allowlist.rs | Seeds the broker curl endpoints into .claude/settings.json::allowed_bash_prefixes so the first broker call never hits a permission prompt. |
src/supervisor/dev_allowlist.rs | Seeds the curated [supervisor.common_dev_allowlist] preset (cargo / git / just / mdBook / OpenSpec) into .claude/settings.json. |
src/supervisor/layout.rs | Supervisor-as-pane tmux layout: pane 0 supervisor, pane 1 dashboard, agent panes 2 onwards in the bottom-row grid (row-height proportions documented below). |
src/supervisor/permission_prompt.rs | Pane classification for permission-prompt detection (tmux capture-pane parsing). |
src/supervisor/poll.rs | Stalled-pane polling loop driving the auto-approver. |
src/supervisor/stall.rs | Stall heuristics (last-seen window, approval-level filter). |
src/specs/ modules
| File | Purpose |
|---|---|
src/specs/mod.rs | Public surface for the spec subsystem. |
src/specs/resolve.rs | Dispatch entry point. Picks the backend from [specs] type, the --specs-format CLI override, or .specify/ auto-detection. |
src/specs/openspec.rs | OpenSpec backend: scans <dir>/<change>/tasks.md directories, skips <dir>/archive/. |
src/specs/markdown.rs | Markdown backend: scans flat .md files with YAML frontmatter; only paw_status: pending is picked up. |
src/specs/speckit.rs | Spec Kit backend: scans .specify/specs/<feature>/, decomposes the current phase into [P]-task worktrees plus one consolidated phase/… worktree; probes <dir>/../memory/constitution.md for the governance auto-wire. |
Start Flow
The start command is the primary flow. Here’s what happens step by step:
git paw start
│
▼
┌─ Check for existing session ──────────────────────┐
│ │
│ Session active + tmux alive? ──yes──► Reattach │
│ │ no │
│ Session saved + tmux dead? ──yes──► Recover │
│ │ no │
│ No session ──────► Fresh start │
└─────────────────────────────────────────────────────┘
│
▼ (fresh start)
┌─ Validate git repo ─────────────────────────────────┐
│ git.validate_repo() → repo root path │
└──────────────────────────────────────────────────────┘
│
▼
┌─ Load config ────────────────────────────────────────┐
│ config.load_config() → merged PawConfig │
└──────────────────────────────────────────────────────┘
│
▼
┌─ Detect CLIs ────────────────────────────────────────┐
│ detect.detect_clis() → Vec<CliInfo> │
│ (auto-detected + custom, deduplicated) │
└──────────────────────────────────────────────────────┘
│
▼
┌─ Interactive selection ──────────────────────────────┐
│ interactive.run_selection() │
│ → Vec<(branch, cli)> mappings │
│ (skipped if --cli + --branches provided) │
└──────────────────────────────────────────────────────┘
│
▼
┌─ Create worktrees ───────────────────────────────────┐
│ git.create_worktree() for each branch │
│ → ../project-branch-name/ directories │
└──────────────────────────────────────────────────────┘
│
▼
┌─ Build tmux session ────────────────────────────────┐
│ TmuxSessionBuilder │
│ .session_name("paw-project") │
│ .pane(branch, worktree, cli) × N │
│ .mouse(true) │
│ .build() → TmuxSession with command sequence │
└──────────────────────────────────────────────────────┘
│
▼
┌─ Mode? ─────────────────────────────────────────────┐
│ supervisor → Pane 0 = supervisor CLI │
│ Pane 1 = `git paw __dashboard` │
│ Pane 2..N = per-spec agent CLIs │
│ broker-only → Pane 0 = `git paw __dashboard` │
│ Pane 1..N = per-branch agent CLIs │
│ no broker → Pane 0..N = per-branch agent CLIs │
│ │
│ In every broker mode the dashboard pane: │
│ ├─ Starts axum HTTP server on configured port │
│ ├─ Injects GIT_PAW_BROKER_URL into all agent panes │
│ └─ Renders the ratatui status table │
└──────────────────────────────────────────────────────┘
│
▼
┌─ Save session state ────────────────────────────────┐
│ session.save_session() → atomic JSON write │
└──────────────────────────────────────────────────────┘
│
▼
┌─ Attach ─────────────────────────────────────────────┐
│ tmux.attach() → user enters tmux session │
└──────────────────────────────────────────────────────┘
Broker Architecture
When [broker] enabled = true, the dashboard pane runs git paw __dashboard. This single process hosts both the HTTP broker and the dashboard TUI. The dashboard pane sits at pane 1 in supervisor mode and at pane 0 in non-supervisor broker mode.
Dashboard pane process (git paw __dashboard):
├── tokio runtime (background threads)
│ ├── axum HTTP server on localhost:9119
│ │ ├── POST /publish
│ │ ├── GET /messages/:agent_id?since=N
│ │ └── GET /status
│ ├── Filesystem watcher (src/broker/watcher.rs)
│ │ └── Auto-publishes agent.status on file changes
│ ├── Conflict detector (src/broker/conflict.rs)
│ │ └── Forward / in-flight / ownership shapes
│ └── Learnings aggregator (src/broker/learnings.rs)
│ └── Opt-in; flushes to .git-paw/session-learnings.md
├── Flush thread (std::thread, 5s interval)
│ └── Appends to broker.log
└── Main thread
└── ratatui dashboard (1s tick)
Broker state
The broker state is held in Arc<Mutex<...>> by src/broker/mod.rs and shared
between the axum server handlers, the watcher, the conflict detector, the
learnings aggregator, and the ratatui dashboard render loop. The server writes
incoming messages (validated and sequenced by src/broker/publish.rs, routed
by src/broker/delivery.rs); the dashboard reads the latest snapshot each
tick.
The flush thread periodically serializes the message log to
.git-paw/broker.log as a JSONL audit trail. This runs on a plain
std::thread to avoid contention with the tokio runtime.
Environment injection
When the broker is enabled, git-paw sets GIT_PAW_BROKER_URL=http://127.0.0.1:<port> in the tmux environment for the session. Each agent pane inherits this variable and can use it to communicate with the broker.
Supervisor Mode Layout
When --supervisor is active (or [supervisor] enabled = true), the tmux
session is laid out as a 50/50 top row plus a row-major agent grid below.
This is the canonical v0.5.0 supervisor-as-pane layout established by the
supervisor-as-pane archive.
┌──────────────────────────┬──────────────────────────┐
│ pane 0: supervisor │ pane 1: dashboard │
├──┬──┬──┬──┬──┬───────────┴──────────────────────────┤
│ 2│ 3│ 4│ 5│ 6│ agent grid (row 1) │
├──┴──┴──┴──┴──┤ │
│ 7│..│..│..│ N│ agent grid (row 2..M) │
└──┴──┴──┴──┴──┴──────────────────────────────────────┘
Pane 0 always hosts the supervisor CLI; pane 1 always hosts the dashboard. Pane indices 2 onwards host one CLI per agent. The supervisor reads agent state via the broker and the dashboard; the dashboard reads the same broker state for its status table.
Row-height proportions
The top row is fixed at 50% of the supervisor pane width and the agent rows share the remaining vertical space. Row-height proportions for the agent grid depend on how many bottom rows the layout produces:
| Agent rows | Bottom-row heights |
|---|---|
| 1 | 60% (top row 40%) |
| 2 | 40% / 30% / 30% (top + 2 bottom rows) |
| 3 | 28% / 24% / 24% / 24% |
| 4 | 28% / 18% / 18% / 18% / 18% |
| 5 | 28% / 14.4% / 14.4% / 14.4% / 14.4% / 14.4% |
The agent-grid columns within each row are split evenly via tmux’s tiled
layout. src/supervisor/layout.rs is the source of truth.
Non-Supervisor Layout
When supervisor mode is OFF and the broker is on, the dashboard occupies pane 0 and the agent CLIs occupy panes 1 onwards in a single row-major grid (no top row):
┌───────────────────────────────────────────────────────┐
│ pane 0: dashboard │
├──┬──┬──┬──┬──┬────────────────────────────────────────┤
│ 1│ 2│ 3│ 4│ 5│ agent grid (row 1) │
├──┴──┴──┴──┴──┤ │
│ 6│..│..│..│ N│ agent grid (row 2..M) │
└──┴──┴──┴──┴──┴───────────────────────────────────────┘
When the broker is disabled too, every pane (0..N) is an agent CLI and there is no dashboard pane.
Worktree Lifecycle
Git worktrees are the foundation of git-paw’s parallel workflow.
Creation
For a project named my-app and branch feature/auth-flow:
my-app/ ← main repo (current directory)
my-app-feature-auth-flow/ ← worktree (created by git-paw)
my-app-feat-api/ ← worktree (created by git-paw)
Worktrees are created as siblings of the main repo directory. The naming convention is <project>-<sanitized-branch> where slashes become hyphens.
Lifecycle states
create_worktree() stop start (recover)
│ │ │
▼ ▼ ▼
[exists on disk] → [still on disk] → [reused as-is]
│
purge │
▼
[removed from disk]
Key points:
- Stop preserves worktrees — uncommitted work survives
- Recover reuses existing worktrees — no data loss
- Purge removes worktrees —
git worktree removefollowed by prune
Session State
Session state is persisted as JSON under ~/.local/share/git-paw/sessions/:
{
"session_name": "paw-my-app",
"repo_path": "/Users/you/projects/my-app",
"project_name": "my-app",
"created_at": "2025-01-15T10:30:00Z",
"status": "active",
"broker_port": 9119,
"broker_enabled": true,
"worktrees": [
{
"branch": "feat/auth",
"worktree_path": "/Users/you/projects/my-app-feat-auth",
"cli": "claude"
},
{
"branch": "feat/api",
"worktree_path": "/Users/you/projects/my-app-feat-api",
"cli": "gemini"
}
]
}
The broker_port and broker_enabled fields are present when the broker is configured. They allow git paw status to display broker information and git paw purge to clean up broker.log.
Atomic writes
Session state is written atomically: write to a temporary file, then rename. This prevents corruption if the process is killed mid-write.
Effective status
The on-disk status may not reflect reality (e.g., tmux was killed externally). git-paw checks the actual tmux state:
| File status | tmux alive? | Effective status |
|---|---|---|
active | Yes | Active (reattach) |
active | No | Stopped (recover) |
stopped | N/A | Stopped (recover) |
| No file | N/A | No session |
Tmux Builder Pattern
The tmux module uses a builder pattern that accumulates operations as data structures rather than immediately executing shell commands. This enables:
- Testability — generate commands without executing them
- Dry run — print the plan without side effects
- Atomicity — validate the full plan before running anything
#![allow(unused)]
fn main() {
TmuxSessionBuilder::new()
.session_name("paw-my-app")
.pane(PaneSpec { branch, worktree_path, cli_command })
.pane(PaneSpec { ... })
.mouse(true)
.build()
// → TmuxSession { name, commands: Vec<TmuxCommand> }
}
The built TmuxSession can be inspected, printed (dry run), or executed.
Error Strategy
All errors flow through PawError (defined with thiserror). Each variant carries an actionable message telling the user what went wrong and how to fix it. No panics in non-test code — all Result propagation.
Exit codes:
- 0 — success
- 1 — operational error
- 2 — user cancelled
Specifications
git-paw uses OpenSpec for formal, testable specifications. Each capability has a dedicated spec file using RFC 2119 keywords (SHALL, MUST, SHOULD) and GIVEN/WHEN/THEN scenarios.
Specification Index
| Capability | Description |
|---|---|
| CLI Parsing | Command-line argument parsing and subcommands |
| CLI Detection | Auto-detect AI CLIs on PATH, load custom CLIs |
| Git Operations | Validate repos, list branches, manage worktrees |
| Tmux Orchestration | Create sessions, manage panes, apply layout |
| Session State | Persist and recover session state |
| Configuration | Parse and merge TOML config files |
| Interactive Selection | User prompts for mode, branch, and CLI selection |
| Error Handling | Unified error types with exit codes |
CLI Parsing
Purpose
Define the command-line interface for git-paw using clap v4. Declares all subcommands (start, stop, purge, status, list-clis, add-cli, remove-cli), their flags, and argument validation. When no subcommand is given, defaults to start.
Requirements
Requirement: Default to start when no subcommand is given
The system SHALL treat no arguments as equivalent to start with no flags.
The system SHALL also accept a hidden __dashboard subcommand that does not appear in --help output. This subcommand is used internally by pane 0 to run the broker and dashboard.
Scenario: No arguments yields None command
- GIVEN no arguments are passed
- WHEN the CLI is parsed
- THEN
commandSHALL beNone(handled asStartin main)
Scenario: __dashboard subcommand parses
- GIVEN
__dashboardis passed - WHEN the CLI is parsed
- THEN the command SHALL be
Command::Dashboard
Scenario: __dashboard does not appear in help
- GIVEN
--helpis passed - WHEN the help text is rendered
- THEN the output SHALL NOT contain
__dashboard
Requirement: Start subcommand with optional flags
The start subcommand SHALL be extended to accept a --supervisor flag (boolean, defaults to false). The flag MAY be combined with any other start flags.
When --supervisor is passed, the parsed StartArgs struct SHALL have supervisor: bool set to true.
The start subcommand SHALL also accept a --no-rebase flag (boolean, defaults to false). When --no-rebase is passed, the parsed StartArgs struct SHALL have no_rebase: bool set to true. The dispatch SHALL invoke create_worktree with rebase_onto_main = !args.no_rebase for every worktree creation in the launch. When --no-rebase is omitted (i.e. no_rebase == false), agent branches SHALL be rebased onto the repository’s default branch before their worktrees are opened. When --no-rebase is present, agent branches SHALL NOT be rebased, matching the post-worktree-resume-fix v0.5.0 behaviour.
The --no-rebase flag MAY be combined with any other start flags including --supervisor, --from-specs, --cli, and --branches.
Scenario: Start with –supervisor flag
- GIVEN
start --supervisor - WHEN the CLI is parsed
- THEN
supervisorSHALL betrue
Scenario: Start with –supervisor combined with other flags
- GIVEN
start --supervisor --cli claude --branches feat/a,feat/b - WHEN the CLI is parsed
- THEN
supervisorSHALL betrue - AND
cliSHALL beSome("claude") - AND
branchesSHALL be["feat/a", "feat/b"]
Scenario: Start without –supervisor defaults to false
- GIVEN
start --cli claude - WHEN the CLI is parsed
- THEN
supervisorSHALL befalse
Scenario: Start with –no-rebase flag
- GIVEN
start --no-rebase - WHEN the CLI is parsed
- THEN
no_rebaseSHALL betrue
Scenario: Start without –no-rebase defaults to false
- GIVEN
start --cli claude - WHEN the CLI is parsed
- THEN
no_rebaseSHALL befalse
Scenario: Start with –no-rebase combined with other flags
- GIVEN
start --no-rebase --supervisor --from-specs - WHEN the CLI is parsed
- THEN
no_rebaseSHALL betrue - AND
supervisorSHALL betrue - AND
from_specsSHALL betrue
Scenario: –no-rebase propagates to create_worktree as rebase_onto_main = false
- GIVEN
start --branches feat/a --no-rebaseis invoked - WHEN the dispatch reaches the worktree-creation loop
- THEN
create_worktree(repo_root, "feat/a", rebase_onto_main)SHALL be called withrebase_onto_main = false
Scenario: Default start propagates rebase_onto_main = true
- GIVEN
start --branches feat/ais invoked without--no-rebase - WHEN the dispatch reaches the worktree-creation loop
- THEN
create_worktree(repo_root, "feat/a", rebase_onto_main)SHALL be called withrebase_onto_main = true
Requirement: Stop subcommand
The stop subcommand SHALL accept an optional --force flag (boolean, defaults to false). When --force is omitted AND stdin is a TTY, cmd_stop SHALL render an interactive confirmation prompt describing the destructive nature of stop and pointing at git paw pause (soft alternative) and git paw purge (full reset). When --force is set OR stdin is not a TTY, the prompt SHALL be skipped and the stop SHALL proceed immediately.
The long_about help text for stop SHALL name all three teardown verbs (pause, stop, purge) with a one-line summary of each, so users can choose the right verb at --help time.
Scenario: Stop parses without flags
- GIVEN
stopis passed - WHEN the CLI is parsed
- THEN the command SHALL be
Command::Stop { force: false }
Scenario: Stop parses with –force
- GIVEN
stop --forceis passed - WHEN the CLI is parsed
- THEN the command SHALL be
Command::Stop { force: true }
Scenario: Stop help names all three teardown verbs
- WHEN
git paw stop --helpis run - THEN the output SHALL mention
pauseas the soft alternative - AND the output SHALL mention
purgeas the full reset - AND the output SHALL describe what
stopitself does (kills CLI processes, preserves worktrees)
Scenario: Stop with –force from a TTY skips the prompt
- GIVEN an active session and
--forceis passed - WHEN
git paw stop --forceis run with stdin attached to a TTY - THEN no interactive prompt SHALL be rendered
- AND the session SHALL be killed immediately
Requirement: Purge subcommand with optional –force flag
The purge subcommand SHALL accept an optional --force flag (defaults to false).
Scenario: Purge without –force
- GIVEN
purgeis passed without flags - WHEN the CLI is parsed
- THEN
forceSHALL befalse
Test: cli::tests::purge_without_force
Scenario: Purge with –force
- GIVEN
purge --forceis passed - WHEN the CLI is parsed
- THEN
forceSHALL betrue
Test: cli::tests::purge_with_force
Requirement: Status subcommand
The status subcommand SHALL parse with no additional arguments.
Scenario: Status parses
- GIVEN
statusis passed - WHEN the CLI is parsed
- THEN the command SHALL be
Command::Status
Test: cli::tests::status_parses
Requirement: List-CLIs subcommand
The list-clis subcommand SHALL parse with no additional arguments.
Scenario: List-CLIs parses
- GIVEN
list-clisis passed - WHEN the CLI is parsed
- THEN the command SHALL be
Command::ListClis
Test: cli::tests::list_clis_parses
Requirement: Add-CLI subcommand with required and optional arguments
The add-cli subcommand SHALL require name and command positional arguments and accept an optional --display-name flag.
Scenario: Add-CLI with required arguments only
- GIVEN
add-cli my-agent /usr/local/bin/my-agent - WHEN the CLI is parsed
- THEN
nameSHALL be"my-agent",commandSHALL be the path, anddisplay_nameSHALL beNone
Test: cli::tests::add_cli_with_required_args
Scenario: Add-CLI with –display-name
- GIVEN
add-cli my-agent my-agent --display-name "My Agent" - WHEN the CLI is parsed
- THEN
display_nameSHALL beSome("My Agent")
Test: cli::tests::add_cli_with_display_name
Scenario: Add-CLI missing required arguments is rejected
- GIVEN
add-cliwith no positional arguments - WHEN the CLI is parsed
- THEN parsing SHALL fail
Test: cli::tests::add_cli_missing_required_args_is_rejected
Requirement: Remove-CLI subcommand with required argument
The remove-cli subcommand SHALL require a name positional argument.
Scenario: Remove-CLI parses
- GIVEN
remove-cli my-agent - WHEN the CLI is parsed
- THEN
nameSHALL be"my-agent"
Test: cli::tests::remove_cli_parses
Requirement: Standard flags –version and –help
The CLI SHALL accept --version and --help flags.
Scenario: –version flag is accepted
- GIVEN
--versionis passed - WHEN the CLI is parsed
- THEN clap SHALL emit a
DisplayVersionresponse
Test: cli::tests::version_flag_is_accepted
Scenario: –help flag is accepted
- GIVEN
--helpis passed - WHEN the CLI is parsed
- THEN clap SHALL emit a
DisplayHelpresponse
Test: cli::tests::help_flag_is_accepted
Requirement: Unknown subcommands are rejected
The CLI SHALL reject unrecognized subcommands with a parse error.
Scenario: Unknown subcommand fails
- GIVEN an unrecognized subcommand is passed
- WHEN the CLI is parsed
- THEN parsing SHALL fail
Test: cli::tests::unknown_subcommand_is_rejected
Requirement: Help output contains all subcommands and quick start
The start --help output SHALL list the --supervisor flag with a description.
Scenario: Start help shows –supervisor flag
- GIVEN
start --helpis passed - WHEN the binary runs
- THEN stdout SHALL contain
--supervisor
Requirement: Version output includes binary name
The --version output SHALL include the binary name.
Scenario: Version output
- GIVEN
--versionis passed - WHEN the binary runs
- THEN stdout SHALL contain “git-paw”
Test: cli_tests::version_output
Requirement: No arguments behaves like start
When no subcommand is provided, the binary SHALL behave identically to start.
Scenario: No args produces same error as start
- GIVEN the binary is run with no arguments outside a git repo
- WHEN both
git-pawandgit-paw startare run - THEN they SHALL produce identical stderr output
Test: cli_tests::no_args_behaves_like_start
Requirement: Subcommands run without error when applicable
Subcommands that don’t require a session SHALL succeed in a valid git repo.
Scenario: Stop runs without error
- GIVEN the binary is run in a git repo
- WHEN
stopis passed - THEN it SHALL succeed
Test: cli_tests::stop_runs_without_error
Scenario: Status runs without error
- GIVEN the binary is run in a git repo
- WHEN
statusis passed - THEN it SHALL succeed
Test: cli_tests::status_runs_without_error
Scenario: List-CLIs runs without error
- GIVEN the binary is run in a git repo
- WHEN
list-clisis passed - THEN it SHALL succeed
Test: cli_tests::list_clis_runs_without_error
Requirement: Binary rejects missing required arguments
Subcommands with required arguments SHALL fail when they are missing.
Scenario: Add-CLI requires arguments
- GIVEN
add-cliis passed with no arguments - WHEN the binary runs
- THEN it SHALL fail with stderr mentioning “required”
Test: cli_tests::add_cli_requires_arguments
Scenario: Remove-CLI requires argument
- GIVEN
remove-cliis passed with no arguments - WHEN the binary runs
- THEN it SHALL fail with stderr mentioning “required”
Test: cli_tests::remove_cli_requires_argument
Requirement: Not-a-repo error from binary
Commands requiring a git repo SHALL fail with an actionable error when run outside one.
Scenario: Start from non-git directory
- GIVEN the binary is run outside a git repository
- WHEN
startis passed - THEN it SHALL fail with stderr containing “Not a git repository”
Test: cli_tests::start_from_non_git_dir
Scenario: Unknown subcommand from binary
- GIVEN the binary is passed an unrecognized subcommand
- WHEN it runs
- THEN it SHALL fail with stderr containing “error”
Test: cli_tests::unknown_subcommand_fails
Requirement: Replay subcommand
The replay subcommand SHALL accept an optional <branch> positional argument, a --list flag, a --color flag, and an optional --session flag.
Scenario: Replay with branch
- WHEN
replay feat/add-authis passed - THEN
branchSHALL beSome("feat/add-auth"),listSHALL befalse,colorSHALL befalse
Scenario: Replay with –list
- WHEN
replay --listis passed - THEN
listSHALL betrueandbranchSHALL beNone
Scenario: Replay with –color
- WHEN
replay feat/add-auth --coloris passed - THEN
colorSHALL betrue
Scenario: Replay with –session
- WHEN
replay feat/add-auth --session paw-myprojectis passed - THEN
sessionSHALL beSome("paw-myproject")
Scenario: Replay with no arguments and no –list
- WHEN
replayis passed with no arguments and no--list - THEN parsing SHALL fail with an error indicating either a branch or
--listis required
Scenario: Replay help text
- WHEN
replay --helpis passed - THEN stdout SHALL contain descriptions of
--list,--color, and--sessionflags with examples
Requirement: Init subcommand
The init subcommand SHALL parse with no required arguments.
Scenario: Init parses
- WHEN
initis passed - THEN the command SHALL be
Command::Init
Scenario: Init help text
- WHEN
init --helpis passed - THEN stdout SHALL contain a description of project initialization and examples
Requirement: Spec mode + supervisor mode dispatch
The start subcommand dispatch SHALL evaluate the supervisor-mode resolution chain (per supervisor-cli) BEFORE branching on --from-specs. Specifically:
- Resolve supervisor-mode-enabled state from the
--supervisorflag,--no-supervisorflag,[supervisor]config, and the prompt fallback. - If supervisor mode is enabled, route to
cmd_supervisor. When--from-specsis also set, passbranches_flag = Nonesocmd_supervisor’s existingscan_specs(...)fallback runs to determine branches from configured specs. - Otherwise, if
--from-specsis set, route tocmd_start_from_specs. - Otherwise, route to bare
cmd_start.
This ordering ensures --from-specs --supervisor (or --from-specs with [supervisor] enabled = true in config) actually engages supervisor mode end-to-end, rather than silently degrading to spec-mode-without-supervisor.
--from-specs combined with --branches continues to follow v0.4’s existing behaviour (the spec-mode flow ignores explicit branches when from-specs is set); this change does not introduce a new mutual-exclusion error for that combination.
Scenario: –from-specs –supervisor engages supervisor mode
- GIVEN
git paw start --from-specs --supervisoris invoked - WHEN the dispatch resolves
- THEN the supervisor-mode resolution chain SHALL evaluate
supervisor = true - AND the dispatch SHALL route to
cmd_supervisor - AND
cmd_supervisorSHALL receivebranches_flag = None, triggering itsscan_specs(...)fallback
Scenario: –from-specs without supervisor uses spec mode
- GIVEN
git paw start --from-specsis invoked, no--supervisorflag, and[supervisor]config indicates supervisor mode is not enabled (either explicitly false or absent + non-interactive) - WHEN the dispatch resolves
- THEN the dispatch SHALL route to
cmd_start_from_specs
Scenario: –from-specs with [supervisor] enabled = true config engages supervisor mode
- GIVEN
git paw start --from-specsis invoked with no--supervisorflag - AND
.git-paw/config.tomlcontains[supervisor] enabled = true - WHEN the dispatch resolves
- THEN supervisor mode SHALL be active per the resolution chain
- AND the dispatch SHALL route to
cmd_supervisor(notcmd_start_from_specs)
Scenario: –no-supervisor –from-specs uses spec mode
- GIVEN
git paw start --from-specs --no-supervisoris invoked - AND
[supervisor] enabled = trueis set in config - WHEN the dispatch resolves
- THEN supervisor mode SHALL be disabled per the resolution chain
- AND the dispatch SHALL route to
cmd_start_from_specs
Scenario: Bare start (no –from-specs, no supervisor) uses cmd_start
- GIVEN
git paw startis invoked with no--from-specs, no--supervisor, and supervisor mode is not enabled in config - WHEN the dispatch resolves
- THEN the dispatch SHALL route to
cmd_start
Requirement: Non-TTY launch handling
When a git paw start invocation reaches its session-launch step (after worktrees are created, panes added, and tmux_session.execute() succeeds), the system SHALL detect whether stdin is connected to a terminal via std::io::IsTerminal::is_terminal(&std::io::stdin()).
When stdin is not a terminal:
- The system SHALL skip the
tmux::attach(...)call. - The system SHALL print an informational message to stdout naming the launched session and the manual-attach command (
tmux attach -t <session>). - The system SHALL exit with status
0. - For supervisor mode specifically, the system SHALL also skip the foreground supervisor-CLI launch (
Command::new(supervisor_cli).status()) with an additional hint that supervisor mode requires an interactive terminal.
When stdin is a terminal, the launch flow proceeds as before (call tmux::attach, run the supervisor CLI in foreground for supervisor mode).
This SHALL apply to all three start paths: cmd_start, cmd_start_from_specs, and cmd_supervisor.
Scenario: Non-TTY bare start exits cleanly with attach hint
- GIVEN
git paw start --branches feat/x,feat/yis invoked with stdin redirected from/dev/null(or otherwise non-TTY) - WHEN the launch flow completes its session-build steps
- THEN the command SHALL exit with status
0 - AND stdout SHALL contain “Session ‘
’ started in detached mode.” - AND stdout SHALL contain “Attach with: tmux attach -t
” - AND the tmux session SHALL exist and be alive after exit
Scenario: Non-TTY –from-specs exits cleanly
- GIVEN
git paw start --from-specsis invoked from a non-TTY context - WHEN the launch flow completes
- THEN the command SHALL exit with status
0 - AND the attach-hint message SHALL be printed
- AND the tmux session SHALL exist and be alive
Scenario: Non-TTY –supervisor skips supervisor CLI launch
- GIVEN
git paw start --supervisor --from-specsis invoked from a non-TTY context - WHEN the launch flow completes
- THEN the command SHALL exit with status
0 - AND the foreground supervisor-CLI launch SHALL be skipped
- AND stdout SHALL contain a hint indicating supervisor mode requires an interactive terminal
- AND stdout SHALL contain the manual-attach command for the launched session
Scenario: TTY launch attaches as before
- GIVEN
git paw start --branches feat/x,feat/yis invoked from a real TTY - WHEN the launch flow completes its session-build steps
- THEN the system SHALL call
tmux::attach(...)for the launched session - AND SHALL NOT print the “started in detached mode” hint
Requirement: –from-all-specs flag
The start subcommand SHALL accept a --from-all-specs flag (boolean, default false). When passed, the resulting StartArgs SHALL indicate the “launch every discovered spec” mode — the v0.4 behaviour previously gated by --from-specs.
The flag SHALL appear in git paw start --help output with a description naming it as the canonical name for this behaviour.
Scenario: –from-all-specs sets the launch-all mode
- GIVEN the user invokes
git paw start --from-all-specs - WHEN the CLI is parsed
- THEN the parsed
StartArgsSHALL indicate the launch-all-discovered-specs mode
Scenario: –from-all-specs combined with –supervisor
- GIVEN
start --from-all-specs --supervisor - WHEN the CLI is parsed
- THEN both
from_all_specsandsupervisorSHALL betrue
Scenario: –from-all-specs appears in help output
- WHEN
git paw start --helpis run - THEN the output contains
--from-all-specs - AND the output describes the flag as launching every discovered spec
Requirement: –from-specs is a hidden alias of –from-all-specs
The start subcommand SHALL accept --from-specs as a hidden alias of --from-all-specs. When the user passes --from-specs, the parsed StartArgs SHALL be byte-for-byte identical to the parse result for --from-all-specs. No stderr warning SHALL be emitted at runtime; the alias is silent.
The alias SHALL NOT appear in git paw start --help output. The alias SHALL be removed in v1.0.0; v0.5.0 keeps it for backward compatibility with v0.4 scripts.
Scenario: –from-specs parses identically to –from-all-specs
- GIVEN two CLI invocations:
start --from-specsandstart --from-all-specs - WHEN both are parsed
- THEN the resulting
StartArgsvalues SHALL be equal
Scenario: –from-specs does not appear in help
- WHEN
git paw start --helpis run - THEN the output SHALL NOT contain the substring
--from-specs
Scenario: –from-specs emits no stderr warning
- GIVEN the user runs a command containing
--from-specs - WHEN the CLI parses
- THEN no stderr warning SHALL be emitted regarding the flag’s deprecation
- AND the command proceeds exactly as if
--from-all-specshad been passed
Requirement: –specs flag with comma-separated values
The start subcommand SHALL accept a --specs flag whose value is a comma-separated list of spec names (mirroring the existing --branches feat/a,feat/b syntax). The flag SHALL accept zero or more values:
--specs(no values) — indicates the picker mode.--specs NAME— narrows to a single named spec.--specs NAME1,NAME2,NAME3— narrows to the listed specs.--specs NAME1,NAME2 --specs NAME3— equivalent to--specs NAME1,NAME2,NAME3if clap’s value-accumulation across repetitions is enabled (implementation choice; tests assert behaviour for the comma-separated form).
The parsed value distinguishes three states:
- Flag absent → no spec mode requested.
- Flag present with zero values → picker mode.
- Flag present with one or more values → narrow mode with the listed names.
The flag SHALL appear in git paw start --help output.
Scenario: –specs with single value parses as narrow
- GIVEN
start --specs add-auth - WHEN the CLI is parsed
- THEN
StartArgsSHALL indicate narrow mode with["add-auth"]
Scenario: –specs with comma-separated values parses as narrow with multiple names
- GIVEN
start --specs add-auth,fix-session,add-logging - WHEN the CLI is parsed
- THEN
StartArgsSHALL indicate narrow mode with["add-auth", "fix-session", "add-logging"]
Scenario: –specs with no values parses as picker
- GIVEN
start --specs - WHEN the CLI is parsed
- THEN
StartArgsSHALL indicate picker mode
Scenario: –specs absent leaves spec mode unset
- GIVEN
start --supervisor(no--specs, no--from-all-specs) - WHEN the CLI is parsed
- THEN
StartArgsSHALL indicate no spec mode (falls through to standard branch selection)
Requirement: –from-all-specs and –specs are mutually exclusive
The system SHALL reject any invocation that combines --from-all-specs (or its alias --from-specs) with --specs. clap’s parse step SHALL produce an error before the command runs. The error message SHALL clearly state that the two flags express opposing intents and SHALL list both flags.
Scenario: –from-all-specs and –specs together are rejected
- GIVEN
start --from-all-specs --specs add-auth - WHEN the CLI is parsed
- THEN parsing SHALL fail with an error mentioning both
--from-all-specsand--specs
Scenario: –from-specs alias and –specs together are also rejected
- GIVEN
start --from-specs --specs add-auth - WHEN the CLI is parsed
- THEN parsing SHALL fail with an error mentioning both flags
- AND the alias SHALL enforce the same mutual-exclusion rule as the canonical name
Requirement: –no-supervisor flag
The start subcommand SHALL accept a --no-supervisor flag (boolean, default false). When passed, the parsed StartArgs SHALL have no_supervisor: bool set to true. The flag SHALL appear in git paw start --help output with a description that names the use case (overriding [supervisor] enabled = true for a single session).
Scenario: –no-supervisor sets the flag
- GIVEN the user invokes
git paw start --no-supervisor - WHEN the CLI is parsed
- THEN the parsed
StartArgs.no_supervisorSHALL betrue - AND
StartArgs.supervisorSHALL befalse
Scenario: –no-supervisor absent leaves flag false
- GIVEN the user invokes
git paw startwith neither--supervisornor--no-supervisor - WHEN the CLI is parsed
- THEN
StartArgs.no_supervisorSHALL befalse - AND
StartArgs.supervisorSHALL befalse
Scenario: –no-supervisor appears in help output
- WHEN
git paw start --helpis run - THEN the output contains
--no-supervisor - AND the output describes the flag as disabling supervisor for the session and overriding any
[supervisor] enabled = trueconfig setting
Requirement: –supervisor and –no-supervisor are mutually exclusive
The system SHALL reject any invocation that combines --supervisor and --no-supervisor on the same start command. clap’s parse step SHALL produce an error before the command runs. The error message SHALL clearly state that the two flags express opposing intents and SHALL list both.
Scenario: Both flags together are rejected
- GIVEN
start --supervisor --no-supervisor - WHEN the CLI is parsed
- THEN parsing SHALL fail with an error mentioning both
--supervisorand--no-supervisor
Scenario: –no-supervisor combines with other flags
- GIVEN
start --no-supervisor --cli claude --branches feat/a,feat/b - WHEN the CLI is parsed
- THEN
no_supervisorSHALL betrue - AND
cliSHALL beSome("claude") - AND
branchesSHALL containfeat/aandfeat/b - AND parsing SHALL succeed
Requirement: Pause subcommand
The pause subcommand SHALL parse with no additional arguments and SHALL be visible in git paw --help output. The subcommand SHALL include an about string (“Pause the session (detaches client, stops broker, leaves CLIs running)”) and a long_about string that names the RAM trade-off and points the reader at stop and (forthcoming v1.0.0) hibernate for the destructive and RAM-free alternatives respectively.
The pause subcommand SHALL appear in the root after_help quick-start guide alongside start, stop, and purge.
Scenario: Pause parses
- GIVEN
pauseis passed - WHEN the CLI is parsed
- THEN the command SHALL be
Command::Pause
Scenario: Pause accepts no flags
- GIVEN
pause --anythingis passed (any flag) - WHEN the CLI is parsed
- THEN parsing SHALL fail with an unknown-argument error
Scenario: Pause appears in help
- WHEN
git paw --helpis run - THEN the output SHALL list a
pausesubcommand - AND the output SHALL include the
pauseline in the quick-startafter_helpblock
Scenario: Pause help text names the RAM trade-off
- WHEN
git paw pause --helpis run - THEN the output SHALL mention that CLI processes remain running
- AND the output SHALL mention the RAM-allocation trade-off (or words conveying “RAM stays held”)
- AND the output SHALL suggest
git paw stopfor the RAM-releasing alternative
Requirement: git paw purge interactive confirmation SHALL honour y+Enter under all conditions
The cmd_purge interactive confirmation prompt SHALL be reliably readable by the dialoguer Confirm widget regardless of preceding stderr output. When the unmerged-commits warning has been written to stderr immediately before the prompt, the warning writer SHALL flush stderr before the prompt’s interact() call begins, so the user’s y+Enter input is not racing the warning’s buffered bytes.
Scenario: Purge with unmerged commits and y+Enter proceeds
- GIVEN a session with at least one branch carrying commits not in
main - AND
git paw purgeis invoked from a TTY - WHEN the prompt “Purge is irreversible. Continue?” appears and the user types
yfollowed by Enter - THEN the purge SHALL proceed (kill tmux session + remove worktrees + delete session JSON)
- AND the exit code SHALL be 0
- AND stdout SHALL contain
Purged session 'paw-...'
Scenario: Purge with unmerged commits and n+Enter cancels
- GIVEN same setup as above
- WHEN the user types
nfollowed by Enter - THEN the purge SHALL NOT proceed
- AND the exit code SHALL be 0
- AND stdout SHALL contain
Purge cancelled. - AND the session worktrees SHALL still be on disk
Scenario: Purge with bare Enter (no y/n) defaults to no
- GIVEN same setup
- WHEN the user types Enter without first typing
yorn - THEN the prompt SHALL default to false (No)
- AND the purge SHALL NOT proceed
- AND stdout SHALL contain
Purge cancelled.
Requirement: git paw purge --force SHALL propagate --force to git worktree remove and emit per-worktree progress
When git paw purge is invoked with --force, the underlying git worktree remove invocations SHALL pass --force so the removal succeeds on worktrees with uncommitted changes. The command SHALL also emit per-worktree progress messages to stderr (e.g. Removing worktree <path>... before each removal and done (<elapsed>s) after) so the user can distinguish a slow-but-progressing removal from an actual hang.
Scenario: purge --force removes dirty worktrees
- GIVEN a session with one worktree containing uncommitted edits
- WHEN
git paw purge --forceis invoked - THEN the dirty worktree SHALL be removed successfully
- AND the exit code SHALL be 0
- AND the underlying
git worktree removeinvocation SHALL include the--forceflag
Scenario: purge --force emits per-worktree progress to stderr
- GIVEN a session with two or more worktrees
- WHEN
git paw purge --forceis invoked - THEN stderr SHALL contain a
Removing worktree <path>...line for each worktree being removed - AND stderr SHALL contain a
doneor completion marker after each removal - AND the order SHALL match the worktree iteration order
Scenario: purge without --force does NOT pass --force to git worktree remove
- GIVEN a session with one worktree containing uncommitted edits
- WHEN
git paw purge(no--force) is invoked and the user confirms withy - THEN the underlying
git worktree removeSHALL NOT include the--forceflag - AND if
git worktree removefails because of the dirty state, the failure SHALL be reported to stderr aswarning: failed to remove worktree '<path>': <git error>per the existing error-handling path - AND purge SHALL continue with the remaining worktrees
Requirement: git paw stop and git paw purge SHALL strip the supervisor boot-block injection from AGENTS.md
cmd_stop and cmd_purge (src/main.rs) SHALL invoke a helper that removes the supervisor-pane boot-block injection block from <repo>/AGENTS.md. The block is bounded by HTML comment markers <!-- git-paw:start --> … <!-- git-paw:end --> (or similar — the actual marker strings are owned by the injection code path and SHALL match exactly). The helper SHALL be idempotent and SHALL preserve all surrounding content byte-for-byte.
Scenario: Stop strips the boot-block injection
- GIVEN a session in which
cmd_supervisororcmd_startinjected a<!-- git-paw:start -->…<!-- git-paw:end -->block intoAGENTS.md - WHEN
git paw stop(with or without--force) is invoked - AND the teardown completes successfully
- THEN the resulting
AGENTS.mdSHALL contain no<!-- git-paw:start -->marker - AND no
<!-- git-paw:end -->marker
Scenario: Purge strips the boot-block injection
- GIVEN the same setup
- WHEN
git paw purge(with or without--force) is invoked - THEN
AGENTS.mdSHALL contain neither marker after the purge completes
Scenario: Stop/purge on AGENTS.md without markers is a no-op
- GIVEN an
AGENTS.mdwith no<!-- git-paw:start -->marker - WHEN
git paw stoporgit paw purgeruns the cleanup helper - THEN
AGENTS.mdSHALL be byte-identical to its pre-cleanup state - AND the helper SHALL return success
Requirement: git paw init SHALL be idempotent and additive on existing config files
src/init.rs::run_init SHALL parse the existing .git-paw/config.toml (if any) and compare its top-level keys/tables against the bundled-default schema. The init flow SHALL append commented stanzas ONLY for keys/tables missing from the user’s config. It SHALL NEVER:
- Modify the value of an existing key.
- Add a second occurrence of any top-level table (e.g. a second
[supervisor]) when the user already has that section commented OR uncommented. - Re-order or reformat existing keys/sections.
- Strip existing user comments or blank lines.
When every bundled-default key is already present in the user’s config, init SHALL print config.toml already has all default keys; no changes and return Ok without writing.
Init invocations SHALL be idempotent: running git paw init a second time on a config that the first run produced SHALL leave the file byte-identical.
Scenario: First init writes a complete commented default config
- GIVEN a fresh repo with no
.git-paw/config.toml - WHEN
git paw initis invoked - THEN the file SHALL be created
- AND SHALL parse as valid TOML
- AND SHALL contain commented stanzas for every bundled-default top-level key/section
Scenario: Second init on the just-written file is a no-op
- GIVEN the same repo after the first init
- WHEN
git paw initis invoked again - THEN the file SHALL be byte-identical to the first-run output
- AND the exit SHALL be 0
Scenario: Init preserves a user-authored [supervisor] block
- GIVEN a
.git-paw/config.tomlcontaining only:[supervisor] enabled = true cli = "claude-oss" - WHEN
git paw initis invoked - THEN the resulting file SHALL contain
enabled = trueandcli = "claude-oss"byte-identical to the input - AND SHALL NOT contain a second
[supervisor]section header (commented or uncommented) - AND SHALL parse as valid TOML (no
duplicate keyerrors)
Scenario: Init appends missing top-level sections
- GIVEN a
.git-paw/config.tomlcontaining onlybranch_prefix = "feat/" - WHEN
git paw initis invoked - THEN the resulting file SHALL preserve
branch_prefix = "feat/"byte-identical - AND SHALL gain commented stanzas for every bundled-default section the user is missing (
[broker],[dashboard],[supervisor], etc.) - AND SHALL parse as valid TOML
Scenario: Init never modifies existing user values
- GIVEN a
.git-paw/config.tomlwith[broker] port = 9200(non-default port) - WHEN
git paw initis invoked - THEN the resulting file SHALL still have
port = 9200 - AND SHALL NOT introduce a second
portkey or a commented# port = 9119stanza inside[broker]
CLI Detection
Purpose
Detect available AI coding CLI binaries by scanning PATH for known names and merging with user-defined custom CLIs from configuration. Provides a unified, deduplicated, sorted list for interactive selection or direct use.
Requirements
Requirement: Auto-detect known AI CLIs on PATH
The system SHALL scan PATH for the known CLI binaries: claude, codex, gemini, aider, vibe, qwen, and amp.
Scenario: All known CLIs are present on PATH
- GIVEN all 8 known CLI binaries exist on PATH
- WHEN
detect_known_clis()is called - THEN it SHALL return a
CliInfofor each binary withsource = Detected, a non-emptydisplay_name, and a validpath
Test: detect::tests::all_known_clis_detected_when_present
Scenario: No known CLIs are present on PATH
- GIVEN PATH contains no known CLI binaries
- WHEN
detect_known_clis()is called - THEN it SHALL return an empty list
Test: detect::tests::returns_empty_when_no_known_clis_on_path
Scenario: Partial set of CLIs on PATH
- GIVEN only a subset of known CLIs exist on PATH
- WHEN
detect_known_clis()is called - THEN it SHALL return only the CLIs that are found
Test: detect::tests::detects_subset_of_known_clis
Requirement: Resolve and merge custom CLIs from configuration
The system SHALL resolve custom CLI definitions by looking up commands as absolute paths or via PATH, and merge them with auto-detected CLIs.
Scenario: Custom CLIs merged with detected CLIs
- GIVEN auto-detected CLIs exist and custom CLI definitions are provided
- WHEN
detect_clis()is called - THEN the result SHALL contain both detected and custom CLIs
Test: detect::tests::custom_clis_merged_with_detected
Scenario: Custom CLI binary not found
- GIVEN a custom CLI definition references a non-existent binary
- WHEN
detect_clis()is called - THEN the missing CLI SHALL be excluded and a warning printed to stderr
Test: detect::tests::custom_cli_excluded_when_binary_missing
Scenario: Custom CLI resolved by absolute path
- GIVEN a custom CLI definition uses an absolute path to an existing binary
- WHEN
resolve_custom_clis()is called - THEN the resolved path SHALL match the absolute path provided
Test: detect::tests::custom_cli_resolved_by_absolute_path
Requirement: Custom CLIs override detected CLIs with the same name
When a custom CLI has the same binary_name as a detected CLI, the custom definition SHALL take precedence.
Scenario: Custom CLI overrides auto-detected CLI
- GIVEN a custom CLI shares a
binary_namewith an auto-detected CLI - WHEN
detect_clis()is called - THEN the result SHALL contain only the custom version with
source = Custom
Test: detect::tests::custom_cli_overrides_detected_with_same_binary_name
Requirement: Each CLI result includes all required fields
Every CliInfo SHALL have a non-empty display_name, binary_name, a valid path, and a source indicator.
Scenario: Detected CLI has all fields populated
- GIVEN a known CLI binary exists on PATH
- WHEN it is detected
- THEN all fields (
display_name,binary_name,path,source) SHALL be populated
Test: detect::tests::detected_cli_has_all_fields
Scenario: Custom CLI has all fields populated
- GIVEN a custom CLI definition is resolved
- WHEN it is included in results
- THEN all fields SHALL be populated
Test: detect::tests::custom_cli_has_all_fields
Requirement: Display name derivation
When no explicit display name is provided, the system SHALL derive one by capitalizing the first letter of the binary name.
Scenario: Custom CLI defaults to capitalized name
- GIVEN a custom CLI definition has no
display_name - WHEN it is resolved
- THEN the
display_nameSHALL be the binary name with the first letter capitalized
Test: detect::tests::custom_cli_display_name_defaults_to_capitalised_name
Requirement: Results sorted by display name
The combined CLI list SHALL be sorted alphabetically by display_name (case-insensitive).
Scenario: Results are sorted
- GIVEN multiple CLIs are detected and/or custom
- WHEN
detect_clis()is called - THEN the results SHALL be sorted by display name
Test: detect::tests::results_sorted_by_display_name
Requirement: CliSource display format
The CliSource enum SHALL display as "detected" or "custom".
Scenario: CliSource display strings
- GIVEN
CliSource::DetectedandCliSource::Custom - WHEN formatted with
Display - THEN they SHALL render as
"detected"and"custom"respectively
Test: detect::tests::cli_source_display_format
Git Operations
Purpose
Validate git repositories, list branches, create and remove worktrees, and derive worktree directory names. Provides the git plumbing that underpins parallel branch sessions.
Requirements
Requirement: Validate that a path is inside a git repository
The system SHALL confirm a path is inside a git repository and return the repository root.
Scenario: Path is inside a git repository
- GIVEN a path inside an initialized git repository
- WHEN
validate_repo()is called - THEN it SHALL return
Okwith the absolute path to the repository root
Test: git::tests::validate_repo_returns_root_inside_repo
Scenario: Path is not inside a git repository
- GIVEN a path that is not inside any git repository
- WHEN
validate_repo()is called - THEN it SHALL return
Err(PawError::NotAGitRepo)
Test: git::tests::validate_repo_returns_not_a_git_repo_outside
Requirement: List branches sorted and deduplicated
The system SHALL list all local and remote branches, deduplicated, sorted, with remote prefixes stripped and HEAD pointers excluded.
Scenario: Branches are returned sorted
- GIVEN a repository with multiple branches
- WHEN
list_branches()is called - THEN it SHALL return branches sorted alphabetically
Test: git::tests::list_branches_returns_sorted_branches
Scenario: Local and remote branches are deduplicated with prefix stripping
- GIVEN a repository cloned from a remote, with branches existing both locally and as remote-tracking refs
- WHEN
list_branches()is called - THEN each branch SHALL appear exactly once, with
origin/prefixes stripped
Test: git_integration::list_branches_strips_remote_prefix_and_deduplicates
Requirement: Derive project name from repository path
The system SHALL extract the project name from the final component of the repository root path, falling back to "project" for root paths.
Scenario: Normal repository path
- GIVEN a repository at
/Users/jie/code/git-paw - WHEN
project_name()is called - THEN it SHALL return
"git-paw"
Test: git::tests::project_name_from_path
Scenario: Root path fallback
- GIVEN a repository at
/ - WHEN
project_name()is called - THEN it SHALL return
"project"
Test: git::tests::project_name_fallback_for_root
Requirement: Build worktree directory names
The system SHALL generate worktree directory names as <project>-<sanitized-branch>, replacing / with - and stripping unsafe characters.
Scenario: Branch with single slash
- GIVEN project
"git-paw"and branch"feature/auth-flow" - WHEN
worktree_dir_name()is called - THEN it SHALL return
"git-paw-feature-auth-flow"
Test: git::tests::worktree_dir_name_replaces_slash_with_dash
Scenario: Branch with multiple slashes
- GIVEN project
"git-paw"and branch"feat/auth/v2" - WHEN
worktree_dir_name()is called - THEN it SHALL return
"git-paw-feat-auth-v2"
Test: git::tests::worktree_dir_name_handles_multiple_slashes
Scenario: Branch with special characters
- GIVEN project
"my-proj"and branch"fix/issue#42" - WHEN
worktree_dir_name()is called - THEN unsafe characters SHALL be stripped, returning
"my-proj-fix-issue42"
Test: git::tests::worktree_dir_name_strips_special_chars
Scenario: Simple branch name
- GIVEN project
"git-paw"and branch"main" - WHEN
worktree_dir_name()is called - THEN it SHALL return
"git-paw-main"
Test: git::tests::worktree_dir_name_simple_branch
Requirement: Create worktrees as siblings of the repository
The system SHALL create git worktrees in the parent directory of the repository root using the derived directory name convention.
The create_worktree function SHALL accept a rebase_onto_main: bool parameter. When rebase_onto_main is true AND the target branch already exists in the local repository, the function SHALL rebase the target branch onto the repository’s default branch (as returned by default_branch()) BEFORE performing the existence check for the worktree directory. The rebase SHALL be performed by invoking git rebase <default-branch> from the repository root. When the branch is already at or ahead of the default branch, git rebase exits zero with no rewrite; the function SHALL treat that as success.
If git rebase exits non-zero (rebase conflict or any other failure), the function SHALL invoke git rebase --abort in the repository root and return Err(PawError::WorktreeError("rebase onto main failed: <stderr>")). The branch SHALL be left at its pre-rebase HEAD after the abort; the function SHALL NOT proceed to the existence check or git worktree add when the rebase failed.
If rebase_onto_main is false, the function SHALL skip the rebase block entirely and behave identically to the post-worktree-resume-fix v0.5.0 contract (idempotent existence check followed by git worktree add).
If the target branch does NOT exist in the local repository at the time create_worktree is invoked, the function SHALL skip the rebase block regardless of the rebase_onto_main value and proceed to the existing git worktree add -b <branch> fallback, which creates the branch from current HEAD (already at the default branch tip by construction).
The system SHALL be idempotent in the resume case: when create_worktree() is invoked for a branch whose worktree already exists at the expected path AND is registered with git for that branch, the function SHALL return Ok(WorktreeCreation { path, branch_created: false }) without re-running git worktree add. Idempotency is verified by parsing git worktree list --porcelain output and matching both the worktree path and the refs/heads/<branch> line. When rebase_onto_main is true, the rebase block runs BEFORE this idempotency check, so a surviving worktree’s branch ref SHALL be updated to the rebased SHA before the function returns.
If the expected path exists on disk but is NOT a git worktree registered for the specified branch (e.g. an unrelated directory, or a worktree for a different branch), the function SHALL fall through to the existing git worktree add call so the user sees the actionable fatal: '<path>' already exists error from git directly.
Scenario: Worktree created at correct path
- GIVEN a repository with a branch
feature/test - WHEN
create_worktree()is called withrebase_onto_main = false - THEN a worktree SHALL be created at
../<project>-feature-testcontaining the repository files
Scenario: Creating worktree for currently checked-out branch fails
- GIVEN the current branch is checked out in the main repo
- WHEN
create_worktree()is called for that branch - THEN it SHALL return
Err(PawError::WorktreeError)
Scenario: Resume of an existing worktree returns success without re-running git worktree add
- GIVEN a worktree already exists at
../<project>-feature-testfor branchfeature/testfrom a prior session - AND
rebase_onto_main = falseis passed - WHEN
create_worktree()is called forfeature/test - THEN the function SHALL return
Ok(WorktreeCreation { path: <expected>, branch_created: false }) - AND the existing worktree SHALL remain unchanged (HEAD SHA, working tree files, and uncommitted changes preserved)
- AND no second
git worktree addSHALL be executed
Scenario: Path exists but is not a git worktree
- GIVEN the expected worktree path
../<project>-feature-testexists as a regular directory (not registered with git) - WHEN
create_worktree()is called for branchfeature/test - THEN the function SHALL return
Err(PawError::WorktreeError)whose message contains the substringalready exists
Scenario: Path exists as a worktree but for a different branch
- GIVEN a worktree already exists at
../<project>-feature-testbut registered for branchfeature/other - WHEN
create_worktree()is called for branchfeature/test - THEN the function SHALL fall through to
git worktree addand returnErr(PawError::WorktreeError)(preserving the v0.4 contract for unrelated path collisions)
Scenario: Rebase-on-resume happy path advances branch onto current main
- GIVEN the default branch
mainhas advanced by N commits since branchfeat/examplewas created - AND
feat/exampleexists locally and is behindmainby exactly N commits with no diverging commits of its own - WHEN
create_worktree()is called forfeat/examplewithrebase_onto_main = true - THEN the function SHALL invoke
git rebase <main>againstfeat/examplein the repository root - AND the rebase SHALL succeed
- AND
feat/example’s HEAD SHA after the call SHALL be reachable frommain(i.e. include the N new commits) - AND the function SHALL return
Ok(WorktreeCreation { path: <expected>, branch_created: false })
Scenario: Rebase skipped when branch is already up-to-date
- GIVEN branch
feat/exampleexists locally and is at the same SHA asmain(no divergence) - WHEN
create_worktree()is called forfeat/examplewithrebase_onto_main = true - THEN
git rebase <main>SHALL be invoked and SHALL exit zero with no rewrite - AND
feat/example’s HEAD SHA SHALL be unchanged - AND the function SHALL return
Ok(WorktreeCreation { path: <expected>, branch_created: false }) - AND no error SHALL be returned
Scenario: Rebase conflict aborts cleanly and surfaces error
- GIVEN branch
feat/exampleandmainboth modify the same line of the same file with different content - WHEN
create_worktree()is called forfeat/examplewithrebase_onto_main = true - THEN
git rebase <main>SHALL be invoked and SHALL exit non-zero with conflict markers - AND the function SHALL invoke
git rebase --abort - AND
feat/example’s HEAD SHA after the call SHALL equal its pre-call HEAD SHA - AND no
.git/rebase-mergeor.git/rebase-applydirectory SHALL remain in the repository - AND the function SHALL return
Err(PawError::WorktreeError(msg))wheremsgcontains the substringrebase onto main failed - AND the worktree directory at
../<project>-feat-exampleSHALL NOT have been created (or, if it existed from a prior session, SHALL be unchanged)
Scenario: rebase_onto_main = false preserves v0.5 no-rebase behaviour
- GIVEN branch
feat/exampleexists locally and is behindmainby 3 commits - WHEN
create_worktree()is called forfeat/examplewithrebase_onto_main = false - THEN no
git rebaseinvocation SHALL occur - AND
feat/example’s HEAD SHA after the call SHALL equal its pre-call HEAD SHA - AND the function SHALL proceed to the existence check and (if applicable)
git worktree add, matching the post-worktree-resume-fixv0.5.0 contract exactly
Scenario: New branch creation skips rebase regardless of flag
- GIVEN branch
feat/newdoes NOT exist in the local repository - AND
rebase_onto_main = trueis passed - WHEN
create_worktree()is called forfeat/new - THEN no
git rebaseinvocation SHALL occur (there is nothing to rebase) - AND the function SHALL invoke
git worktree add -b feat/new <path>to create the branch from current HEAD - AND the function SHALL return
Ok(WorktreeCreation { path, branch_created: true })
Requirement: Remove worktrees and prune stale entries
The system SHALL force-remove a worktree and prune stale git worktree metadata. remove_worktree SHALL pass --force to git worktree remove so a worktree containing uncommitted modifications, untracked files, or both is still deleted; the function is only called from the destructive purge path, where leaving worktree directories on disk after the user already opted into a destructive operation is the wrong behaviour.
Scenario: Worktree fully cleaned up after removal
- GIVEN an existing worktree
- WHEN
remove_worktree()is called - THEN the directory SHALL be deleted and git SHALL no longer track it
Test: git::tests::remove_worktree_cleans_up_fully
Scenario: Dirty worktree is force-removed
- GIVEN an existing worktree containing both a modified tracked file and an untracked file
- WHEN
remove_worktree()is called - THEN the call SHALL succeed
- AND the worktree directory SHALL be deleted from disk
- AND git SHALL no longer track the worktree
Test: git_integration::remove_worktree_force_removes_dirty_worktree
Requirement: Repository validation SHALL work against real git repos
Scenario: Succeeds inside a real git repo
- GIVEN a temporary git repository with an initial commit
- WHEN
validate_repo()is called - THEN it SHALL return the canonicalized repo root
Test: git_integration::validate_repo_succeeds_inside_git_repo
Scenario: Fails outside a git repo
- GIVEN a temporary directory that is not a git repo
- WHEN
validate_repo()is called - THEN it SHALL return an error
Test: git_integration::validate_repo_fails_outside_git_repo
Requirement: Branch listing SHALL work against real git repos
Scenario: Lists created branches
- GIVEN a repo with branches
feature/authandfix/db - WHEN
list_branches()is called - THEN both branches SHALL appear in the result
Test: git_integration::list_branches_includes_created_branches
Scenario: Branches are sorted
- GIVEN branches created in non-alphabetical order
- WHEN
list_branches()is called - THEN results SHALL be alphabetically sorted
Test: git_integration::list_branches_returns_sorted
Scenario: Deduplicates local and remote
- GIVEN a repository with a default branch
- WHEN
list_branches()is called - THEN each branch SHALL appear exactly once
Test: git_integration::list_branches_deduplicates_local_and_remote
Requirement: Worktree lifecycle SHALL work against real git repos
Scenario: Create and remove worktree
- GIVEN a branch in a temporary repo
- WHEN
create_worktree()thenremove_worktree()are called - THEN the worktree SHALL exist after creation and be gone after removal
Test: git_integration::create_and_remove_worktree
Scenario: Worktree placed as sibling of repo
- GIVEN a repo at
<sandbox>/test-repo/ - WHEN
create_worktree()is called - THEN the worktree SHALL be in the same parent directory
Test: git_integration::worktree_placed_as_sibling_of_repo
Scenario: Fails for checked-out branch
- GIVEN the currently checked-out branch
- WHEN
create_worktree()is called for it - THEN it SHALL fail
Test: git_integration::create_worktree_fails_for_checked_out_branch
Requirement: Directory naming SHALL be correct in integration tests
Scenario: Project name from real repo path
- GIVEN a repo at
.../test-repo/ - WHEN
project_name()is called - THEN it SHALL return
"test-repo"
Test: git_integration::project_name_from_repo_path
Scenario: Worktree dir name replaces slashes
- WHEN
worktree_dir_name("my-project", "feature/auth-flow")is called - THEN it SHALL return
"my-project-feature-auth-flow"
Test: git_integration::worktree_dir_name_replaces_slashes
Scenario: Worktree dir name strips unsafe chars
- WHEN
worktree_dir_name("proj", "feat/special@chars!")is called - THEN
@and!SHALL be stripped
Test: git_integration::worktree_dir_name_strips_unsafe_chars
Scenario: Worktree dir name handles nested slashes
- WHEN
worktree_dir_name("proj", "feature/deep/nested/branch")is called - THEN it SHALL return
"proj-feature-deep-nested-branch"
Test: git_integration::worktree_dir_name_handles_nested_slashes
Requirement: Worktree creation produces a usable worktree path
The create_worktree function SHALL create a git worktree for the given branch and return its path. Callers MAY perform post-creation setup (such as AGENTS.md generation) using the returned path.
Scenario: Worktree created at correct path
- GIVEN a git repo and a branch name
- WHEN
create_worktree()is called - THEN it SHALL return the path to the new worktree as a sibling of the repo directory
Test: git::tests::create_worktree_at_correct_path
Scenario: Worktree creation fails for checked-out branch
- GIVEN a branch that is currently checked out
- WHEN
create_worktree()is called - THEN it SHALL return a
PawError::WorktreeError
Test: git::tests::create_worktree_errors_on_checked_out_branch
Tmux Orchestration
Purpose
Orchestrate tmux sessions with multiple panes, each running an AI CLI in a git worktree. Uses a builder pattern for testability and dry-run support, with configurable mouse mode and automatic tiled layout.
Requirements
Requirement: Check tmux availability with actionable error
The system SHALL verify tmux is installed on PATH and provide install instructions if missing.
Scenario: tmux is present on PATH
- GIVEN tmux is installed
- WHEN
ensure_tmux_installed()is called - THEN it SHALL return
Ok(())
Test: tmux::tests::ensure_tmux_installed_succeeds_when_present
Requirement: Create named sessions derived from project name
The system SHALL name tmux sessions as paw-<project_name>.
Scenario: Session named after project
- GIVEN project name
"my-project" - WHEN a session is built
- THEN the session name SHALL be
"paw-my-project"
Test: tmux::tests::session_is_named_after_project
Scenario: Session creation command uses correct name
- GIVEN project name
"app" - WHEN a session is built
- THEN the commands SHALL include
new-sessionwithpaw-app
Test: tmux::tests::session_creation_command_uses_session_name
Requirement: Session creation passes explicit dimensions for headless environments
Both session builders (the basic TmuxSessionBuilder and build_supervisor_session) SHALL emit tmux new-session with -x 200 -y 50 so the session has explicit window dimensions when created without an attached client. The user’s real terminal resizes the session on tmux attach.
Without explicit dimensions, tmux on Linux (apt-shipped tmux 3.4+) errors with size missing on subsequent split-window operations because the layout engine can’t resolve percentages without a known window size.
Additionally, immediately after the new-session command, both builders SHALL emit tmux set-option -g default-size 200x50. This pins the global default-size so subsequent split-window / resize-pane operations have a fallback size context even when no client is attached. macOS tmux honours per-session -x/-y for splits; Linux tmux 3.4+ requires the server-level fallback.
Scenario: Basic session passes -x/-y to new-session
- GIVEN any
TmuxSessionBuilderwith one or more panes - WHEN
command_strings()is invoked - THEN the first command in the output SHALL be a
new-sessioncontaining the substrings-x 200and-y 50
Scenario: Basic session sets global default-size after new-session
- GIVEN any
TmuxSessionBuilderwith one or more panes - WHEN
command_strings()is invoked - THEN the second command in the output SHALL be
set-option -g default-size 200x50
Scenario: Supervisor session passes -x/-y to new-session
- GIVEN a
build_supervisor_sessioninvocation with supervisor + dashboard + N agent panes - WHEN the command list is built
- THEN the first emitted command SHALL be a
new-sessioncontaining-x 200and-y 50
Scenario: Supervisor session sets global default-size after new-session
- GIVEN a
build_supervisor_sessioninvocation - WHEN the command list is built
- THEN the second emitted command SHALL be
set-option -g default-size 200x50
Scenario: Headless supervisor launch succeeds under socket isolation
- GIVEN a cold tmux server (no pre-existing client, isolated socket via
TMUX_TMPDIR) - WHEN
git paw start --supervisor --branches a,bis invoked - THEN the supervisor session SHALL launch successfully
- AND stderr SHALL NOT contain
Tmux error: size missing - AND the exit code SHALL be 0
Test: tmux::tests::built_session_can_be_executed_and_killed, tmux::tests::supervisor_top_row_split_50_50, and the cli_supervisor_no_config::supervisor_without_section_uses_default_when_default_cli_present integration test.
Scenario: Supervisor splits use -l <N>% syntax (tmux 3.1+) not deprecated -p <N>
- GIVEN a
build_supervisor_sessioninvocation with any agent count - WHEN the command list is built
- THEN every emitted
split-windowcommand SHALL use the-l <N>%length flag, NOT the deprecated-p <N>percentage flag
Rationale: Linux apt-tmux 3.4 (Ubuntu 24.04) emits cmd-split-window.c: "size missing" when -p cannot resolve the percentage against the parent pane’s laid-out size — on a detached server with no attached client the pane geometry is unresolved. -l <N>% resolves against the window’s -y dimension (set by new-session -x 200 -y 50) instead, which is well-defined in headless mode. macOS tmux 3.6a tolerates either form.
Test: tmux::tests::supervisor_splits_use_l_percent_not_p.
Requirement: Session name override via builder
The builder SHALL support overriding the default paw-<project> session name with a custom name.
Scenario: Override replaces default name
- GIVEN
session_name("custom-session-name")is set on the builder - WHEN the session is built
- THEN the session name SHALL be
"custom-session-name"and commands SHALL target it
Test: tmux::tests::session_name_override_replaces_default
Requirement: Dynamic pane count matches input
The number of panes in the session SHALL match the number of PaneSpec entries added via the builder. When broker is enabled, the builder SHALL receive an additional PaneSpec for the dashboard in pane 0, increasing the total pane count by one.
Scenario: Two agent panes plus dashboard created
- GIVEN broker is enabled and 2 agent pane specs are added
- WHEN the session is built
- THEN exactly 3 panes SHALL exist: pane 0 (dashboard) + panes 1-2 (agents)
Scenario: Two panes without broker
- GIVEN broker is disabled and 2 pane specs are added
- WHEN the session is built
- THEN exactly 2 panes SHALL exist (same as v0.2.0)
Requirement: Correct commands sent to each pane
Each pane SHALL receive a cd <worktree> && <cli_command> command targeting the correct pane index.
Scenario: Each pane receives cd and CLI command
- GIVEN two panes with different worktrees and CLIs
- WHEN the session is built
- THEN each
send-keyscommand SHALL containcd <worktree> && <cli>
Test: tmux::tests::each_pane_receives_cd_and_cli_command
Scenario: Commands are submitted with Enter
- GIVEN a pane spec
- WHEN the session is built
- THEN the
send-keyscommand SHALL includeEnter
Test: tmux::tests::pane_commands_are_submitted_with_enter
Scenario: Each pane targets a distinct index
- GIVEN 3 panes
- WHEN the session is built
- THEN
send-keysSHALL target:0.0,:0.1, and:0.2respectively
Test: tmux::tests::each_pane_targets_a_distinct_pane_index
Requirement: Pane titles show branch and CLI
Each pane SHALL be titled with <branch> → <cli_command> and border status configured.
Scenario: Pane titles contain branch and CLI
- GIVEN panes with branches and CLIs
- WHEN the session is built
- THEN
select-pane -Tcommands SHALL set titles like"feat/auth → claude"
Test: tmux::tests::each_pane_is_titled_with_branch_and_cli
Scenario: Pane border status configured
- GIVEN any session
- WHEN the session is built
- THEN
pane-border-statusSHALL be set totopandpane-border-formatSHALL use#{pane_title}
Test: tmux::tests::pane_border_status_is_configured
Requirement: Configurable mouse mode per session
Mouse mode SHALL be enabled by default and be disableable via the builder.
Scenario: Mouse mode enabled by default
- GIVEN no explicit mouse mode setting
- WHEN the session is built
- THEN a
mouse oncommand SHALL be emitted
Test: tmux::tests::mouse_mode_enabled_by_default
Scenario: Mouse mode can be disabled
- GIVEN
mouse_mode(false)is set on the builder - WHEN the session is built
- THEN no
mouse oncommand SHALL be emitted
Test: tmux::tests::mouse_mode_can_be_disabled
Requirement: Attach to a tmux session
The system SHALL attach the current terminal to a named tmux session, returning an error if the session does not exist.
Scenario: Attaching to a nonexistent session fails
- GIVEN no tmux session with the given name exists
- WHEN
attach()is called - THEN it SHALL return an error
Test: e2e_tests::attach_fails_for_nonexistent_session
Requirement: Session liveness check
The system SHALL check whether a tmux session is alive by name.
Scenario: Nonexistent session reports not alive
- GIVEN no tmux session with the queried name exists
- WHEN
is_session_alive()is called - THEN it SHALL return
false
Test: tmux::tests::is_session_alive_returns_false_for_nonexistent
Requirement: Session lifecycle management
The system SHALL support creating, checking, and killing tmux sessions.
Scenario: Full create-check-kill lifecycle
- GIVEN a tmux session is created
- WHEN
is_session_alive()is called, thenkill_session(), thenis_session_alive()again - THEN it SHALL be alive after creation and not alive after killing
Test: tmux::tests::session_lifecycle_create_check_kill
Scenario: Built session can be executed and killed
- GIVEN a session built via
TmuxSessionBuilder - WHEN
execute()is called - THEN the tmux session SHALL be alive, and after
kill_session()it SHALL be gone
Test: tmux::tests::built_session_can_be_executed_and_killed
Requirement: Session name collision resolution
The system SHALL resolve name collisions by appending -2, -3, etc. to the base session name.
Scenario: No collision returns base name
- GIVEN no existing session with the base name
- WHEN
resolve_session_name()is called - THEN it SHALL return
paw-<project_name>
Test: tmux::tests::resolve_session_name_returns_base_when_no_collision
Scenario: Collision appends numeric suffix
- GIVEN a session with the base name already exists
- WHEN
resolve_session_name()is called - THEN it SHALL return
paw-<project_name>-2
Test: tmux::tests::resolve_session_name_appends_suffix_on_collision
Requirement: Tmux session lifecycle SHALL work against a real tmux server
Scenario: Create and kill session lifecycle
- GIVEN a tmux session is created via the builder
- WHEN
execute(),is_session_alive(), andkill_session()are called - THEN the session SHALL be alive after creation and gone after killing
Test: e2e_tests::tmux_session_create_and_kill_lifecycle
Scenario: Five panes with different CLIs
- GIVEN 5 pane specs with different branch/CLI pairs
- WHEN the session is executed
- THEN tmux SHALL have 5 panes with correct titles
Test: e2e_tests::tmux_session_with_five_panes_and_different_clis
Scenario: Mouse mode enabled by default against live tmux
- GIVEN a session built with default settings
- WHEN
tmux show-optionis queried - THEN mouse SHALL be “on”
Test: e2e_tests::tmux_mouse_mode_enabled_by_default
Scenario: is_session_alive returns false for nonexistent (e2e)
- GIVEN no session with the queried name
- WHEN
is_session_alive()is called - THEN it SHALL return
false
Test: e2e_tests::tmux_is_session_alive_returns_false_for_nonexistent
Scenario: Attach succeeds for live session
- GIVEN a live tmux session
- WHEN
attach()is called and the client is detached programmatically - THEN the function SHALL execute without panic
Test: e2e_tests::attach_succeeds_for_live_session
Requirement: E2E commands SHALL behave correctly against real repos
Scenario: Dry run shows session plan
- GIVEN a git repo with branches and
--dry-run --cli echo --branches feat/a,feat/b - WHEN the binary runs
- THEN stdout SHALL contain “Dry run”, branch names, and the CLI name
Test: e2e_tests::dry_run_with_flags_shows_plan
Scenario: Preset not found returns error
- GIVEN a git repo with no presets configured
- WHEN
start --preset nonexistentis run - THEN it SHALL fail with stderr mentioning “not found”
Test: e2e_tests::preset_not_found_returns_error
Scenario: Stop with no session
- GIVEN a git repo with no active session
- WHEN
stopis run - THEN it SHALL succeed with stdout mentioning “No active session”
Test: e2e_tests::stop_with_no_session
Scenario: Purge with no session
- GIVEN a git repo with no active session
- WHEN
purge --forceis run - THEN it SHALL succeed with stdout mentioning “No session to purge”
Test: e2e_tests::purge_with_no_session
Scenario: Status with no session
- GIVEN a git repo with no active session
- WHEN
statusis run - THEN it SHALL succeed with stdout mentioning “No session”
Test: e2e_tests::status_with_no_session
Scenario: Stop from non-git directory fails
- GIVEN a directory that is not a git repository
- WHEN
stopis run - THEN it SHALL fail with “Not a git repository”
Test: e2e_tests::stop_from_non_git_dir_fails
Scenario: Status from non-git directory fails
- GIVEN a directory that is not a git repository
- WHEN
statusis run - THEN it SHALL fail with “Not a git repository”
Test: e2e_tests::status_from_non_git_dir_fails
Requirement: TmuxSession supports pipe-pane command
The TmuxSession builder SHALL support queuing a pipe-pane command to attach logging to a specific pane.
Scenario: pipe-pane queued in builder
- WHEN
pipe_pane()is called on aTmuxSessionwith a pane target and log path - THEN the command queue SHALL contain a
pipe-pane -o -t <pane> "cat >> <path>"entry
Scenario: pipe-pane in dry-run output
- WHEN a session with
pipe_pane()is rendered as dry-run - THEN the output SHALL include the
tmux pipe-panecommand string
Scenario: pipe-pane executed after pane creation
- WHEN the session commands are executed
- THEN the
pipe-panecommand SHALL execute after the correspondingsplit-windowandsend-keyscommands for that pane
Requirement: TmuxSession supports session-level environment variables
The TmuxSessionBuilder SHALL support setting session-level environment variables via a set_environment(key, value) method. The resulting set-environment -t <session> <key> <value> command SHALL be emitted before any send-keys commands to ensure all panes inherit the variable.
Scenario: set_environment emits correct tmux command
- GIVEN
set_environment("GIT_PAW_BROKER_URL", "http://127.0.0.1:9119")is called on the builder - WHEN the session is built
- THEN the command queue SHALL contain
set-environment -t <session> GIT_PAW_BROKER_URL http://127.0.0.1:9119
Scenario: set_environment appears before send-keys
- GIVEN a builder with environment variables and pane specs
- WHEN the session is built
- THEN all
set-environmentcommands SHALL appear before anysend-keyscommands in the command queue
Scenario: set_environment in dry-run output
- GIVEN a builder with
set_environmentcalled - WHEN the session is rendered as dry-run
- THEN the output SHALL include the
tmux set-environmentcommand string
Scenario: Multiple environment variables
- GIVEN
set_environment("A", "1")andset_environment("B", "2")are both called - WHEN the session is built
- THEN both
set-environmentcommands SHALL appear in the command queue
Requirement: Supervisor-mode pane layout
When the tmux session is built for supervisor mode (per the supervisor-launch capability), the system SHALL produce a layout with these structural properties:
-
Top row: split horizontally 50/50 between pane 0 (supervisor agent) and pane 1 (dashboard).
-
Agent grid below: dynamically sized by agent count, with up to 5 columns per row in v0.5.0. The agent grid is a sequence of horizontal rows; each row holds up to 5 agent panes side-by-side.
-
Pane indices: pane 0 = supervisor; pane 1 = dashboard; panes 2..N+1 = coding agents in row-major order (left-to-right, top-to-bottom).
-
Vertical proportions by total-row count (top row + agent rows):
Total rows Top row height Each agent row height 2 (1-5 agents) 60% 40% 3 (6-10 agents) 40% 30% each 4 (11-15 agents) 28% 24% each 5 (16-20 agents) 28% 18% each 6 (21-25 agents) 28% 14.4% each -
Hard cap: 25 agents per session. Above 25, the system SHALL reject the launch with a clear “split into multiple sessions” error before any tmux command runs.
The layout SHALL be built using tmux split-window -h and -v with explicit percentages, then enforced via tmux resize-pane -y <pct> for the height proportions. select-layout tiled (or other auto-layouts) SHALL NOT be used for the supervisor-mode layout because they don’t preserve the predictable pane-index ordering this layout relies on.
Scenario: 5-agent supervisor layout has 1 agent row
- GIVEN a supervisor session with 5 agent branches
- WHEN the tmux layout is built
- THEN pane 0 SHALL be the supervisor at 50% of the top row’s width
- AND pane 1 SHALL be the dashboard at 50% of the top row’s width
- AND panes 2-6 SHALL be agents arranged in a single row below the top row
- AND the top row’s height SHALL be 60% and the agent row’s height SHALL be 40%
Scenario: 10-agent supervisor layout has 2 agent rows
- GIVEN a supervisor session with 10 agent branches
- WHEN the tmux layout is built
- THEN total row count SHALL be 3 (1 top + 2 agent rows)
- AND the top row’s height SHALL be 40%
- AND each agent row’s height SHALL be 30%
- AND the first agent row SHALL contain panes 2-6, the second agent row SHALL contain panes 7-11
Scenario: 20-agent supervisor layout has 4 agent rows
- GIVEN a supervisor session with 20 agent branches
- WHEN the tmux layout is built
- THEN total row count SHALL be 5 (1 top + 4 agent rows)
- AND the top row’s height SHALL be 28%
- AND each of the 4 agent rows’ height SHALL be 18%
Scenario: 26-agent supervisor session is rejected
- GIVEN 26 agent branches resolved (via specs, –branches, or a combination)
- WHEN the supervisor launch flow runs
- THEN the launch SHALL be rejected with a
PawError - AND the error message SHALL state the requested count (26), the maximum (25), and a hint suggesting
--branches <subset>for splitting into multiple sessions - AND no tmux session SHALL be created
Scenario: Pane indices match row-major order
- GIVEN a supervisor session with 7 agents
- WHEN the tmux layout is built
- THEN pane 2 SHALL be the first agent (top-left of the agent grid)
- AND pane 6 SHALL be the fifth agent (top-right of the first agent row, since
agents_per_row = 5) - AND pane 7 SHALL be the sixth agent (start of the second agent row)
Session State
Purpose
Persist session state to disk for recovery after crashes, reboots, or manual stops. Stores one JSON file per session under the XDG data directory, with atomic writes and tmux liveness checks.
Requirements
Requirement: Save session state atomically
The system SHALL serialize session data to JSON and write it atomically using a temp file and rename to prevent corruption.
The session data SHALL include optional broker fields: broker_port (Option<u16>), broker_bind (Option<String>), and broker_log_path (Option<PathBuf>). These fields SHALL be omitted from the JSON when None and SHALL default to None when absent during deserialization.
Scenario: Saved session round-trips with all fields intact
- GIVEN an active session with 3 worktrees
- WHEN
save_session()is called and the session is loaded back - THEN all fields (session_name, repo_path, project_name, created_at, status, worktrees) SHALL match the original
Scenario: Saved session with broker fields round-trips
- GIVEN an active session with
broker_port = Some(9119),broker_bind = Some("127.0.0.1"),broker_log_path = Some("/path/to/broker.log") - WHEN
save_session()is called and the session is loaded back - THEN all broker fields SHALL match the original
Scenario: Session without broker fields loads successfully
- GIVEN a session JSON file saved by v0.2.0 (no broker fields)
- WHEN the session is loaded
- THEN
broker_port,broker_bind, andbroker_log_pathSHALL all beNone - AND all existing fields SHALL load correctly
Scenario: Saving again replaces previous state
- GIVEN a previously saved session
- WHEN
save_session()is called with updated fields - THEN the new state SHALL overwrite the old state
Requirement: Load session by name
The system SHALL load a session from disk by name, returning None if the file does not exist.
Scenario: Loading a nonexistent session returns None
- GIVEN no session file exists with the given name
- WHEN
load_session()is called - THEN it SHALL return
Ok(None)
Test: session::tests::loading_nonexistent_session_returns_none
Requirement: Find session by repository path
The system SHALL scan all session files and return the session matching a given repository path.
Scenario: Finds correct session among multiple
- GIVEN two sessions for different repositories
- WHEN
find_session_for_repo()is called with one repo path - THEN it SHALL return the matching session
Test: session::tests::finds_correct_session_among_multiple_by_repo_path
Scenario: No matching session
- GIVEN saved sessions for other repositories
- WHEN
find_session_for_repo()is called with a different path - THEN it SHALL return
None
Test: session::tests::find_returns_none_when_no_repo_matches
Scenario: No sessions directory
- GIVEN no sessions directory exists
- WHEN
find_session_for_repo()is called - THEN it SHALL return
None
Test: session::tests::find_returns_none_when_no_sessions_exist
Requirement: Delete session by name
The system SHALL delete a session file, succeeding even if the file does not exist (idempotent).
Scenario: Deleted session is no longer loadable
- GIVEN a saved session
- WHEN
delete_session()is called - THEN
load_session()SHALL returnNone
Test: session::tests::deleted_session_is_no_longer_loadable
Scenario: Deleting nonexistent session succeeds
- GIVEN no session file with the given name
- WHEN
delete_session()is called - THEN it SHALL return
Ok(())
Test: session::tests::deleting_nonexistent_session_succeeds
Requirement: Effective status combines file state with tmux liveness
Session::effective_status(is_tmux_alive) SHALL combine the persisted status field with the result of is_tmux_alive to produce the runtime-effective status:
| Recorded status | tmux alive? | Effective status |
|---|---|---|
Active | yes | Active |
Active | no | Stopped |
Paused | yes | Paused |
Paused | no | Stopped |
Stopped | any | Stopped |
The rule for Paused: tmux must still be alive for the Paused state to be valid — pause’s whole purpose is to keep tmux + CLI panes running while the client is detached. If tmux died despite a recorded Paused state (e.g. tmux server crash), effective_status SHALL downgrade to Stopped, and cmd_start SHALL run the cold-recovery path (fresh CLI spawn) rather than the restart-from-pause path.
Scenario: Active + alive remains Active
- GIVEN a session with
status = Active - WHEN
effective_status(|_| true)is called - THEN it SHALL return
Active
Scenario: Active + dead downgrades to Stopped
- GIVEN a session with
status = Active - WHEN
effective_status(|_| false)is called - THEN it SHALL return
Stopped
Scenario: Paused + alive remains Paused
- GIVEN a session with
status = Paused - WHEN
effective_status(|_| true)is called - THEN it SHALL return
Paused
Scenario: Paused + dead downgrades to Stopped
- GIVEN a session with
status = Paused - WHEN
effective_status(|_| false)is called - THEN it SHALL return
Stopped
Scenario: Stopped remains Stopped regardless of tmux liveness
- GIVEN a session with
status = Stopped - WHEN
effective_statusis called with either liveness result - THEN it SHALL return
Stopped
Requirement: SessionStatus display format
The SessionStatus enum SHALL display as lowercase strings.
Scenario: SessionStatus display strings
- GIVEN
SessionStatus::ActiveandSessionStatus::Stopped - WHEN formatted with
Display - THEN they SHALL render as
"active"and"stopped"
Test: session::tests::session_status_displays_as_lowercase_string
Requirement: Recovery data survives tmux crashes
After a tmux crash, the persisted session SHALL contain all data needed to reconstruct the session.
Scenario: Crashed session has all recovery data including broker fields
- GIVEN a saved session with worktrees and broker enabled
- WHEN tmux crashes and the session is loaded from disk
- THEN it SHALL have the session name, repo path, all worktree details, AND broker_port, broker_bind, broker_log_path
Scenario: Session recovery recreates dashboard pane when broker was enabled
- GIVEN a saved session with
broker_port = Some(9119)andbroker_bind = Some("127.0.0.1") - WHEN
recover_session()is called - THEN the rebuilt tmux session SHALL have:
- Dashboard pane in pane 0 running
git-paw __dashboard GIT_PAW_BROKER_URLenvironment variable set tohttp://127.0.0.1:9119- All original worktree panes in subsequent indices
- Dashboard pane in pane 0 running
Scenario: Session recovery uses original broker config, not current config
- GIVEN a saved session with
broker_port = Some(9119) - AND current repo config has
broker.enabled = false - WHEN
recover_session()is called - THEN the dashboard pane SHALL still be created with the original broker URL
Scenario: Session recovery without original broker creates no dashboard
- GIVEN a saved session with
broker_port = None - WHEN
recover_session()is called - THEN no dashboard pane SHALL be created
Requirement: Session persistence SHALL work through the public API
Scenario: Save and load round-trip
- GIVEN a session with 2 worktrees
- WHEN
save_session_in()andload_session_from()are called - THEN all fields SHALL match
Test: session_integration::save_and_load_round_trip
Scenario: Find session by repo path
- GIVEN a saved session
- WHEN
find_session_for_repo_in()is called with the matching repo path - THEN the correct session SHALL be returned
Test: session_integration::find_session_by_repo_path
Scenario: Find returns None for unknown repo
- GIVEN no matching session
- WHEN
find_session_for_repo_in()is called - THEN it SHALL return
None
Test: session_integration::find_session_returns_none_for_unknown_repo
Scenario: Find correct session among multiple
- GIVEN two sessions for different repos
- WHEN
find_session_for_repo_in()is called for one - THEN the correct session SHALL be returned
Test: session_integration::find_correct_session_among_multiple
Scenario: Delete removes session
- GIVEN a saved session
- WHEN
delete_session_in()is called - THEN
load_session_from()SHALL returnNone
Test: session_integration::delete_removes_session
Scenario: Delete nonexistent is idempotent
- GIVEN no session file
- WHEN
delete_session_in()is called - THEN it SHALL succeed
Test: session_integration::delete_nonexistent_is_idempotent
Scenario: Load nonexistent returns None
- GIVEN no session file
- WHEN
load_session_from()is called - THEN it SHALL return
None
Test: session_integration::load_nonexistent_returns_none
Scenario: Saving again replaces previous state
- GIVEN a saved session
- WHEN the status is changed and saved again
- THEN the loaded session SHALL have the new status
Test: session_integration::saving_again_replaces_previous_state
Scenario: Effective status active when tmux alive
- GIVEN a session with
Activestatus and tmux alive - WHEN
effective_status()is called - THEN it SHALL return
Active
Test: session_integration::effective_status_active_when_tmux_alive
Scenario: Effective status stopped when tmux dead
- GIVEN a session with
Activestatus and tmux dead - WHEN
effective_status()is called - THEN it SHALL return
Stopped
Test: session_integration::effective_status_stopped_when_tmux_dead
Scenario: Effective status stopped stays stopped
- GIVEN a session with
Stoppedstatus - WHEN
effective_status()is called - THEN it SHALL return
Stoppedregardless of tmux
Test: session_integration::effective_status_stopped_stays_stopped
Scenario: Saved session has all recovery fields
- GIVEN a saved and reloaded session
- WHEN recovery fields are checked
- THEN session_name, repo_path, project_name, and all worktree entries SHALL be non-empty
Test: session_integration::saved_session_has_all_recovery_fields
Requirement: Paused session status variant
The SessionStatus enum SHALL include a third variant Paused (alongside Active and Stopped). The serde representation SHALL serialize as the lowercase string "paused" and SHALL deserialize from the same string. The Display implementation SHALL render Paused as "paused".
The Paused state means: the tmux session is intended to remain alive, all coding-agent CLI panes are intended to remain running, the user’s tmux client is detached, and the broker is stopped. Session state files saved by v0.4.0 binaries (which only know Active and Stopped) SHALL continue to load successfully under v0.5+ binaries — the new variant only appears in files saved by v0.5+.
Scenario: Paused status serializes lowercase
- GIVEN a
Sessionwithstatus = SessionStatus::Paused - WHEN
save_session()is called and the JSON file is inspected - THEN the
"status"field SHALL be"paused"
Scenario: Paused status round-trips
- GIVEN a
Sessionwithstatus = SessionStatus::Pausedsaved to disk - WHEN the session is loaded back via
load_session() - THEN
statusSHALL beSessionStatus::Paused
Scenario: v0.4-saved sessions load under v0.5
- GIVEN a session JSON file saved by v0.4.0 (only
"active"or"stopped"in the status field) - WHEN the file is loaded by a v0.5+ binary
- THEN the load SHALL succeed
- AND the
statusfield SHALL match the original (ActiveorStopped)
Scenario: Paused Display renders lowercase
- WHEN
format!("{}", SessionStatus::Paused)is evaluated - THEN the result SHALL be
"paused"
Requirement: Dashboard pane index persisted in session state
The Session struct SHALL include an optional field dashboard_pane: Option<u32> that records the pane index of the dashboard pane within the tmux session. The field SHALL use #[serde(default, skip_serializing_if = "Option::is_none")] so v0.4-saved sessions load with None. The field SHALL be populated by the start flow when broker is enabled (typically 0 for bare-start mode and 1 for supervisor mode).
The restart-from-pause flow (specced in the broker-lifecycle delta) SHALL read this field to determine where to re-spawn the dashboard pane. When the field is None (v0.4-saved session), the restart flow SHALL default to 0.
Scenario: Dashboard pane index round-trips
- GIVEN a
Sessionwithdashboard_pane = Some(1)saved to disk - WHEN the session is loaded back
- THEN
dashboard_paneSHALL beSome(1)
Scenario: Session without dashboard_pane defaults to None on load
- GIVEN a session JSON file with no
dashboard_panefield - WHEN the session is loaded
- THEN
dashboard_paneSHALL beNone
Scenario: Dashboard pane field is omitted when None
- GIVEN a
Sessionwithdashboard_pane = None - WHEN
save_session()is called and the JSON file is inspected - THEN the JSON SHALL NOT contain a
dashboard_panefield
Configuration
Purpose
Parse TOML configuration from global (~/.config/git-paw/config.toml) and per-repo (.git-paw/config.toml) files. Supports custom CLI definitions, presets, and programmatic add/remove of custom CLIs with repo config overriding global config.
Requirements
Requirement: Parse TOML config with all fields
The system SHALL parse a TOML configuration file containing default_cli, mouse, clis, presets, and optional sections [specs], [logging], [broker], and [supervisor].
Scenario: Config with all fields populated
- GIVEN a TOML file with
default_cli,mouse, custom CLIs, presets,[broker], and[supervisor]sections - WHEN the file is loaded
- THEN all fields SHALL be correctly parsed including supervisor fields
Scenario: All fields are optional
- GIVEN a TOML file with only
default_cli - WHEN the file is loaded
- THEN missing fields SHALL default to
Noneor empty collections - AND
supervisorSHALL beNone
Requirement: Merge repo config over global config
The system SHALL merge per-repo configuration on top of global configuration, with repo values taking precedence for scalar fields and map entries.
Scenario: Repo overrides global scalar fields
- GIVEN global config has
default_cli = "claude"andmouse = true, and repo hasdefault_cli = "gemini" - WHEN configs are merged
- THEN
default_cliSHALL be"gemini"andmouseSHALL betrue(preserved from global)
Test: config::tests::repo_config_overrides_global_scalars
Scenario: CLI maps are merged
- GIVEN global config has CLI
agent-aand repo config has CLIagent-b - WHEN configs are merged
- THEN both CLIs SHALL be present
Test: config::tests::repo_config_merges_cli_maps
Scenario: Repo CLI overrides global CLI with same name
- GIVEN both global and repo define a CLI named
my-agent - WHEN configs are merged
- THEN the repo definition SHALL win
Test: config::tests::repo_cli_overrides_global_cli_with_same_name
Scenario: Only global config exists
- GIVEN a global config file but no repo config
- WHEN
load_config()is called - THEN global values SHALL be used
Test: config::tests::load_config_from_reads_global_file_when_no_repo
Scenario: Only repo config exists
- GIVEN a repo config file but no global config
- WHEN
load_config()is called - THEN repo values SHALL be used
Test: config::tests::load_config_from_reads_repo_file_when_no_global
Requirement: Preset lookup by name
The system SHALL provide access to named presets that define branches and a CLI.
Scenario: Preset accessible by name
- GIVEN a config with a preset named
"backend" - WHEN
get_preset("backend")is called - THEN it SHALL return the preset with its branches and CLI
Test: config::tests::preset_accessible_by_name
Scenario: Missing preset returns None
- GIVEN a config without the requested preset
- WHEN
get_preset("nonexistent")is called - THEN it SHALL return
None
Test: config::tests::preset_returns_none_when_not_in_config
Requirement: Add custom CLIs to global config
The system SHALL add custom CLI definitions to the global config, resolving non-absolute commands via PATH.
Scenario: Add CLI with absolute path
- GIVEN an absolute path to a CLI binary
- WHEN
add_custom_cli()is called - THEN the CLI SHALL be written to the config file
Test: config::tests::add_cli_writes_to_config_file
Scenario: Adding preserves existing entries
- GIVEN an existing CLI in the config
- WHEN a second CLI is added
- THEN both CLIs SHALL be present
Test: config::tests::add_cli_preserves_existing_entries
Scenario: Adding CLI with missing command fails
- GIVEN a command that does not exist on PATH
- WHEN
add_custom_cli()is called - THEN it SHALL return an error mentioning “not found on PATH”
Test: config::tests::add_cli_errors_when_command_not_on_path
Requirement: Remove custom CLIs from global config
The system SHALL remove a custom CLI by name, returning an error if the CLI is not found.
Scenario: Remove existing CLI
- GIVEN a config with CLIs
keep-meandremove-me - WHEN
remove_custom_cli("remove-me")is called - THEN only
keep-meSHALL remain
Test: config::tests::remove_cli_deletes_entry_from_config_file
Scenario: Remove nonexistent CLI returns error
- GIVEN a config without the named CLI
- WHEN
remove_custom_cli()is called - THEN it SHALL return
PawError::CliNotFound
Test: config::tests::remove_nonexistent_cli_returns_cli_not_found_error
Scenario: Remove CLI from empty/missing config returns error
- GIVEN no config file exists
- WHEN
remove_custom_cli()is called - THEN it SHALL return
PawError::CliNotFound
Test: config::tests::remove_cli_from_empty_config_returns_error
Requirement: Config survives round-trip serialization
A PawConfig SHALL be identical after save and reload.
Scenario: Config round-trip
- GIVEN a fully populated config
- WHEN saved and loaded back
- THEN it SHALL be equal to the original
Test: config::tests::config_survives_save_and_load
Requirement: Config loading SHALL work with real files
The system SHALL provide a load_config(repo_root, user_config_path) function that loads the merged PawConfig from the per-repo .git-paw/config.toml and a user-level (global) config.toml. The second parameter user_config_path: Option<&Path> SHALL control which file is read as the user-level config:
- When
user_config_pathisNone, the loader SHALL resolve the user-level config path via the platform-default helper (global_config_path()→crate::dirs::config_dir().join("git-paw/config.toml")), preserving the v0.4 production behaviour. - When
user_config_pathisSome(p), the loader SHALL readpas the user-level config and SHALL NOT consult the platform-default helper. Ifpdoes not exist on disk, the user-level side of the merge SHALL be the defaultPawConfig, exactly as if no file existed at the platform-default path.
The merge semantics on top of the user-level config (per-repo config overrides user-level for scalar fields and map entries) are unchanged from prior requirements in this capability.
Scenario: Defaults when no files exist
- GIVEN a temp directory with no config files
- AND
load_configis called withuser_config_path = None - WHEN
load_config()is called - THEN all fields SHALL be None/empty
Test: config_integration::load_config_returns_defaults_when_no_files_exist
Scenario: Reads repo .git-paw/config.toml
- GIVEN a
.git-paw/config.tomlwith default_cli and mouse - AND
load_configis called withuser_config_path = Some(&unused_temp_path) - WHEN
load_config()is called - THEN the values SHALL be read correctly
Test: config_integration::load_config_reads_repo_config
Scenario: Repo config with custom CLIs
- GIVEN a
.git-paw/config.tomlwith two custom CLIs - AND
load_configis called withuser_config_path = Some(&unused_temp_path) - WHEN
load_config()is called - THEN both CLIs SHALL be parsed with correct fields
Test: config_integration::repo_config_with_custom_clis
Scenario: Repo config with presets
- GIVEN a
.git-paw/config.tomlwith two presets - AND
load_configis called withuser_config_path = Some(&unused_temp_path) - WHEN
load_config()is called - THEN presets SHALL be accessible with correct branches and CLI
Test: config_integration::repo_config_with_presets
Scenario: Default PawConfig has no presets
- GIVEN a default
PawConfig - WHEN
get_preset("nonexistent")is called - THEN it SHALL return
None
Test: config_integration::get_preset_returns_none_for_unknown
Scenario: Repo config overrides default fields
- GIVEN a
.git-paw/config.tomlwith specific values - AND
load_configis called withuser_config_path = Some(&unused_temp_path) - WHEN
load_config()is called - THEN the repo values SHALL take precedence
Test: config_integration::repo_config_overrides_default_fields
Scenario: Repo config path is correct
- GIVEN a temp directory
- WHEN
repo_config_path()is called - THEN it SHALL return
<dir>/.git-paw/config.toml
Test: config_integration::repo_config_path_is_in_repo_root
Scenario: Malformed TOML returns error
- GIVEN a
.git-paw/config.tomlwith invalid TOML - AND
load_configis called withuser_config_path = Some(&unused_temp_path) - WHEN
load_config()is called - THEN it SHALL return an error
Test: config_integration::malformed_toml_returns_error
Scenario: Empty config file is valid
- GIVEN an empty
.git-paw/config.toml - AND
load_configis called withuser_config_path = Some(&unused_temp_path) - WHEN
load_config()is called - THEN it SHALL return a default config
Test: config_integration::empty_config_file_is_valid
Scenario: None preserves platform-default user-config resolution
- GIVEN a repo
TempDirwith no.git-paw/config.toml - AND the platform-default user config path (
crate::dirs::config_dir().join("git-paw/config.toml")) is a readable file containing a custom CLI namedglobally-registered - WHEN
load_config(&repo, None)is called - THEN the returned
PawConfig.clisSHALL containglobally-registered - AND the loader SHALL have resolved the user-level path via
global_config_path(), exactly matching v0.4 behaviour
Test: config::tests::load_config_with_none_reads_platform_default_global
Scenario: Some(path) pins the user-level read to that path
- GIVEN a
TempDircontaining two distinct files:tmp/global-A.tomldefining custom CLIcli-Atmp/global-B.tomldefining custom CLIcli-B
- AND an unrelated CLI
cli-Cis registered at the platform-default user-config path - WHEN
load_config(&repo, Some(&tmp.join("global-A.toml")))is called - THEN the returned
PawConfig.clisSHALL containcli-A - AND it SHALL NOT contain
cli-Borcli-C
Test: config::tests::load_config_with_some_pins_global_to_override_path
Scenario: Some(nonexistent path) returns defaults for the user-level side
- GIVEN a
TempDirand a pathtmp/does-not-exist.tomlthat has never been written - AND an unrelated CLI
cli-leakis registered at the platform-default user-config path - WHEN
load_config(&repo, Some(&tmp.join("does-not-exist.toml")))is called - THEN the user-level side of the merge SHALL be the default
PawConfig - AND the returned
PawConfig.clisSHALL NOT containcli-leak - AND no error SHALL be returned (a missing user-config file is not an error)
Test: config::tests::load_config_with_some_nonexistent_returns_defaults
Scenario: Override path does not affect repo-config resolution
- GIVEN a
TempDirwith.git-paw/config.tomldefiningdefault_cli = "claude" - AND a separate path
tmp/global.tomldefiningdefault_cli = "gemini" - WHEN
load_config(&tmp, Some(&tmp.join("global.toml")))is called - THEN the repo-level
default_cli = "claude"SHALL override the user-leveldefault_cli = "gemini"per the existing repo-overrides-user merge semantics - AND the override parameter SHALL only control which user-level file is read, never the repo-level resolution
Test: config::tests::load_config_override_does_not_affect_repo_resolution
Requirement: Custom CLI management SHALL persist through file I/O
Scenario: Add CLI with absolute path
- GIVEN no config file
- WHEN
add_custom_cli_to()is called with an absolute path - THEN the CLI SHALL be persisted and reloadable
Test: config_integration::add_custom_cli_with_absolute_path
Scenario: Add CLI with display name
- GIVEN no config file
- WHEN
add_custom_cli_to()is called with a display name - THEN the display name SHALL be persisted
Test: config_integration::add_custom_cli_with_display_name
Scenario: Multiple CLIs preserved across adds
- GIVEN 4 CLIs added sequentially
- WHEN the config is loaded
- THEN all 4 SHALL be present with correct fields
Test: config_integration::add_multiple_custom_clis_preserves_all
Scenario: Adding overwrites existing entry
- GIVEN a CLI with name
my-agentalready exists - WHEN
add_custom_cli_to()is called with the same name but different values - THEN the new values SHALL replace the old
Test: config_integration::add_cli_overwrites_existing_entry
Scenario: Add CLI with nonexistent command fails
- GIVEN a non-absolute command that is not on PATH
- WHEN
add_custom_cli_to()is called - THEN it SHALL return an error
Test: config_integration::add_cli_with_nonexistent_path_command_fails
Scenario: Remove custom CLI
- GIVEN two CLIs in the config
- WHEN one is removed
- THEN only the other SHALL remain
Test: config_integration::remove_custom_cli
Scenario: Remove nonexistent CLI returns error
- GIVEN no CLIs in the config
- WHEN
remove_custom_cli_from()is called - THEN it SHALL return an error
Test: config_integration::remove_nonexistent_cli_returns_error
Scenario: Remove all CLIs leaves empty config
- GIVEN one CLI in the config
- WHEN it is removed
- THEN the CLI map SHALL be empty
Test: config_integration::remove_all_custom_clis_leaves_empty_config
Requirement: Global and repo config SHALL merge custom CLIs correctly
Scenario: Repo custom CLIs merge with global
- GIVEN global config with 2 CLIs and repo config with 2 CLIs (one overlapping)
- WHEN
load_config_from()is called - THEN the result SHALL have 3 CLIs, with repo winning on collision
Test: config_integration::repo_custom_clis_merge_with_global_custom_clis
Requirement: Config SHALL handle many custom CLIs
Scenario: Config with 10 custom CLIs
- GIVEN a config file with 10 custom CLI definitions
- WHEN
load_config()is called - THEN all 10 SHALL be parsed correctly
Test: config_integration::config_with_many_custom_clis
Requirement: The system SHALL support a default_spec_cli config field
The system SHALL support a default_spec_cli field in PawConfig that specifies the CLI to use for --from-specs branches that don’t have a paw_cli override, bypassing the interactive picker.
Scenario: default_spec_cli set
- WHEN a config has
default_spec_cli = "claude" - THEN
PawConfig.default_spec_cliSHALL beSome("claude")
Scenario: default_spec_cli absent
- WHEN a config has no
default_spec_clifield - THEN
PawConfig.default_spec_cliSHALL beNone
Scenario: Merge preserves repo override
- WHEN global config has
default_spec_cli = "claude"and repo config hasdefault_spec_cli = "gemini" - THEN the merged config SHALL have
default_spec_cli = Some("gemini")
Requirement: Repo SHALL override new v0.2.0 scalar fields
Scenario: Repo overrides new v0.2.0 scalar fields
- GIVEN global config has
default_spec_cli = "claude"and repo hasdefault_spec_cli = "gemini" - WHEN configs are merged
- THEN
default_spec_cliSHALL be"gemini"
Requirement: Specs configuration section
The system SHALL support an optional [specs] section with a dir field and a type field. Field names SHALL match the spec-scanning capability and the implementation in src/config.rs::SpecsConfig.
dir: String— path (relative to the repo root) to the directory containing spec filestype: String— backend identifier (e.g."openspec","markdown"); the field is exposed asspec_typein Rust to avoid clashing with thetypekeyword and is serialised astypein TOML/JSON via#[serde(rename = "type")]
When the [specs] section is absent, the optional specs field on PawConfig SHALL be None.
Scenario: Specs section with all fields
- GIVEN a TOML file with
[specs]containingdir = "openspec/specs"andtype = "openspec" - WHEN the file is loaded
- THEN
specs.dirSHALL be"openspec/specs" - AND
specs.spec_typeSHALL be"openspec"
Scenario: Specs section defaults
- GIVEN a TOML file without a
[specs]section - WHEN the file is loaded
- THEN
specsSHALL beNone
Scenario: Round-trip preserves rename
- GIVEN a
SpecsConfig { dir: "openspec/specs".into(), spec_type: "openspec".into() } - WHEN the value is serialised to TOML and parsed back
- THEN the resulting TOML SHALL contain
type = "openspec"(notspec_type) - AND parsing SHALL succeed and reproduce the original struct
Requirement: Logging configuration section
The system SHALL support an optional [logging] section with enabled and log_dir fields.
Scenario: Logging section with all fields
- GIVEN a TOML file with
[logging]containingenabled = trueandlog_dir = ".git-paw/logs" - WHEN the file is loaded
- THEN
logging.enabledSHALL betrueandlogging.log_dirSHALL be".git-paw/logs"
Scenario: Logging section defaults
- GIVEN a TOML file without a
[logging]section - WHEN the file is loaded
- THEN
loggingSHALL beNone
Requirement: Default config generation
The system SHALL provide a function to generate a default config.toml string with active defaults and commented-out fields including the [supervisor] section.
Scenario: Generated config contains commented supervisor examples
- WHEN the default config string is generated
- THEN it SHALL contain commented-out examples for
[supervisor]withenabled,cli,test_command, andagent_approvalfields
Scenario: Generated config contains commented examples
- WHEN the default config string is generated
- THEN it SHALL contain commented-out examples for
default_spec_cli,branch_prefix,[specs],[logging],[broker], and[supervisor]
Requirement: Config round-trip with new fields
A PawConfig with v0.2.0 fields populated SHALL be identical after save and reload.
Scenario: Config with specs and logging round-trips
- GIVEN a config with
default_spec_cli,branch_prefix,specs, andloggingpopulated - WHEN saved and loaded back
- THEN it SHALL be equal to the original
Requirement: Broker configuration section
The system SHALL support an optional [broker] section with the following fields:
enabled: bool— defaults tofalsewhen the field or section is absentport: u16— defaults to9119when absentbind: String— defaults to"127.0.0.1"when absent
The BrokerConfig struct SHALL provide a url(&self) -> String method returning http://<bind>:<port>.
Scenario: Broker section with all fields
- GIVEN a TOML file with
[broker]containingenabled = true,port = 9200,bind = "127.0.0.1" - WHEN the file is loaded
- THEN
broker.enabledSHALL betrue,broker.portSHALL be9200,broker.bindSHALL be"127.0.0.1"
Scenario: Broker section defaults
- GIVEN a TOML file without a
[broker]section - WHEN the file is loaded
- THEN
brokerSHALL haveenabled = false,port = 9119,bind = "127.0.0.1"
Scenario: Partial broker section
- GIVEN a TOML file with
[broker]containing onlyenabled = true - WHEN the file is loaded
- THEN
broker.enabledSHALL betrue,broker.portSHALL be9119,broker.bindSHALL be"127.0.0.1"
Scenario: BrokerConfig url method
- GIVEN
BrokerConfig { enabled: true, port: 9200, bind: "127.0.0.1" } - WHEN
url()is called - THEN the result SHALL be
"http://127.0.0.1:9200"
Scenario: Broker config round-trips through save and load
- GIVEN a config with
[broker]fully populated - WHEN saved and loaded back
- THEN all broker fields SHALL match the original
Requirement: Internal callers SHALL preserve v0.4 behaviour by passing None
All production call sites of load_config inside the git-paw binary SHALL pass None as the user_config_path argument, so production behaviour is byte-identical to the v0.4 single-argument load_config(repo_root) API.
The Option<&Path> argument SHALL exist only to give test code a discoverable way to isolate the user-level config read from whatever exists at the dev machine’s platform-default path. No production code path SHALL pass Some(_).
Scenario: All production call sites pass None
- GIVEN the v0.5.0 source tree
- WHEN every call site of
config::load_configinsidesrc/is inspected - THEN every call SHALL be of the form
config::load_config(&repo_root, None)(modulo whitespace and the exact name of therepo_rootbinding) - AND no production call site SHALL pass
Some(_)
Test: covered by cargo build (compile-time) plus a focused grep-style assertion in src/main.rs::tests or equivalent — see tasks.md task 2.
Scenario: Production behaviour is byte-identical to v0.4
- GIVEN a v0.5.0 binary built from this change
- AND the same
.git-paw/config.tomland platform-default user config that a v0.4 binary would read - WHEN any production command that calls
load_configruns (e.g.git paw start,git paw add-cli,git paw dashboard) - THEN the merged
PawConfigthe command operates on SHALL be equal to the mergedPawConfigv0.4 would have produced
Test: behaviour preserved by construction (every production call passes None); verified by the v0.4 test suite continuing to pass unchanged plus the new load_config_with_none_reads_platform_default_global unit test.
Interactive Selection
Purpose
Interactive selection prompts for choosing branches and AI CLIs. Supports uniform (same CLI for all branches) and per-branch assignment modes, with CLI flags that skip prompts. Logic is separated from UI via the Prompter trait for testability.
Requirements
Requirement: CLI flags skip all prompts when both provided
When both --cli and --branches flags are provided, the system SHALL skip all interactive prompts and map the CLI to all specified branches.
Scenario: Both flags skip all prompts
- GIVEN
--cli alphaand--branches feature/auth,fix/apiflags - WHEN
run_selection()is called - THEN it SHALL return mappings without invoking any prompts
Test: interactive::tests::both_flags_skips_all_prompts_and_maps_cli_to_all_branches
Requirement: CLI flag skips CLI prompt but prompts for branches
When only --cli is provided, the system SHALL prompt for branch selection but skip CLI selection.
Scenario: CLI flag provided, branches prompted
- GIVEN
--cli alphaflag and no branches flag - WHEN
run_selection()is called - THEN branch selection SHALL be prompted and the flag CLI SHALL be used
Test: interactive::tests::cli_flag_skips_cli_prompt_but_prompts_for_branches
Requirement: Branches flag skips branch prompt but prompts for CLI
When only --branches is provided, the system SHALL skip branch selection but prompt for CLI assignment.
Scenario: Branches flag provided, CLI prompted in uniform mode
- GIVEN
--branchesflag and no CLI flag - WHEN user selects uniform mode
- THEN the selected CLI SHALL be mapped to all flagged branches
Test: interactive::tests::branches_flag_skips_branch_prompt_but_prompts_for_cli_uniform
Requirement: Uniform mode maps same CLI to all branches
In uniform mode, the system SHALL assign the selected CLI to every selected branch.
Scenario: Uniform mode selection
- GIVEN user selects uniform mode, picks 2 branches and 1 CLI
- WHEN
run_selection()completes - THEN both branches SHALL be mapped to the same CLI
Test: interactive::tests::uniform_mode_maps_same_cli_to_all_selected_branches
Requirement: Per-branch mode maps different CLIs to each branch
In per-branch mode, the system SHALL prompt for a CLI for each selected branch individually.
Scenario: Per-branch mode selection
- GIVEN user selects per-branch mode with 2 branches
- WHEN different CLIs are chosen for each branch
- THEN each branch SHALL be mapped to its respective CLI
Test: interactive::tests::per_branch_mode_maps_different_cli_to_each_branch
Scenario: Per-branch mode with branches flag
- GIVEN branches provided via flag and per-branch mode selected
- WHEN different CLIs are chosen
- THEN each flagged branch SHALL be mapped to its selected CLI
Test: interactive::tests::per_branch_mode_with_branches_flag
Requirement: Error when no CLIs available
The system SHALL return PawError::NoCLIsFound when the CLI list is empty.
Scenario: Empty CLI list
- GIVEN no CLIs available
- WHEN
run_selection()is called - THEN it SHALL return
Err(PawError::NoCLIsFound)
Test: interactive::tests::no_clis_available_returns_error
Requirement: Error when no branches available
The system SHALL return PawError::BranchError when the branch list is empty.
Scenario: Empty branch list
- GIVEN no branches available
- WHEN
run_selection()is called - THEN it SHALL return
Err(PawError::BranchError)
Test: interactive::tests::no_branches_available_returns_error
Requirement: User cancellation propagates as PawError::UserCancelled
The system SHALL propagate cancellation (Ctrl+C or empty selection) as PawError::UserCancelled.
Scenario: User cancels branch selection
- GIVEN user presses Ctrl+C during branch selection
- WHEN
run_selection()is called - THEN it SHALL return
Err(PawError::UserCancelled)
Test: interactive::tests::user_cancels_branch_selection_returns_cancelled
Scenario: User selects no branches
- GIVEN user confirms with zero branches selected
- WHEN
run_selection()is called - THEN it SHALL return
Err(PawError::UserCancelled)
Test: interactive::tests::user_selects_no_branches_returns_cancelled
Scenario: User cancels CLI selection
- GIVEN user presses Ctrl+C during CLI selection
- WHEN
run_selection()is called - THEN it SHALL return
Err(PawError::UserCancelled)
Test: interactive::tests::user_cancels_cli_selection_returns_cancelled
Requirement: Subset branch selection
The system SHALL support selecting a subset of available branches.
Scenario: Selecting one of two branches
- GIVEN 2 available branches
- WHEN user selects only the second
- THEN only that branch SHALL appear in the result
Test: interactive::tests::selecting_subset_of_branches_works
Requirement: CliMode display format
The CliMode enum SHALL display as human-readable descriptions.
Scenario: CliMode display strings
- GIVEN
CliMode::UniformandCliMode::PerBranch - WHEN formatted with
Display - THEN they SHALL render as
"Same CLI for all branches"and"Different CLI per branch"
Test: interactive::tests::cli_mode_display
Requirement: CliInfo display format
CliInfo SHALL display as the binary name when it matches the display name, or as "DisplayName (binary)" when they differ.
Scenario: Same display and binary name
- GIVEN a
CliInfowheredisplay_nameequalsbinary_name - WHEN formatted with
Display - THEN it SHALL render as just the binary name
Test: interactive::tests::cli_info_display_same_names
Scenario: Different display and binary name
- GIVEN a
CliInfowheredisplay_namediffers frombinary_name - WHEN formatted with
Display - THEN it SHALL render as
"DisplayName (binary_name)"
Test: interactive::tests::cli_info_display_different_names
Requirement: CLI picker with optional pre-selection
The select_cli method on the Prompter trait SHALL accept an optional default CLI name for pre-selection in the interactive picker.
Scenario: Picker with default pre-selected
- WHEN
select_cli()is called withdefault = Some("claude")and"claude"is in the CLI list - THEN the picker SHALL display with
"claude"highlighted as the default selection
Scenario: Picker without default
- WHEN
select_cli()is called withdefault = None - THEN the picker SHALL display with the first item selected (no pre-selection)
Scenario: Default CLI not in available list
- WHEN
select_cli()is called withdefault = Some("nonexistent")and that CLI is not available - THEN the picker SHALL display with no pre-selection (graceful fallback)
Requirement: Spec multi-select picker
The Prompter trait SHALL include a select_specs(&self, specs: &[SpecEntry]) -> Result<Vec<SpecEntry>, PawError> method that presents a multi-select picker for spec entries and returns the user’s chosen subset.
The default TerminalPrompter implementation SHALL display one row per logical spec unit (a feature in Spec Kit terms; a change in OpenSpec; a file in plain Markdown), grouping multiple SpecEntry values that decompose from the same Spec Kit feature into a single row. Selecting a row SHALL cause every SpecEntry belonging to that row’s logical unit to be returned.
Each row’s display label SHALL include the unit identifier and, for Spec Kit features that decompose into multiple worktrees, a worktree-count hint summarising the breakdown (e.g. "003-user-list — 3 worktrees: 2 [P] + 1 phase/"). For OpenSpec changes and Markdown specs, the label SHALL be the unit identifier alone (one entry → one worktree, no hint needed).
The picker SHALL behave the same way as select_branches for cancellation:
- User pressing Ctrl+C →
PawError::UserCancelled. - User confirming with zero rows selected →
PawError::UserCancelled.
Scenario: select_specs returns the chosen subset
- GIVEN 3 OpenSpec entries
add-auth,fix-session,add-logging - WHEN the user toggles
add-authandadd-loggingand presses enter - THEN
select_specsreturns aVeccontaining those two entries
Scenario: select_specs groups Spec Kit entries by feature
- GIVEN 4 SpecEntry values from a Spec Kit project: two
[P]entries (003-user-list-T009,003-user-list-T010), one consolidated entry (003-user-list-phase-2), and one entry from a different feature (004-error-handling-phase-1) - WHEN the picker renders
- THEN it displays exactly 2 rows — one per logical feature
- AND the row for feature
003-user-listshows a worktree-count hint summarising the 3 underlying entries (2 [P] + 1 phase/)
Scenario: Selecting a Spec Kit feature row pulls in all its entries
- GIVEN a picker rendering one row for feature
003-user-list(3 underlying SpecEntry values) - WHEN the user selects only that row and confirms
- THEN
select_specsreturns all 3 underlying SpecEntry values
Scenario: User cancels spec picker via Ctrl+C
- GIVEN the spec picker is open
- WHEN the user presses Ctrl+C
- THEN
select_specsreturnsErr(PawError::UserCancelled)
Scenario: User confirms with zero rows selected
- GIVEN the spec picker is open with N rows displayed
- WHEN the user confirms without toggling any row
- THEN
select_specsreturnsErr(PawError::UserCancelled)
Requirement: Spec picker requires an interactive terminal
When the start command would invoke select_specs (i.e. the user passed --specs with no values), the system SHALL detect whether stdin is connected to a terminal before invoking the picker. If stdin is NOT a terminal (CI, scripted invocation, redirected input), the system SHALL exit with an actionable error pointing at the explicit forms (--specs NAME[,NAME...] to narrow, --from-all-specs to launch every discovered spec).
The system SHALL NOT block waiting for picker input on a non-interactive stdin.
Scenario: Bare –specs in non-TTY environment exits with guidance
- GIVEN the user runs
git paw start --specswith stdin redirected (or no controlling terminal) - WHEN the start command attempts to open the picker
- THEN the command SHALL exit with a non-zero status before any picker UI is drawn
- AND the error message SHALL point the user at
--specs NAME[,NAME...]and--from-all-specs
Scenario: Bare –specs on TTY proceeds to picker
- GIVEN the user runs
git paw start --specsfrom an interactive terminal - WHEN the start command runs
- THEN the picker SHALL open
- AND no TTY-required error SHALL be emitted
Requirement: Spec name resolution for narrow mode
When --specs is passed with one or more values (narrow mode), the system SHALL resolve each value against the discovered SpecEntry set returned by scan_specs(). Resolution SHALL apply the following matching strategies in order, taking the first that succeeds:
- Exact match on
SpecEntry.id(case-sensitive). For Spec Kit, this matches a specific decomposed entry like003-user-list-T009. For OpenSpec / Markdown, it matches the change name or filename stem. - Spec Kit feature match on the feature directory prefix of the
SpecEntry.id(e.g.003-user-listmatches all entries belonging to that feature). When the value matches a Spec Kit feature unambiguously, ALL entries belonging to that feature SHALL be selected. - Spec Kit numeric prefix match (e.g.
003) matching a Spec Kit feature directory name’s leading numeric portion. The match SHALL succeed only when exactly one feature directory begins with the given prefix followed by a non-digit boundary; ambiguous prefixes SHALL be rejected (see below).
Resolution SHALL fail (and the start command SHALL exit before any worktrees are created) when:
- A value matches no
SpecEntryand no feature. - A Spec Kit numeric prefix matches more than one feature directory (ambiguous).
The resulting error SHALL list the unresolved or ambiguous names AND the discovered candidate names so the user can correct quickly.
Scenario: Exact match resolves to a single SpecEntry
- GIVEN a discovered set including OpenSpec change
add-auth - WHEN the user passes
--specs add-auth - THEN the resolved set SHALL contain exactly that one
SpecEntry
Scenario: Spec Kit feature name resolves to all decomposed entries
- GIVEN a Spec Kit feature
003-user-listdecomposing into 3 SpecEntry values (2[P]+ 1 consolidated) - WHEN the user passes
--specs 003-user-list - THEN the resolved set SHALL contain all 3 entries belonging to that feature
Scenario: Spec Kit numeric prefix resolves unambiguously
- GIVEN a Spec Kit project with a single feature directory beginning with
003-(e.g.003-user-list) - WHEN the user passes
--specs 003 - THEN the resolved set SHALL contain all entries belonging to that feature
Scenario: Ambiguous numeric prefix is rejected
- GIVEN a Spec Kit project containing both
003-user-listand003a-experiment - WHEN the user passes
--specs 003 - THEN the start command SHALL exit with an error
- AND the error message SHALL list both candidate feature names
Scenario: Unknown spec name is rejected with candidate list
- GIVEN a discovered set containing
add-auth,fix-session - WHEN the user passes
--specs no-such-spec - THEN the start command SHALL exit with an error
- AND the error message SHALL include
no-such-spec - AND the error message SHALL list
add-authandfix-sessionas candidates
Scenario: Multiple values are resolved independently
- GIVEN a discovered set including
add-auth,fix-session,add-logging - WHEN the user passes
--specs add-auth,add-logging - THEN the resolved set SHALL contain entries for
add-authandadd-logging - AND the resolved set SHALL NOT contain the entry for
fix-session
Scenario: Partial-failure batches do not partially start
- GIVEN a user passes
--specs add-auth,no-such-spec - WHEN resolution runs
- THEN the start command SHALL exit with the unknown-name error
- AND no worktrees SHALL be created
- AND the error message SHALL include
no-such-spec(the unresolved name)
Error Handling
Purpose
Define the central error type PawError used across all git-paw modules. Every variant carries an actionable, user-facing message and maps to a process exit code.
Requirements
Requirement: Actionable error messages for each variant
Each PawError variant SHALL produce a user-facing message that explains the problem and suggests a remedy where appropriate.
Scenario: NotAGitRepo is actionable
- GIVEN
PawError::NotAGitRepo - WHEN formatted with
Display - THEN the message SHALL mention “git repository” and name the tool
Test: error::tests::test_not_a_git_repo_is_actionable
Scenario: TmuxNotInstalled includes install instructions
- GIVEN
PawError::TmuxNotInstalled - WHEN formatted with
Display - THEN the message SHALL include both
brew installandapt installhints
Test: error::tests::test_tmux_not_installed_includes_install_instructions
Scenario: NoCLIsFound suggests add-cli
- GIVEN
PawError::NoCLIsFound - WHEN formatted with
Display - THEN the message SHALL suggest the
add-clicommand
Test: error::tests::test_no_clis_found_suggests_add_cli
Scenario: WorktreeError includes detail
- GIVEN
PawError::WorktreeError("failed to create") - WHEN formatted with
Display - THEN the message SHALL include the inner detail string
Test: error::tests::test_worktree_error_includes_detail
Scenario: SessionError includes detail
- GIVEN
PawError::SessionError("file corrupt") - WHEN formatted with
Display - THEN the message SHALL include the inner detail string
Test: error::tests::test_session_error_includes_detail
Scenario: ConfigError includes detail
- GIVEN
PawError::ConfigError("invalid toml") - WHEN formatted with
Display - THEN the message SHALL include the inner detail string
Test: error::tests::test_config_error_includes_detail
Scenario: BranchError includes detail
- GIVEN
PawError::BranchError("not found") - WHEN formatted with
Display - THEN the message SHALL include the inner detail string
Test: error::tests::test_branch_error_includes_detail
Scenario: UserCancelled has a message
- GIVEN
PawError::UserCancelled - WHEN formatted with
Display - THEN the message SHALL not be empty
Test: error::tests::test_user_cancelled_is_not_empty
Scenario: TmuxError includes detail
- GIVEN
PawError::TmuxError("session failed") - WHEN formatted with
Display - THEN the message SHALL include the inner detail string
Test: error::tests::test_tmux_error_includes_detail
Scenario: CliNotFound includes CLI name
- GIVEN
PawError::CliNotFound("my-agent") - WHEN formatted with
Display - THEN the message SHALL include the missing CLI name
Test: error::tests::test_cli_not_found_includes_cli_name
Requirement: Exit codes distinguish cancellation from errors
UserCancelled SHALL exit with code 2; all other errors SHALL exit with code 1.
Scenario: UserCancelled exit code
- GIVEN
PawError::UserCancelled - WHEN
exit_code()is called - THEN it SHALL return
2
Test: error::tests::test_user_cancelled_exit_code
Scenario: General errors exit code
- GIVEN any non-cancellation error variant
- WHEN
exit_code()is called - THEN it SHALL return
1
Test: error::tests::test_general_errors_exit_code
Requirement: Exit method prints to stderr and exits with correct code
PawError::exit() SHALL print the error message to stderr and terminate with the appropriate exit code.
Scenario: NotAGitRepo exits with code 1
- GIVEN the binary is run outside a git repository
- WHEN the error propagates to
exit() - THEN the process SHALL exit with code 1 and stderr SHALL contain the error message
Test: e2e_tests::error_exit_code_is_1_for_not_a_git_repo
Scenario: ConfigError exits with code 1
- GIVEN a nonexistent preset is requested
- WHEN the error propagates to
exit() - THEN the process SHALL exit with code 1 and stderr SHALL mention “not found”
Test: e2e_tests::error_exit_code_is_1_for_preset_not_found
Requirement: Debug representation is derivable
All PawError variants SHALL support Debug formatting.
Scenario: Debug format includes variant name
- GIVEN
PawError::NotAGitRepo - WHEN formatted with
Debug - THEN the output SHALL contain
"NotAGitRepo"
Test: error::tests::test_debug_derived
Requirement: SkillError variants with actionable messages
The system SHALL define a SkillError type with variants for skill loading failures. Each variant SHALL produce a user-facing message that explains the problem and suggests a remedy. SkillError SHALL be wrappable inside PawError as a variant.
The following variants SHALL exist:
UnknownSkill { name: String }— no embedded or user override found for the requested skill nameUserOverrideRead { path: PathBuf, source: std::io::Error }— a user override file exists but cannot be read
Scenario: UnknownSkill is actionable
- GIVEN
SkillError::UnknownSkill { name: "nonexistent" } - WHEN formatted with
Display - THEN the message SHALL mention the skill name
"nonexistent"and indicate no embedded default exists
Scenario: UserOverrideRead is actionable
- GIVEN
SkillError::UserOverrideRead { path: "/home/user/.config/git-paw/agent-skills/coordination.md", .. } - WHEN formatted with
Display - THEN the message SHALL include the file path and suggest checking permissions
Scenario: SkillError exit code
- GIVEN any
SkillErrorvariant wrapped inPawError - WHEN
exit_code()is called - THEN it SHALL return
1
Requirement: BrokerError variants with actionable messages
The system SHALL define a BrokerError type with variants for broker-specific failures. Each variant SHALL produce a user-facing message that explains the problem and suggests a remedy. BrokerError SHALL be wrappable inside PawError as a variant.
The following variants SHALL exist:
PortInUse { port: u16, source: std::io::Error }— the configured port is already occupied;sourcecarries the underlying bind/probeio::Errorso callers can chain or log the original causeProbeTimeout { port: u16 }— the stale-broker probe timed outBindFailed(std::io::Error)— socket bind failed for a reason other than port-in-useRuntimeFailed(std::io::Error)— tokio runtime construction failed
PortInUse.source SHALL be marked #[source] (or equivalent thiserror attribute) so it participates in std::error::Error::source() chains. The Display output SHALL NOT include the source by default — it is reserved for explicit chaining via {:?} or programmatic .source() access — to avoid duplicated diagnostics in user-facing CLI output.
Scenario: PortInUse is actionable
- GIVEN
BrokerError::PortInUse { port: 9119, source: io::Error::from(io::ErrorKind::AddrInUse) } - WHEN formatted with
Display - THEN the message SHALL mention port
9119and suggest changing[broker] portin config - AND the message SHALL NOT contain the underlying
io::ErrorDisplay text
Scenario: PortInUse exposes underlying cause
- GIVEN a
PortInUsevalue with anAddrInUsesource - WHEN
std::error::Error::source()is called on it - THEN the result SHALL be
Some(&dyn Error)referencing the wrappedio::Error
Scenario: ProbeTimeout is actionable
- GIVEN
BrokerError::ProbeTimeout { port: 9119 } - WHEN formatted with
Display - THEN the message SHALL mention the port and suggest checking for stuck processes
Scenario: BrokerError exit code
- GIVEN any
BrokerErrorvariant wrapped inPawError - WHEN
exit_code()is called - THEN it SHALL return
1
Contributing
Contributions to git-paw are welcome! This guide covers the development workflow.
Prerequisites
- Rust (see
rust-toolchain.tomlfor the exact version) - tmux
- just (task runner)
Getting Started
git clone https://github.com/bearicorn/git-paw.git
cd git-paw
just check
Development Commands
git-paw uses just as a task runner. Key recipes:
| Command | Description |
|---|---|
just check | Run fmt + clippy + tests |
just test | Run all tests |
just test-all | Run all tests including tmux-dependent ones |
just lint | Run cargo fmt --check and cargo clippy |
just coverage | Generate HTML coverage report |
just docs | Build and open mdBook documentation |
just api-docs | Build and open Rustdoc API docs |
just build | Build release binary |
just install | Install from local source |
just clean | Clean build artifacts |
Building
# Debug build
cargo build
# Release build
cargo build --release
# Install locally
cargo install --path .
Testing
# Unit tests
cargo test
# Include tmux-dependent tests (requires tmux installed)
cargo test -- --include-ignored
# Coverage report
cargo llvm-cov --html
# Open: target/llvm-cov/html/index.html
Tests are organized as:
- Unit tests —
#[cfg(test)]modules within each source file - Integration tests —
tests/directory (CLI binary tests, worktree lifecycle, session round-trips) - Tmux-dependent tests — run normally (tmux is a hard dependency)
Code Style
- Formatting:
cargo fmt(config inrustfmt.toml) - Linting:
cargo clippy -- -D warningswith pedantic lints enabled - No panics: No
unwrap()orexpect()in non-testsrc/code - Documentation:
//!module-level doc comments,///on all public items
Commit Format
This project uses Conventional Commits:
<type>(<scope>): <description>
[optional body]
[optional footer(s)]
Types: feat, fix, docs, style, refactor, test, ci, chore
Scopes: cli, detect, git, tmux, session, config, interactive, error
Examples:
feat(tmux): add mouse mode support
fix(session): handle missing state file gracefully
docs: update installation instructions
test(git): add worktree creation edge cases
Branch Naming
feat/<description> # New features
fix/<description> # Bug fixes
docs/<description> # Documentation
test/<description> # Test additions
ci/<description> # CI/CD changes
Pull Request Process
- Fork the repository
- Create a feature branch from
main - Make your changes
- Ensure
just checkpasses (fmt, clippy, tests) - Write or update tests as needed
- Open a PR against
main
PRs should:
- Have a clear title and description
- Pass all CI checks
- Include tests for new functionality
- Follow the commit format above
Architecture
See the Architecture chapter for an overview of the module structure and design decisions.
Changelog
All notable changes to this project will be documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
[0.5.0] - 2026-05-25
Features
- (cli,main,interactive) SpecMode dispatcher, pause subcommand, –no-supervisor, –specs picker, –from-specs –supervisor routing
- (init,skills) Bundle sweep.sh helper installed by git paw init, idempotent merge against existing configs
- (supervisor) Supervisor-as-pane, dev-allowlist seeding, default-config fallback, auto-approve, stall detection, layout helper
- (tmux,git,agents,session,dirs) Pause primitives, idempotent worktrees, AGENTS.md boot-block lifecycle, worktree base rebase
- (dashboard) Supervisor-as-pane row, prompt-inbox removal, phase-aware status, layout collapse
- (config) [governance], [common_dev_allowlist], supervisor gate-command keys, user_config_path override
- (skills) Supervisor + coordination skill v0.5.0 doctrine
- (specs) Spec Kit backend, backend-tagged SpecEntry, per-backend boot-prompt dispatch
- (broker) Agent.intent, learnings aggregator, conflict detector, status payload metadata, agent_id validation
Bug Fixes
- (docs) List all crates in third-party licenses page
Documentation
- Align README, mdBook, AGENTS.md, and user-guide with v0.5.0 surface
- (specs) V0.5.0 OpenSpec changes, archive plan, and main-spec alignment
Testing
- Behavioral coverage for v0.5.0 surfaces + tmux/config-integration isolation harness
[0.4.0] - 2026-04-17
Features
- (supervisor) Auto-approve patterns
- (supervisor) Mode with merge loop, session summary, recovery, question forwarding
- (cli,config,init,git) Supervisor + force flags, supervisor config schema, branch handling
- (dashboard) Committed counter, prompt-inbox interactivity, message log panel, layout
- (broker) Hook injection, watcher, sticky terminal status, real uptime, verified/feedback messages
- (skills) Standardize agent-skill resolution to agentskills.io layout
- (detect) Expand auto-detection to cover 10 additional AI CLI tools
Documentation
- Align README, mdBook, and AGENTS.md with v0.4.0 surface
- (specs) V0.4.0 OpenSpec changes, archive plan, and main-spec alignment
Testing
- Behavioral integration and unit tests for v0.4.0
[0.3.0] - 2026-04-10
Features
- (broker) Wire broker into session lifecycle and update docs (#43)
- Add dashboard, skills, and agent coordination
- (broker) Add HTTP broker with message types, delivery, and config
CI/CD
- (deps) Switch dependabot to monthly and ignore cargo-dist actions
- (deps) Bump actions/deploy-pages from 4 to 5 (#40) (#40)
Build
- (deps) Bump toml from 0.9.12+spec-1.1.0 to 1.1.2+spec-1.1.0 (#41) (#41)
[0.2.0] - 2026-04-08
Features
- Add v0.2.0 spec-driven launch, init, logging, replay, and AGENTS.md integration (#42)
[0.1.0] - 2026-03-25
Features
- Add CLI tool for parallel AI coding sessions across git worktrees [0.5.0]: https://github.com/bearicorn/git-paw/compare/v0.4.0…v0.5.0 [0.4.0]: https://github.com/bearicorn/git-paw/compare/v0.3.0…v0.4.0 [0.3.0]: https://github.com/bearicorn/git-paw/compare/v0.2.0…v0.3.0 [0.2.0]: https://github.com/bearicorn/git-paw/compare/v0.1.0…v0.2.0
FAQ
General
What does “paw” stand for?
Parallel AI Worktrees.
Does git-paw work on Windows?
Only through WSL (Windows Subsystem for Linux). git-paw requires tmux, which is not natively available on Windows. See the Installation chapter for WSL setup instructions.
Do I need tmux experience to use git-paw?
No. git-paw creates and manages tmux sessions for you. Mouse mode is enabled by default, so you can click to switch panes and drag to resize. The only tmux shortcut you might need is Ctrl-b d to detach.
Can I use git-paw with AI CLIs not in the supported list?
Yes! Use git paw add-cli to register any CLI binary. See Custom CLIs.
Sessions
What happens if I close my terminal?
The tmux session keeps running in the background. Run git paw again to reattach.
What happens if tmux crashes or my machine reboots?
git-paw saves session state to disk. The next time you run git paw, it detects the saved state and automatically recovers: reuses existing worktrees, recreates the tmux session, and relaunches your AI CLIs.
Can I run multiple git-paw sessions?
One session per repository. To work with multiple repos, open separate terminals and run git paw in each repo directory.
How do I switch between branches in a session?
Click the pane you want (mouse mode is on by default), or use Ctrl-b followed by arrow keys to navigate between panes. Each pane is labeled with its branch and CLI in the border title.
Worktrees
What are git worktrees?
Git worktrees let you check out multiple branches simultaneously in separate directories. Each worktree is a fully functional working copy of the repository sharing the same .git data. Changes in one worktree don’t affect others.
Where does git-paw create worktrees?
As siblings of your main repo directory. For a project at ~/projects/my-app with branch feat/auth:
~/projects/my-app/ ← your repo
~/projects/my-app-feat-auth/ ← worktree created by git-paw
Does stopping a session delete my worktrees?
No. git paw stop kills the tmux session but keeps worktrees and any uncommitted work intact. Only git paw purge removes worktrees.
Can I manually work in a git-paw worktree?
Yes. Worktrees are regular git working directories. You can cd into them, edit files, commit, push — anything you’d do in a normal repo. When you restart the session, git-paw reuses the existing worktrees.
Configuration
Where are config files stored?
| Level | Path |
|---|---|
| Global | ~/.config/git-paw/config.toml |
| Per-repo | .git-paw/config.toml (in repo root) |
Both are optional. See Configuration.
How do I set a default CLI?
Add to your global or repo config:
default_cli = "my-cli"
How do I disable mouse mode?
mouse = false
This only affects git-paw’s tmux sessions, not your other tmux usage.
Troubleshooting
“Not a git repository”
Run git-paw from inside a git repository. It needs to be anywhere within a repo’s working tree.
“tmux is required but not installed”
Install tmux:
- macOS:
brew install tmux - Ubuntu/Debian:
sudo apt install tmux - Fedora:
sudo dnf install tmux
“No AI CLIs found on PATH”
Install at least one AI coding CLI (see Supported AI CLIs), or register a custom one:
git paw add-cli my-tool /path/to/my-tool
“no space for new pane” in tmux
This can happen with many branches on a small terminal. Make your terminal window larger before launching, or select fewer branches. git-paw applies tiled layout progressively to minimize this issue.
Session state seems stale
git-paw checks tmux liveness to determine effective status. If something seems off, try:
git paw purge --force
git paw start
Third-Party Licenses
git-paw includes the following third-party software.
Summary
- 190 crates under MIT License (
MIT) - 5 crates under Apache License 2.0 (
Apache-2.0) - 1 crates under BSD 3-Clause “New” or “Revised” License (
BSD-3-Clause) - 1 crates under Unicode License v3 (
Unicode-3.0) - 1 crates under zlib License (
Zlib)
License notices
Each section below covers crates that share an identical license-text variant. License-IDs with multiple copyright holders therefore appear more than once, with the relevant crates and copyright notice grouped together.
Apache License 2.0 (Apache-2.0)
Used by:
- sdd 3.0.10
License text
Apache License
Version 2.0, April 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
Copyright 2024-present Changgyoo Park
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
Apache License 2.0 (Apache-2.0)
Used by:
- normalize-line-endings 0.3.0
License text
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "{}"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright {yyyy} {name of copyright owner}
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
Apache License 2.0 (Apache-2.0)
Used by:
- scc 2.4.0
License text
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
Copyright 2020-2024 Changgyoo Park
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
Apache License 2.0 (Apache-2.0)
Used by:
- ryu 1.0.23
- sync_wrapper 1.0.2
License text
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files.
"Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions:
(a) You must give any other recipients of the Work or Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License.
You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
BSD 3-Clause “New” or “Revised” License (BSD-3-Clause)
Used by:
- matchit 0.8.4
License text
BSD 3-Clause License
Copyright (c) 2013, Julien Schmidt
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
MIT License (MIT)
Used by:
- instability 0.3.12
License text
# MIT License
Copyright (c) 2020 Stephen M. Coakley
Copyright (c) The Ratatui Developers
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
MIT License (MIT)
Used by:
- core-foundation-sys 0.8.7
License text
Copyright (c) 2012-2013 Mozilla Foundation
Permission is hereby granted, free of charge, to any
person obtaining a copy of this software and associated
documentation files (the "Software"), to deal in the
Software without restriction, including without
limitation the rights to use, copy, modify, merge,
publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software
is furnished to do so, subject to the following
conditions:
The above copyright notice and this permission notice
shall be included in all copies or substantial portions
of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
MIT License (MIT)
Used by:
- form_urlencoded 1.2.2
License text
Copyright (c) 2013-2016 The rust-url developers
Permission is hereby granted, free of charge, to any
person obtaining a copy of this software and associated
documentation files (the "Software"), to deal in the
Software without restriction, including without
limitation the rights to use, copy, modify, merge,
publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software
is furnished to do so, subject to the following
conditions:
The above copyright notice and this permission notice
shall be included in all copies or substantial portions
of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
MIT License (MIT)
Used by:
- percent-encoding 2.3.2
License text
Copyright (c) 2013-2025 The rust-url developers
Permission is hereby granted, free of charge, to any
person obtaining a copy of this software and associated
documentation files (the "Software"), to deal in the
Software without restriction, including without
limitation the rights to use, copy, modify, merge,
publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software
is furnished to do so, subject to the following
conditions:
The above copyright notice and this permission notice
shall be included in all copies or substantial portions
of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
MIT License (MIT)
Used by:
- cc 1.2.61
- cfg-if 1.0.4
- find-msvc-tools 0.1.9
- js-sys 0.3.97
- socket2 0.6.3
- wait-timeout 0.2.1
- wasm-bindgen-macro-support 0.2.120
- wasm-bindgen-macro 0.2.120
- wasm-bindgen-shared 0.2.120
- wasm-bindgen 0.2.120
License text
Copyright (c) 2014 Alex Crichton
Permission is hereby granted, free of charge, to any
person obtaining a copy of this software and associated
documentation files (the "Software"), to deal in the
Software without restriction, including without
limitation the rights to use, copy, modify, merge,
publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software
is furnished to do so, subject to the following
conditions:
The above copyright notice and this permission notice
shall be included in all copies or substantial portions
of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
MIT License (MIT)
Used by:
- mio 1.2.0
License text
Copyright (c) 2014 Carl Lerche and other MIO contributors
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
MIT License (MIT)
Used by:
- errno 0.3.14
License text
Copyright (c) 2014 Chris Wong
Permission is hereby granted, free of charge, to any
person obtaining a copy of this software and associated
documentation files (the "Software"), to deal in the
Software without restriction, including without
limitation the rights to use, copy, modify, merge,
publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software
is furnished to do so, subject to the following
conditions:
The above copyright notice and this permission notice
shall be included in all copies or substantial portions
of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
MIT License (MIT)
Used by:
- mime 0.3.17
License text
Copyright (c) 2014 Sean McArthur
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
MIT License (MIT)
Used by:
- bitflags 2.11.0
- log 0.4.29
- num-traits 0.2.19
- regex-automata 0.4.14
- regex-syntax 0.8.10
- regex 1.12.3
License text
Copyright (c) 2014 The Rust Project Developers
Permission is hereby granted, free of charge, to any
person obtaining a copy of this software and associated
documentation files (the "Software"), to deal in the
Software without restriction, including without
limitation the rights to use, copy, modify, merge,
publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software
is furnished to do so, subject to the following
conditions:
The above copyright notice and this permission notice
shall be included in all copies or substantial portions
of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
MIT License (MIT)
Used by:
- float-cmp 0.10.0
License text
Copyright (c) 2014-2020 Optimal Computing (NZ) Ltd
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.
MIT License (MIT)
Used by:
- hyper 1.9.0
License text
Copyright (c) 2014-2026 Sean McArthur
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
MIT License (MIT)
Used by:
- either 1.15.0
- itertools 0.13.0
License text
Copyright (c) 2015
Permission is hereby granted, free of charge, to any
person obtaining a copy of this software and associated
documentation files (the "Software"), to deal in the
Software without restriction, including without
limitation the rights to use, copy, modify, merge,
publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software
is furnished to do so, subject to the following
conditions:
The above copyright notice and this permission notice
shall be included in all copies or substantial portions
of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
MIT License (MIT)
Used by:
- tempfile 3.27.0
License text
Copyright (c) 2015 Steven Allen
Permission is hereby granted, free of charge, to any
person obtaining a copy of this software and associated
documentation files (the "Software"), to deal in the
Software without restriction, including without
limitation the rights to use, copy, modify, merge,
publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software
is furnished to do so, subject to the following
conditions:
The above copyright notice and this permission notice
shall be included in all copies or substantial portions
of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
MIT License (MIT)
Used by:
- heck 0.5.0
- unicode-segmentation 1.13.2
- unicode-width 0.1.14
- unicode-width 0.2.0
License text
Copyright (c) 2015 The Rust Project Developers
Permission is hereby granted, free of charge, to any
person obtaining a copy of this software and associated
documentation files (the "Software"), to deal in the
Software without restriction, including without
limitation the rights to use, copy, modify, merge,
publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software
is furnished to do so, subject to the following
conditions:
The above copyright notice and this permission notice
shall be included in all copies or substantial portions
of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
MIT License (MIT)
Used by:
- which 8.0.2
License text
Copyright (c) 2015 fangyuanziti
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
MIT License (MIT)
Used by:
- winapi 0.3.9
License text
Copyright (c) 2015-2018 The winapi-rs Developers
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
MIT License (MIT)
Used by:
- httparse 1.10.1
License text
Copyright (c) 2015-2025 Sean McArthur
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
MIT License (MIT)
Used by:
- futures-channel 0.3.32
- futures-core 0.3.32
- futures-executor 0.3.32
- futures-task 0.3.32
- futures-util 0.3.32
License text
Copyright (c) 2016 Alex Crichton
Copyright (c) 2017 The Tokio Authors
Permission is hereby granted, free of charge, to any
person obtaining a copy of this software and associated
documentation files (the "Software"), to deal in the
Software without restriction, including without
limitation the rights to use, copy, modify, merge,
publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software
is furnished to do so, subject to the following
conditions:
The above copyright notice and this permission notice
shall be included in all copies or substantial portions
of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
MIT License (MIT)
Used by:
- hashbrown 0.15.5
- hashbrown 0.17.0
License text
Copyright (c) 2016 Amanieu d'Antras
Permission is hereby granted, free of charge, to any
person obtaining a copy of this software and associated
documentation files (the "Software"), to deal in the
Software without restriction, including without
limitation the rights to use, copy, modify, merge,
publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software
is furnished to do so, subject to the following
conditions:
The above copyright notice and this permission notice
shall be included in all copies or substantial portions
of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
MIT License (MIT)
Used by:
- serde_urlencoded 0.7.1
License text
Copyright (c) 2016 Anthony Ramine
Permission is hereby granted, free of charge, to any
person obtaining a copy of this software and associated
documentation files (the "Software"), to deal in the
Software without restriction, including without
limitation the rights to use, copy, modify, merge,
publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software
is furnished to do so, subject to the following
conditions:
The above copyright notice and this permission notice
shall be included in all copies or substantial portions
of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
MIT License (MIT)
Used by:
- utf8parse 0.2.2
License text
Copyright (c) 2016 Joe Wilm
Permission is hereby granted, free of charge, to any
person obtaining a copy of this software and associated
documentation files (the "Software"), to deal in the
Software without restriction, including without
limitation the rights to use, copy, modify, merge,
publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software
is furnished to do so, subject to the following
conditions:
The above copyright notice and this permission notice
shall be included in all copies or substantial portions
of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
MIT License (MIT)
Used by:
- httpdate 1.0.3
License text
Copyright (c) 2016 Pyfisch
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
MIT License (MIT)
Used by:
- lock_api 0.4.14
- parking_lot 0.12.5
- parking_lot_core 0.9.12
License text
Copyright (c) 2016 The Rust Project Developers
Permission is hereby granted, free of charge, to any
person obtaining a copy of this software and associated
documentation files (the "Software"), to deal in the
Software without restriction, including without
limitation the rights to use, copy, modify, merge,
publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software
is furnished to do so, subject to the following
conditions:
The above copyright notice and this permission notice
shall be included in all copies or substantial portions
of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
MIT License (MIT)
Used by:
- shell-words 1.1.1
License text
Copyright (c) 2016 Tomasz Miąsko
Permission is hereby granted, free of charge, to any
person obtaining a copy of this software and associated
documentation files (the "Software"), to deal in the
Software without restriction, including without
limitation the rights to use, copy, modify, merge,
publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software
is furnished to do so, subject to the following
conditions:
The above copyright notice and this permission notice
shall be included in all copies or substantial portions
of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
MIT License (MIT)
Used by:
- indexmap 2.14.0
License text
Copyright (c) 2016--2017
Permission is hereby granted, free of charge, to any
person obtaining a copy of this software and associated
documentation files (the "Software"), to deal in the
Software without restriction, including without
limitation the rights to use, copy, modify, merge,
publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software
is furnished to do so, subject to the following
conditions:
The above copyright notice and this permission notice
shall be included in all copies or substantial portions
of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
MIT License (MIT)
Used by:
- equivalent 1.0.2
License text
Copyright (c) 2016--2023
Permission is hereby granted, free of charge, to any
person obtaining a copy of this software and associated
documentation files (the "Software"), to deal in the
Software without restriction, including without
limitation the rights to use, copy, modify, merge,
publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software
is furnished to do so, subject to the following
conditions:
The above copyright notice and this permission notice
shall be included in all copies or substantial portions
of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
MIT License (MIT)
Used by:
- scopeguard 1.2.0
License text
Copyright (c) 2016-2019 Ulrik Sverdrup "bluss" and scopeguard developers
Permission is hereby granted, free of charge, to any
person obtaining a copy of this software and associated
documentation files (the "Software"), to deal in the
Software without restriction, including without
limitation the rights to use, copy, modify, merge,
publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software
is furnished to do so, subject to the following
conditions:
The above copyright notice and this permission notice
shall be included in all copies or substantial portions
of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
MIT License (MIT)
Used by:
- redox_syscall 0.5.18
License text
Copyright (c) 2017 Redox OS Developers
MIT License
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
MIT License (MIT)
Used by:
- http 1.4.0
License text
Copyright (c) 2017 http-rs authors
Permission is hereby granted, free of charge, to any
person obtaining a copy of this software and associated
documentation files (the "Software"), to deal in the
Software without restriction, including without
limitation the rights to use, copy, modify, merge,
publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software
is furnished to do so, subject to the following
conditions:
The above copyright notice and this permission notice
shall be included in all copies or substantial portions
of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
MIT License (MIT)
Used by:
- signal-hook-mio 0.2.5
- signal-hook-registry 1.4.8
- signal-hook 0.3.18
License text
Copyright (c) 2017 tokio-jsonrpc developers
Permission is hereby granted, free of charge, to any
person obtaining a copy of this software and associated
documentation files (the "Software"), to deal in the
Software without restriction, including without
limitation the rights to use, copy, modify, merge,
publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software
is furnished to do so, subject to the following
conditions:
The above copyright notice and this permission notice
shall be included in all copies or substantial portions
of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
MIT License (MIT)
Used by:
- bytes 1.11.1
License text
Copyright (c) 2018 Carl Lerche
Permission is hereby granted, free of charge, to any
person obtaining a copy of this software and associated
documentation files (the "Software"), to deal in the
Software without restriction, including without
limitation the rights to use, copy, modify, merge,
publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software
is furnished to do so, subject to the following
conditions:
The above copyright notice and this permission notice
shall be included in all copies or substantial portions
of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
MIT License (MIT)
Used by:
- autocfg 1.5.0
License text
Copyright (c) 2018 Josh Stone
Permission is hereby granted, free of charge, to any
person obtaining a copy of this software and associated
documentation files (the "Software"), to deal in the
Software without restriction, including without
limitation the rights to use, copy, modify, merge,
publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software
is furnished to do so, subject to the following
conditions:
The above copyright notice and this permission notice
shall be included in all copies or substantial portions
of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
MIT License (MIT)
Used by:
- smallvec 1.15.1
License text
Copyright (c) 2018 The Servo Project Developers
Permission is hereby granted, free of charge, to any
person obtaining a copy of this software and associated
documentation files (the "Software"), to deal in the
Software without restriction, including without
limitation the rights to use, copy, modify, merge,
publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software
is furnished to do so, subject to the following
conditions:
The above copyright notice and this permission notice
shall be included in all copies or substantial portions
of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
MIT License (MIT)
Used by:
- serial_test 3.4.0
- serial_test_derive 3.4.0
License text
Copyright (c) 2018 Tom Parker-Shemilt
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
MIT License (MIT)
Used by:
- want 0.3.1
License text
Copyright (c) 2018-2019 Sean McArthur
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
MIT License (MIT)
Used by:
- try-lock 0.2.5
License text
Copyright (c) 2018-2023 Sean McArthur
Copyright (c) 2016 Alex Crichton
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
MIT License (MIT)
Used by:
- getrandom 0.4.2
License text
Copyright (c) 2018-2026 The rust-random Project Developers
Copyright (c) 2014 The Rust Project Developers
Permission is hereby granted, free of charge, to any
person obtaining a copy of this software and associated
documentation files (the "Software"), to deal in the
Software without restriction, including without
limitation the rights to use, copy, modify, merge,
publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software
is furnished to do so, subject to the following
conditions:
The above copyright notice and this permission notice
shall be included in all copies or substantial portions
of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
MIT License (MIT)
Used by:
- unicode-truncate 1.1.0
License text
Copyright (c) 2019 Aetf <aetf at unlimitedcodeworks dot xyz>
Permission is hereby granted, free of charge, to any
person obtaining a copy of this software and associated
documentation files (the "Software"), to deal in the
Software without restriction, including without
limitation the rights to use, copy, modify, merge,
publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software
is furnished to do so, subject to the following
conditions:
The above copyright notice and this permission notice
shall be included in all copies or substantial portions
of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
MIT License (MIT)
Used by:
- slab 0.4.12
License text
Copyright (c) 2019 Carl Lerche
Permission is hereby granted, free of charge, to any
person obtaining a copy of this software and associated
documentation files (the "Software"), to deal in the
Software without restriction, including without
limitation the rights to use, copy, modify, merge,
publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software
is furnished to do so, subject to the following
conditions:
The above copyright notice and this permission notice
shall be included in all copies or substantial portions
of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
MIT License (MIT)
Used by:
- bumpalo 3.20.2
License text
Copyright (c) 2019 Nick Fitzgerald
Permission is hereby granted, free of charge, to any
person obtaining a copy of this software and associated
documentation files (the "Software"), to deal in the
Software without restriction, including without
limitation the rights to use, copy, modify, merge,
publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software
is furnished to do so, subject to the following
conditions:
The above copyright notice and this permission notice
shall be included in all copies or substantial portions
of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
MIT License (MIT)
Used by:
- tracing-core 0.1.36
- tracing 0.1.44
License text
Copyright (c) 2019 Tokio Contributors
Permission is hereby granted, free of charge, to any
person obtaining a copy of this software and associated
documentation files (the "Software"), to deal in the
Software without restriction, including without
limitation the rights to use, copy, modify, merge,
publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software
is furnished to do so, subject to the following
conditions:
The above copyright notice and this permission notice
shall be included in all copies or substantial portions
of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
MIT License (MIT)
Used by:
- tower-layer 0.3.3
- tower-service 0.3.3
- tower 0.5.3
License text
Copyright (c) 2019 Tower Contributors
Permission is hereby granted, free of charge, to any
person obtaining a copy of this software and associated
documentation files (the "Software"), to deal in the
Software without restriction, including without
limitation the rights to use, copy, modify, merge,
publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software
is furnished to do so, subject to the following
conditions:
The above copyright notice and this permission notice
shall be included in all copies or substantial portions
of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
MIT License (MIT)
Used by:
- axum 0.8.8
License text
Copyright (c) 2019 axum Contributors
Permission is hereby granted, free of charge, to any
person obtaining a copy of this software and associated
documentation files (the "Software"), to deal in the
Software without restriction, including without
limitation the rights to use, copy, modify, merge,
publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software
is furnished to do so, subject to the following
conditions:
The above copyright notice and this permission notice
shall be included in all copies or substantial portions
of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
MIT License (MIT)
Used by:
- http-body 1.0.1
License text
Copyright (c) 2019-2024 Sean McArthur & Hyper Contributors
Permission is hereby granted, free of charge, to any
person obtaining a copy of this software and associated
documentation files (the "Software"), to deal in the
Software without restriction, including without
limitation the rights to use, copy, modify, merge,
publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software
is furnished to do so, subject to the following
conditions:
The above copyright notice and this permission notice
shall be included in all copies or substantial portions
of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
MIT License (MIT)
Used by:
- http-body-util 0.1.3
License text
Copyright (c) 2019-2025 Sean McArthur & Hyper Contributors
Permission is hereby granted, free of charge, to any
person obtaining a copy of this software and associated
documentation files (the "Software"), to deal in the
Software without restriction, including without
limitation the rights to use, copy, modify, merge,
publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software
is furnished to do so, subject to the following
conditions:
The above copyright notice and this permission notice
shall be included in all copies or substantial portions
of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
MIT License (MIT)
Used by:
- iana-time-zone-haiku 0.1.2
- iana-time-zone 0.1.65
License text
Copyright (c) 2020 Andrew D. Straw
Permission is hereby granted, free of charge, to any
person obtaining a copy of this software and associated
documentation files (the "Software"), to deal in the
Software without restriction, including without
limitation the rights to use, copy, modify, merge,
publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software
is furnished to do so, subject to the following
conditions:
The above copyright notice and this permission notice
shall be included in all copies or substantial portions
of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
MIT License (MIT)
Used by:
- hyper-util 0.1.20
License text
Copyright (c) 2023-2025 Sean McArthur
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
MIT License (MIT)
Used by:
- anstream 1.0.0
- anstyle-parse 1.0.0
- anstyle-query 1.1.5
- anstyle-wincon 3.0.11
- anstyle 1.0.14
- assert_cmd 2.2.0
- clap 4.6.0
- clap_builder 4.6.0
- clap_derive 4.6.0
- clap_lex 1.1.0
- colorchoice 1.0.5
- is_terminal_polyfill 1.70.2
- once_cell_polyfill 1.70.2
- predicates-core 1.0.10
- predicates-tree 1.0.13
- predicates 3.1.4
- serde_spanned 1.1.1
- termtree 0.5.1
- toml 1.1.2+spec-1.1.0
- toml_datetime 1.1.1+spec-1.1.0
- toml_parser 1.1.2+spec-1.1.0
- toml_writer 1.1.1+spec-1.1.0
License text
Copyright (c) Individual contributors
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
MIT License (MIT)
Used by:
- libc 0.2.184
License text
Copyright (c) The Rust Project Developers
Permission is hereby granted, free of charge, to any
person obtaining a copy of this software and associated
documentation files (the "Software"), to deal in the
Software without restriction, including without
limitation the rights to use, copy, modify, merge,
publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software
is furnished to do so, subject to the following
conditions:
The above copyright notice and this permission notice
shall be included in all copies or substantial portions
of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
MIT License (MIT)
Used by:
- lru 0.12.5
License text
MIT License
Copyright (c) 2016 Jerome Froelich
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
MIT License (MIT)
Used by:
- static_assertions 1.1.0
License text
MIT License
Copyright (c) 2017 Nikolai Vazquez
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
MIT License (MIT)
Used by:
- darling 0.23.0
- darling_core 0.23.0
- darling_macro 0.23.0
License text
MIT License
Copyright (c) 2017 Ted Driggs
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
MIT License (MIT)
Used by:
- zeroize 1.8.2
License text
MIT License
Copyright (c) 2018-2021 The RustCrypto Project Developers
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
MIT License (MIT)
Used by:
- schemars 0.8.22
- schemars_derive 0.8.22
License text
MIT License
Copyright (c) 2019 Graham Esau
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
MIT License (MIT)
Used by:
- strum 0.26.3
- strum_macros 0.26.4
License text
MIT License
Copyright (c) 2019 Peter Glotfelty
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
MIT License (MIT)
Used by:
- tokio-macros 2.7.0
License text
MIT License
Copyright (c) 2019 Yoshua Wuyts
Copyright (c) Tokio Contributors
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
MIT License (MIT)
Used by:
- axum-core 0.5.6
License text
MIT License
Copyright (c) 2019–2025 axum Contributors
Permission is hereby granted, free of charge, to any
person obtaining a copy of this software and associated
documentation files (the "Software"), to deal in the
Software without restriction, including without
limitation the rights to use, copy, modify, merge,
publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software
is furnished to do so, subject to the following
conditions:
The above copyright notice and this permission notice
shall be included in all copies or substantial portions
of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
MIT License (MIT)
Used by:
- compact_str 0.8.1
License text
MIT License
Copyright (c) 2021 Parker Timmerman
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
MIT License (MIT)
Used by:
- castaway 0.2.4
License text
MIT License
Copyright (c) 2021 Stephen M. Coakley
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
MIT License (MIT)
Used by:
- matchit 0.8.4
License text
MIT License
Copyright (c) 2022 Ibraheem Ahmed
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
MIT License (MIT)
Used by:
- git-paw 0.5.0
License text
MIT License
Copyright (c) 2026 bearicorn
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
MIT License (MIT)
Used by:
- chrono 0.4.44
- difflib 0.4.0
- r-efi 6.0.0
- wasip2 1.0.2+wasi-0.2.9
- wasip3 0.4.0+wasi-0.3.0-rc-2026-01-06
- winapi-i686-pc-windows-gnu 0.4.0
- winapi-x86_64-pc-windows-gnu 0.4.0
- windows-core 0.62.2
- windows-implement 0.60.2
- windows-interface 0.59.3
- windows-link 0.2.1
- windows-result 0.4.1
- windows-strings 0.5.1
- windows-sys 0.59.0
- windows-sys 0.61.2
- windows-targets 0.52.6
- windows_aarch64_gnullvm 0.52.6
- windows_aarch64_msvc 0.52.6
- windows_i686_gnu 0.52.6
- windows_i686_gnullvm 0.52.6
- windows_i686_msvc 0.52.6
- windows_x86_64_gnu 0.52.6
- windows_x86_64_gnullvm 0.52.6
- windows_x86_64_msvc 0.52.6
License text
MIT License
Copyright (c) <year> <copyright holders>
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
associated documentation files (the "Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the
following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial
portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO
EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
USE OR OTHER DEALINGS IN THE SOFTWARE.
MIT License (MIT)
Used by:
- tokio 1.51.1
License text
MIT License
Copyright (c) Tokio Contributors
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
MIT License (MIT)
Used by:
- ident_case 1.0.1
License text
MIT License
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
MIT License (MIT)
Used by:
- crossterm 0.28.1
- crossterm_winapi 0.9.1
License text
MIT License
Copyright (c) 2019 Timon
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
MIT License (MIT)
Used by:
- anyhow 1.0.102
- atomic-waker 1.1.2
- dyn-clone 1.0.20
- fastrand 2.4.1
- indoc 2.0.7
- itoa 1.0.18
- linux-raw-sys 0.12.1
- linux-raw-sys 0.4.15
- once_cell 1.21.4
- paste 1.0.15
- pin-project-lite 0.2.17
- proc-macro2 1.0.106
- quote 1.0.45
- rustix 0.38.44
- rustix 1.1.4
- rustversion 1.0.22
- serde 1.0.228
- serde_core 1.0.228
- serde_derive 1.0.228
- serde_derive_internals 0.29.1
- serde_json 1.0.149
- serde_path_to_error 0.1.20
- serde_yaml 0.9.34+deprecated
- syn 2.0.117
- thiserror-impl 2.0.18
- thiserror 2.0.18
- unicode-ident 1.0.24
- unsafe-libyaml 0.2.11
- wasi 0.11.1+wasi-snapshot-preview1
- wit-bindgen 0.51.0
- zmij 1.0.21
License text
Permission is hereby granted, free of charge, to any
person obtaining a copy of this software and associated
documentation files (the "Software"), to deal in the
Software without restriction, including without
limitation the rights to use, copy, modify, merge,
publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software
is furnished to do so, subject to the following
conditions:
The above copyright notice and this permission notice
shall be included in all copies or substantial portions
of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
MIT License (MIT)
Used by:
- allocator-api2 0.2.21
License text
Permission is hereby granted, free of charge, to any
person obtaining a copy of this software and associated
documentation files (the "Software"), to deal in the
Software without restriction, including without
limitation the rights to use, copy, modify, merge,
publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software
is furnished to do so, subject to the following
conditions:
The above copyright notice and this permission notice
shall be included in all copies or substantial portions
of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
MIT License (MIT)
Used by:
- winnow 1.0.1
License text
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
MIT License (MIT)
Used by:
- encode_unicode 1.0.0
License text
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE
MIT License (MIT)
Used by:
- android_system_properties 0.1.5
License text
The MIT License (MIT)
Copyright (c) 2013 Nicolas Silva
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
MIT License (MIT)
Used by:
- aho-corasick 1.1.4
- memchr 2.8.0
License text
The MIT License (MIT)
Copyright (c) 2015 Andrew Gallant
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
MIT License (MIT)
Used by:
- strsim 0.11.1
License text
The MIT License (MIT)
Copyright (c) 2015 Danny Guo
Copyright (c) 2016 Titus Wormer <tituswormer@gmail.com>
Copyright (c) 2018 Akash Kurdekar
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
MIT License (MIT)
Used by:
- shlex 1.3.0
License text
The MIT License (MIT)
Copyright (c) 2015 Nicholas Allegra (comex).
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
MIT License (MIT)
Used by:
- ratatui 0.29.0
License text
The MIT License (MIT)
Copyright (c) 2016-2022 Florian Dehau
Copyright (c) 2023-2024 The Ratatui Developers
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
MIT License (MIT)
Used by:
- console 0.16.3
- dialoguer 0.12.0
License text
The MIT License (MIT)
Copyright (c) 2017 Armin Ronacher <armin.ronacher@active-4.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
MIT License (MIT)
Used by:
- bstr 1.12.1
License text
The MIT License (MIT)
Copyright (c) 2018-2019 Andrew Gallant
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
MIT License (MIT)
Used by:
- cassowary 0.3.0
License text
The MIT License (MIT)
Copyright (c) 2016 Dylan Ede
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
Unicode License v3 (Unicode-3.0)
Used by:
- unicode-ident 1.0.24
License text
UNICODE LICENSE V3
COPYRIGHT AND PERMISSION NOTICE
Copyright © 1991-2023 Unicode, Inc.
NOTICE TO USER: Carefully read the following legal agreement. BY
DOWNLOADING, INSTALLING, COPYING OR OTHERWISE USING DATA FILES, AND/OR
SOFTWARE, YOU UNEQUIVOCALLY ACCEPT, AND AGREE TO BE BOUND BY, ALL OF THE
TERMS AND CONDITIONS OF THIS AGREEMENT. IF YOU DO NOT AGREE, DO NOT
DOWNLOAD, INSTALL, COPY, DISTRIBUTE OR USE THE DATA FILES OR SOFTWARE.
Permission is hereby granted, free of charge, to any person obtaining a
copy of data files and any associated documentation (the "Data Files") or
software and any associated documentation (the "Software") to deal in the
Data Files or Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, and/or sell
copies of the Data Files or Software, and to permit persons to whom the
Data Files or Software are furnished to do so, provided that either (a)
this copyright and permission notice appear with all copies of the Data
Files or Software, or (b) this copyright and permission notice appear in
associated Documentation.
THE DATA FILES AND SOFTWARE ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF
THIRD PARTY RIGHTS.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN THIS NOTICE
BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES,
OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THE DATA
FILES OR SOFTWARE.
Except as contained in this notice, the name of a copyright holder shall
not be used in advertising or otherwise to promote the sale, use or other
dealings in these Data Files or Software without prior written
authorization of the copyright holder.
zlib License (Zlib)
Used by:
- foldhash 0.1.5
License text
Copyright (c) 2024 Orson Peters
This software is provided 'as-is', without any express or implied warranty. In
no event will the authors be held liable for any damages arising from the use of
this software.
Permission is granted to anyone to use this software for any purpose, including
commercial applications, and to alter it and redistribute it freely, subject to
the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim
that you wrote the original software. If you use this software in a product,
an acknowledgment in the product documentation would be appreciated but is
not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.