Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,8 @@ Behavior changes require doc updates. `src/cli/mod.rs` (`after_long_help` plus c

Per-tool layout and path resolution (Claude/Codex/Gemini), the convention-only Claude manifest, the Codex inline-hooks rationale, the generated plugin-skills mirror, the accepted `wt-switch-create` tradeoff, and `test_plugin_layout_is_consolidated`: `plugins/worktrunk/CLAUDE.md`.

The Pi-family integrations are two commands because they are two agents. `wt config plugins pi` targets Pi (earendil-works/pi), which loads `ExtensionAPI` extensions from `~/.pi/agent/extensions/`; `wt config plugins omp` targets oh-my-pi, which loads `HookAPI` hooks from `~/.omp/agent/hooks/pre/`. Path rules live in `src/commands/config/pi.rs` and `src/commands/config/omp.rs`; the embedded sources are `dev/pi-extension.ts` and `dev/omp-hook.ts`. Neither file is interchangeable — the loaders differ, and so do the config roots (`$PI_CODING_AGENT_DIR` for Pi; `$PI_CONFIG_DIR`, `$OMP_PROFILE`/`$PI_PROFILE`, and `$PI_CODING_AGENT_DIR` for oh-my-pi).

## Data Safety

Never risk data loss without explicit user consent. A failed command that preserves data beats a "successful" one that silently destroys work.
Expand Down
8 changes: 6 additions & 2 deletions dev/pi-plugin.ts → dev/omp-hook.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
// Worktrunk activity tracking hook for Pi / oh-my-pi.
// Worktrunk activity tracking hook for oh-my-pi (`omp`).
//
// Tracks agent activity per branch, showing status markers in `wt list`:
// 🤖 — agent is working
// 💬 — agent is waiting for input
//
// Installed globally via: wt config plugins pi install
// Installed globally via: wt config plugins omp install
//
// oh-my-pi loads user hooks from `hooks/pre/*.ts` and exposes `HookAPI`.
// earendil-works Pi is a different agent with a different loader and API —
// see `dev/pi-extension.ts` and `wt config plugins pi install`.

import type { HookAPI } from "@oh-my-pi/pi-coding-agent/extensibility/hooks";

Expand Down
43 changes: 43 additions & 0 deletions dev/pi-extension.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
// Worktrunk activity tracking extension for Pi (earendil-works/pi).
//
// Tracks agent activity per branch, showing status markers in `wt list`:
// 🤖 — agent is working
// 💬 — agent is waiting for input
//
// Installed globally via: wt config plugins pi install
//
// Pi loads user extensions from `~/.pi/agent/extensions/*.ts` (or
// `$PI_CODING_AGENT_DIR/extensions/`) and hands each factory an
// `ExtensionAPI`. oh-my-pi is a different agent with a different loader and
// API — see `dev/omp-hook.ts` and `wt config plugins omp install`.

import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";

export default function worktrunkActivity(pi: ExtensionAPI): void {
const run = async (
cwd: string,
args: ["set", string] | ["clear"],
): Promise<void> => {
try {
await pi.exec("wt", ["config", "state", "marker", ...args], { cwd });
} catch {
// Activity tracking must never interrupt the host Pi session.
}
};

pi.on("agent_start", async (_event, ctx) => {
await run(ctx.cwd, ["set", "🤖"]);
});

// `agent_end` is not the end: Pi may auto-retry, auto-compact and retry, or
// pick up a queued follow-up message. `agent_settled` is the event Pi
// documents for status integrations — it fires once Pi will not continue
// running on its own.
pi.on("agent_settled", async (_event, ctx) => {
await run(ctx.cwd, ["set", "💬"]);
});

pi.on("session_shutdown", async (_event, ctx) => {
await run(ctx.cwd, ["clear"]);
});
}
2 changes: 1 addition & 1 deletion docs/public/llms.txt

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

26 changes: 17 additions & 9 deletions docs/src/content/docs/claude-code.md
Original file line number Diff line number Diff line change
@@ -1,21 +1,21 @@
---
title: "Agent Integration"
description: "Worktrunk plugins for Claude Code, Codex, OpenCode, Pi, and Gemini CLI: a configuration skill, wt list activity tracking, and Claude-only worktree isolation."
description: "Worktrunk plugins for Claude Code, Codex, OpenCode, Pi, oh-my-pi, and Gemini CLI: a configuration skill, wt list activity tracking, and Claude-only worktree isolation."
sidebar:
order: 21
---
Worktrunk ships a plugin for each supported agent CLI. What a plugin provides depends on the hooks that CLI exposes:

| Capability | Claude Code | Codex | OpenCode | Pi | Gemini CLI |
|---|:-:|:-:|:-:|:-:|:-:|
| Configuration skill | ✓ | ✓ | | | ✓ |
| Activity tracking (🤖/💬 in `wt list`) | ✓ | ✓ | ✓ | ✓ | ✓ |
| Worktree isolation | ✓ | | | | |
| `/wt-switch-create` skill\* | ✓ | | | | |
| Capability | Claude Code | Codex | OpenCode | Pi | oh-my-pi | Gemini CLI |
|---|:-:|:-:|:-:|:-:|:-:|:-:|
| Configuration skill | ✓ | ✓ | | | | ✓ |
| Activity tracking (🤖/💬 in `wt list`) | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| Worktree isolation | ✓ | | | | | |
| `/wt-switch-create` skill\* | ✓ | | | | | |

\* Codex and Gemini also load the `/wt-switch-create` skill from the shared skill set, but neither lets a skill change the session's working directory, so it does nothing there.

The configuration skill is documentation the agent reads to help set up LLM commits, hooks, and troubleshooting. Activity tracking shows which worktrees have running sessions. Worktree isolation needs worktree-lifecycle hooks, which only Claude Code exposes, so Codex, OpenCode, Pi, and Gemini users invoke `wt switch --create` and `wt remove` directly. Codex tracks activity through its own `Stop` and `SessionEnd` hooks.
The configuration skill is documentation the agent reads to help set up LLM commits, hooks, and troubleshooting. Activity tracking shows which worktrees have running sessions. Worktree isolation needs worktree-lifecycle hooks, which only Claude Code exposes, so Codex, OpenCode, Pi, oh-my-pi, and Gemini users invoke `wt switch --create` and `wt remove` directly. Codex tracks activity through its own `Stop` and `SessionEnd` hooks.

## Installation

Expand Down Expand Up @@ -63,7 +63,15 @@ This writes the activity-tracking plugin to OpenCode's global plugins directory,
wt config plugins pi install
```

This writes the activity hook to `~/.omp/agent/hooks/pre/worktrunk.ts`. Named `$OMP_PROFILE` or `$PI_PROFILE` profiles use `~/.omp/profiles/<profile>/agent`, `$PI_CONFIG_DIR` changes the `.omp` config root, and `$PI_CODING_AGENT_DIR` overrides the agent directory for the default profile. `wt config plugins pi uninstall` removes the hook.
This writes the activity extension to `~/.pi/agent/extensions/worktrunk.ts`, where Pi discovers it on startup; `$PI_CODING_AGENT_DIR` replaces the agent directory. Pi has no profile concept. `wt config plugins pi uninstall` removes the extension.

### oh-my-pi

```bash
wt config plugins omp install
```

oh-my-pi (`omp`) is a Pi-derived agent with its own config root and hook API, so it takes a separate command. This writes the activity hook to `~/.omp/agent/hooks/pre/worktrunk.ts`. Named `$OMP_PROFILE` or `$PI_PROFILE` profiles use `~/.omp/profiles/<profile>/agent`, `$PI_CONFIG_DIR` changes the `.omp` config root, and `$PI_CODING_AGENT_DIR` overrides the agent directory for the default profile. `wt config plugins omp uninstall` removes the hook.

### Gemini CLI

Expand Down
9 changes: 5 additions & 4 deletions docs/src/content/docs/faq.md
Original file line number Diff line number Diff line change
Expand Up @@ -160,14 +160,15 @@ Created by the `wt config plugins <agent>` install commands. Each writes outside
| File | Created by | Purpose |
|------|------------|---------|
| `~/.config/opencode/plugins/worktrunk.ts` | `wt config plugins opencode install` | Activity markers in `wt list` |
| `~/.omp/agent/hooks/pre/worktrunk.ts` | `wt config plugins pi install` | Activity markers in `wt list` |
| `~/.pi/agent/extensions/worktrunk.ts` | `wt config plugins pi install` | Activity markers in `wt list` |
| `~/.omp/agent/hooks/pre/worktrunk.ts` | `wt config plugins omp install` | Activity markers in `wt list` |
| `~/.claude/settings.json` | `wt config plugins claude install-statusline` | Adds a `statusLine` entry running `wt list statusline --format=claude-code` |

The OpenCode path follows `$OPENCODE_CONFIG_DIR` > `$XDG_CONFIG_HOME/opencode` > `~/.config/opencode`; the Pi path follows `$PI_CONFIG_DIR`, `$OMP_PROFILE`/`$PI_PROFILE`, and `$PI_CODING_AGENT_DIR`; Claude Code's follows `$CLAUDE_CONFIG_DIR`. The two plugin files are worktrunk's own, so install writes them whole. `settings.json` belongs to Claude Code, so install merges the `statusLine` key into it and leaves the rest untouched.
The OpenCode path follows `$OPENCODE_CONFIG_DIR` > `$XDG_CONFIG_HOME/opencode` > `~/.config/opencode`; the Pi path follows `$PI_CODING_AGENT_DIR`; the oh-my-pi path follows `$PI_CONFIG_DIR`, `$OMP_PROFILE`/`$PI_PROFILE`, and `$PI_CODING_AGENT_DIR`; Claude Code's follows `$CLAUDE_CONFIG_DIR`. The three plugin files are worktrunk's own, so install writes them whole (and uninstall removes them whole). `settings.json` belongs to Claude Code, so install merges the `statusLine` key into it and leaves the rest untouched.

`wt config plugins claude install` and `wt config plugins codex install` write nothing themselves — they run `claude` / `codex` to register the marketplace and install the plugin, and each CLI records that in its own config (`~/.claude/plugins/`, `~/.codex/config.toml`).

**To remove:** `wt config plugins opencode uninstall` and `wt config plugins pi uninstall` delete their plugin file. `wt config plugins claude uninstall` / `codex uninstall` remove the plugin and marketplace through that CLI. The statusline entry is removed by editing `settings.json`.
**To remove:** `wt config plugins opencode uninstall`, `wt config plugins pi uninstall`, and `wt config plugins omp uninstall` delete their plugin file. `wt config plugins claude uninstall` / `codex uninstall` remove the plugin and marketplace through that CLI. The statusline entry is removed by editing `settings.json`.

### 6. Temporary files (automatic)

Expand Down Expand Up @@ -215,7 +216,7 @@ A branch checked out in a second worktree is retained regardless, `-D` included.
- `wt config state clear` — removes all worktrunk data from `.git/` (config keys, caches, markers, hints, variables, logs, stale trash)
- `wt config shell install` — when migrating an integration to a new location, removes the file left at the old one: fish `conf.d/wt.fish` (now `functions/wt.fish`) and nushell wrappers stranded under `<config-dir>/vendor/autoload` (now `<data-dir>/vendor/autoload`). The old path is where worktrunk's own wrapper lived and is named after the command being installed, so it's taken back whole without reading it — a `conf.d/wt.fish` left in place would be sourced at startup and shadow the new wrapper anyway. Only that exact filename is touched, and each removal is printed
- `wt config shell uninstall` — removes integration lines from bash/zsh/PowerShell rc files, and deletes worktrunk's wrapper and completion files (fish `functions/`, `conf.d/`, and `completions/`; nushell `vendor/autoload`). Uninstall takes no command name, so it lists those directories and recognizes files by worktrunk's own content markers, whatever binary name they were installed under; files without the markers are left alone. An rc file belongs to the user, so a line qualifies only where it runs the init command: one that merely mentions it, inside a comment, an `echo`, or an alias body, stays. Every line uninstall does take is printed, before removal and again after
- `wt config plugins opencode uninstall` / `wt config plugins pi uninstall` — deletes that agent's `worktrunk.ts` plugin file. Only worktrunk's own file is touched; the rest of the agent's plugin directory is left alone
- `wt config plugins opencode uninstall` / `wt config plugins pi uninstall` / `wt config plugins omp uninstall` — deletes that agent's `worktrunk.ts` plugin file. Only worktrunk's own file is touched; the rest of the agent's plugin directory is left alone

See [What files does Worktrunk create?](#what-files-does-worktrunk-create) for details.

Expand Down
2 changes: 1 addition & 1 deletion docs/tests/built-site.test.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -606,7 +606,7 @@ test('short wide tables become labeled records without capturing dense tables',
/\bwt-responsive-records\b/,
);
assert.doesNotMatch(
findTable('/claude-code/', ['Capability', 'Claude Code', 'Codex', 'OpenCode', 'Pi', 'Gemini CLI']).attributes,
findTable('/claude-code/', ['Capability', 'Claude Code', 'Codex', 'OpenCode', 'Pi', 'oh-my-pi', 'Gemini CLI']).attributes,
/\bwt-responsive-records\b/,
);
assert.doesNotMatch(
Expand Down
24 changes: 16 additions & 8 deletions plugins/worktrunk/skills/worktrunk/reference/claude-code.md

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading
Loading