AgentSkillsCN

zjj

zjj 工作区隔离专家 v0.4.0。当用户提及“zjj”、“隔离工作区”、“启动工作区”、“工作区隔离”,或需要借助 Zellij 会话集成来搭建、管理、同步、合并,或移除隔离的 JJ 工作区时,此技能便大显身手。涵盖 56 条命令:init、add、remove、list、status、focus、switch、attach、sync、diff、done、abort、spawn、work、agents、ai、bookmark、template、pane、checkpoint、undo、revert、retry、rollback、recover、integrity、lock、unlock、claim、yield、queue、batch、events、whereami、whoami、context、introspect、query、can-i、contract、examples、validate、whatif、wait、schema、export、import、rename、pause、resume、clone、backup、clean、doctor、dashboard、config、completions。

SKILL.md
--- frontmatter
name: zjj
description: "zjj workspace isolation expert v0.4.0. Use when the user says 'zjj', 'isolated workspace', 'spawn workspace', 'workspace isolation', or needs to stand up, manage, sync, merge, or remove isolated jj workspaces with Zellij session integration. Covers 56 commands: init, add, remove, list, status, focus, switch, attach, sync, diff, done, abort, spawn, work, agents, ai, bookmark, template, pane, checkpoint, undo, revert, retry, rollback, recover, integrity, lock, unlock, claim, yield, queue, batch, events, whereami, whoami, context, introspect, query, can-i, contract, examples, validate, whatif, wait, schema, export, import, rename, pause, resume, clone, backup, clean, doctor, dashboard, config, completions."
argument-hint: [subcommand or workflow question]

You are an expert in zjj (v0.4.0), the workspace isolation manager that combines Jujutsu (jj) workspaces with Zellij terminal sessions. When the user asks for an isolated workspace, you use zjj commands — never raw jj workspace commands.

Core Mental Model

  • zjj = jj workspaces + Zellij tabs + session state — one command stands up an isolated working directory with its own terminal session
  • Each session gets: a jj workspace (separate working directory), a Zellij tab (terminal environment), and tracked state (in .zjj/state.db)
  • Workspaces share the repo — changes are visible across workspaces via jj log, but working copies are independent
  • zjj done is the clean exit — squash-merges work back to main, cleans up workspace and session
  • Dependencies: jj (required), zellij (required), beads (optional), claude (optional)

Architecture

code
project/                          # main jj repo
├── .zjj/
│   ├── state.db                  # SQLite session tracking database
│   ├── config.toml               # project-level configuration
│   └── layouts/                  # generated Zellij layout files (KDL)
├── .beads/
│   └── issues.jsonl              # bead issue tracker (JSONL)
└── ../lewis__workspaces/         # workspace directory (configurable via workspace_dir)
    ├── feature-auth/             # zjj session workspace
    │   ├── .cursorrules          # AI agent discovery (Cursor/Windsurf)
    │   └── .ai-instructions.md   # AI agent discovery (Claude/generic)
    ├── bugfix-123/               # another session workspace
    └── ai-sandbox/               # spawned agent workspace

Each zjj add creates:

  1. A jj workspace via jj workspace add --name <name> <path>
  2. A Zellij tab named zjj:<name> (context-dependent: new tab if inside Zellij, new session if outside)
  3. A session record in state.db (SQLite) with status CreatingActive

Session State Machine

Sessions follow a strict lifecycle with validated transitions:

code
Creating ──→ Active ──→ Completed
   │            │  ↘        ↑
   │            │   Paused ─┘
   │            ↓
   └──→ Failed ←── Syncing → Synced → Active
StateAllowed OperationsTransitions To
Creating(none — transient)Active, Failed
Activestatus, diff, focus, remove, sync, done, abort, checkpointSyncing, Paused, Completed, Failed
Syncing(transient)Synced, Failed
Synced(transient)Active, Paused, Completed
Pausedstatus, focus, remove, resumeActive, Completed
Completedremove, undo(terminal; undo only if not pushed)
Failedremove, recover(terminal; recover auto-diagnoses and fixes)

Database Schema (state.db)

sql
CREATE TABLE sessions (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    name TEXT UNIQUE NOT NULL,
    status TEXT CHECK(status IN ('creating','active','paused','completed','failed')),
    workspace_path TEXT NOT NULL,
    branch TEXT,
    created_at INTEGER,          -- unix timestamp
    updated_at INTEGER,          -- unix timestamp (auto-updated via trigger)
    last_synced INTEGER,
    metadata TEXT                 -- JSON blob
);

Internal Command Flows

zjj add — 8-Step Creation

  1. Validate name: ASCII alphanumeric/dash/underscore, starts with letter, max 64 chars
  2. Check uniqueness: no existing session with same name
  3. Resolve workspace path: {repo_root}/{workspace_dir}/{name} (creates parent dir if needed)
  4. Create jj workspace: runs jj workspace add --name <name> <path>
  5. Insert DB record: status = Creating
  6. Execute post_create hooks: sequential, CWD = workspace dir, failure → status = Failed
  7. Update status: Active
  8. Open Zellij: new tab (inside Zellij) or new session (outside Zellij), using layout template

zjj done — 9-Phase Merge

  1. Validate location: must be in workspace OR use -w <name> to target a workspace from main — exit code 2 only if neither applies
  2. Build preview (if --dry-run or via zjj whatif done): uncommitted files, commits to merge, conflicts, bead to close
  3. Get uncommitted files: jj status --no-pager, parse M/A/D/R lines
  4. Commit changes: jj commit -m "<message>" (auto-generated or custom)
  5. Check conflicts: jj log -r @..@ for divergent commits
  6. Get commits to merge: parse change_id, commit_id, description, timestamp from jj log
  7. Merge to main: jj workspace abandon --name <name> — exit code 3 on conflict
  8. Update beads: find linked bead in .beads/issues.jsonl, set status to closed
  9. Cleanup: delete workspace directory (unless --keep-workspace)

Note: done is reversiblezjj undo can roll it back within 24 hours, as long as changes haven't been pushed to remote.

If step 7 returns exit code 3 — exponential backoff with checkpoint safety:

The full safe sequence: checkpoint first (safety snapshot), then sync + retry with backoff, then recover on exhaustion. Use zjj retry (not a manual re-invocation of done) — it retries the exact last failed command.

bash
# 1. Safety checkpoint BEFORE the retry loop
zjj checkpoint create -d "Before merge retry loop"

# 2. Backoff retry loop
WAIT=2
MAX_RETRIES=6
RETRY=0
EXIT_CODE=3

while [ $RETRY -lt $MAX_RETRIES ] && [ $EXIT_CODE -ne 0 ]; do
  # Re-sync onto latest main — stale state is the #1 cause of repeated conflicts
  zjj sync
  SYNC_EXIT=$?
  if [ $SYNC_EXIT -ne 0 ]; then
    echo "Sync conflict — resolve manually in workspace, then retry."
    break
  fi

  # Use zjj retry — retries the last failed command (the done)
  zjj retry
  EXIT_CODE=$?
  [ $EXIT_CODE -eq 0 ] && break

  RETRY=$((RETRY + 1))
  echo "Merge attempt $((RETRY + 1))/$((MAX_RETRIES + 1)) — waiting ${WAIT}s..."
  sleep $WAIT
  WAIT=$((WAIT * 2))
  [ $WAIT -gt 60 ] && WAIT=60
done

# 3. On exhaustion: recover, then flag user
if [ $EXIT_CODE -ne 0 ]; then
  echo "EXHAUSTED: merge retries failed."
  zjj recover --diagnose   # diagnose what's broken without auto-fixing
  echo "Workspace preserved. File a bead. Flag user for manual resolution."
  # DO NOT abort or remove the workspace — it is evidence.
  # Rollback to checkpoint if state is corrupt:
  #   zjj rollback --to <checkpoint-id> <session-name>
fi

zjj spawn — Agent Isolation

  1. Validate location: must be on main branch (not in workspace)
  2. Validate bead: check .beads/issues.jsonl, must be open or ready
  3. Create workspace: jj workspace add --name <bead_id> <path>
  4. Write agent discovery files: .cursorrules and .ai-instructions.md in workspace
  5. Update bead: status → in_progress
  6. Spawn agent subprocess: CWD = workspace, env vars set (see below)
  7. On success (exit 0): merge via jj workspace abandon, bead → completed, cleanup
  8. On failure (exit non-0): bead stays in_progress, optionally cleanup

Agent Environment Variables:

  • ZJJ_BEAD_ID — the bead being worked on
  • ZJJ_WORKSPACE — absolute path to workspace
  • ZJJ_AGENT_ID — agent identifier for tracking
  • ZJJ_SESSION — current session name
  • ZJJ_ACTIVE=1 — signals agent is in zjj context

Exit Codes

CodeMeaningContext
0SuccessAll commands
1Validation errorInvalid input, bad name, missing args
2Not in workspacezjj done run from main instead of workspace
3Merge conflictzjj done encountered conflicts during merge
4Other errorCommand failures, hook failures, DB errors

Standing Up an Isolated Workspace

Quick Start (Most Common)

bash
zjj init                          # first time only — initialize zjj in a jj repo
zjj add feature-auth              # create isolated workspace + Zellij tab
# You're now in an isolated workspace. Work freely.
zjj done                          # merge back to main, clean up

Full Workflow

bash
# 1. Initialize (once per repo)
zjj init

# 2. Create isolated workspace
zjj add feature-auth              # standard layout (claude + beads + status panes)
zjj add quick-fix -t minimal      # minimal layout (just a shell)
zjj add experiment -t full        # full layout (all panes)
zjj add headless --no-open        # create workspace without opening Zellij tab
zjj add feature-x -b zjj-abc12    # associate with bead zjj-abc12

# 3. Work in isolation
# Your workspace is at ../lewis__workspaces/feature-auth/
# All jj commands work normally within the workspace

# 4. Check status
zjj status feature-auth           # detailed session info
zjj list                          # all active sessions
zjj list --state active           # filter by state

# 5. Stay synced with main
zjj sync feature-auth             # rebase workspace onto latest main
zjj sync                          # sync current workspace
zjj sync --all                    # sync all active sessions

# 6. Review changes
zjj diff feature-auth             # full diff against main
zjj diff feature-auth --stat      # summary only

# 7. Complete work
zjj done                          # merge to main + cleanup
zjj done -m "feat: auth system"   # custom commit message
zjj done --squash                 # squash all commits into one
zjj done --dry-run                # preview without executing
zjj done --keep-workspace         # merge but keep workspace alive
zjj done --detect-conflicts       # check for conflicts before merging

Complete CLI Reference (56 Commands)

1. Initialization

CommandPurpose
zjj initInitialize zjj in a jj repo (creates .zjj/ directory)
zjj init --jsonJSON output for programmatic use

2. Session Creation (Manual)

CommandPurpose
zjj add <name>Create workspace + Zellij tab
zjj add <name> -t <template>Use layout: minimal, standard, full, split, review
zjj add <name> --no-openCreate workspace without Zellij tab
zjj add <name> --no-zellijSkip Zellij integration (non-TTY)
zjj add <name> --no-hooksSkip post_create hooks
zjj add <name> --idempotentSucceed if session already exists
zjj add <name> -b <bead_id>Associate with bead/issue ID
zjj add <name> --dry-runPreview without creating

3. Session Completion

CommandPurpose
zjj doneComplete work: merge to main + cleanup
zjj done -w <name>Complete specific workspace from anywhere
zjj done -m "msg"Merge with custom message
zjj done --squashSquash all commits into one
zjj done --dry-runPreview merge
zjj done --keep-workspaceMerge but preserve workspace
zjj done --detect-conflictsCheck for conflicts before merging
zjj done --no-bead-updateSkip bead status update
zjj abortDiscard workspace without merging
zjj abort -w <name>Discard specific workspace
zjj abort --keep-workspaceKeep files, just remove from tracking

4. Session Removal

CommandPurpose
zjj remove <name>Remove session + workspace (with confirmation)
zjj remove <name> -fForce removal without confirmation
zjj remove <name> --mergeSquash-merge to main before removal
zjj remove <name> -kRemove session but keep jj branch
zjj remove <name> --idempotentSucceed if session doesn't exist

5. Session List & Status

CommandPurpose
zjj listList active sessions
zjj list --allInclude completed and failed sessions
zjj list --verboseShow workspace paths and bead titles
zjj list --bead <id>Filter by bead ID
zjj list --agent <name>Filter by agent owner
zjj list --state <state>Filter by state (created, working, ready, merged, etc.)
zjj statusShow all session statuses
zjj status <name>Detailed status for one session
zjj status --watchContinuously update (1s refresh)

6. Navigation & Focus

CommandPurpose
zjj focus <name>Switch to session's Zellij tab (inside Zellij)
zjj focusInteractive session selection
zjj attach <name>Attach to Zellij session from outside (shell → Zellij)
zjj switch <name>Navigate between workspaces
zjj switch --show-contextSwitch and show session details
zjj dashboardLaunch interactive TUI kanban dashboard

7. Sync & Diff

CommandPurpose
zjj sync <name>Rebase session workspace onto main
zjj syncSync current workspace
zjj sync --allSync all active sessions
zjj diff <name>Diff between session and main
zjj diff <name> --statSummary diffstat only

8. Version Control (Bookmarks)

CommandPurpose
zjj bookmark list [session]List bookmarks in session workspace
zjj bookmark list --allShow all bookmarks including remote
zjj bookmark create <name>Create bookmark at current revision
zjj bookmark create -p <name>Create and push to remote
zjj bookmark delete <name>Delete a bookmark
zjj bookmark move --to <rev> <name>Move bookmark to different revision

9. Checkpoint & Undo

CommandPurpose
zjj checkpoint create -d "desc"Create checkpoint with description
zjj checkpoint listList all available checkpoints
zjj checkpoint restore <id>Restore sessions to checkpoint
zjj undoRevert most recent done (24hr window)
zjj undo -lList undo history
zjj undo --dry-runPreview undo
zjj revert <name>Revert specific session merge
zjj rollback --to <cp> <session>Rollback session to checkpoint
zjj retryRetry the last failed operation

10. Agent Management

CommandPurpose
zjj agentsList all active agents
zjj agents --allInclude stale agents
zjj agents --session <name>Filter by session
zjj agents registerRegister as an agent
zjj agents register --id <id>Register with specific ID
zjj agents register -s <session>Associate with session
zjj agents heartbeatSend heartbeat to indicate liveness
zjj agents heartbeat -c <cmd>Report current command
zjj agents statusShow current agent status
zjj agents unregisterUnregister as an agent

11. Agent Spawning

CommandPurpose
zjj spawn <bead_id>Spawn workspace + run Claude agent
zjj spawn <bead_id> -bRun agent in background
zjj spawn <bead_id> --agent-command=<cmd>Use custom agent
zjj spawn <bead_id> --agent-args <args>Pass additional arguments
zjj spawn <bead_id> --timeout <secs>Set timeout (default: 14400s)
zjj spawn <bead_id> --no-auto-mergeDon't merge on success
zjj spawn <bead_id> --no-auto-cleanupDon't cleanup on failure
zjj work <name>Create workspace + register agent
zjj work <name> -b <bead_id>Associate with bead
zjj work <name> --agent-id <id>Register with specific agent ID
zjj work <name> --no-zellijDon't create Zellij tab
zjj work <name> --no-agentDon't register as agent
zjj work <name> --idempotentReuse existing session
zjj broadcast <message>Send message to all active agents
zjj broadcast --agent-id <id> <msg>Send as specific agent

12. AI Integration

CommandPurpose
zjj ai statusAI-optimized status with guided next action
zjj ai workflowShow 7-step parallel agent workflow
zjj ai quick-startShow essential commands
zjj ai nextGet single next action with copy-paste command
zjj whereamiReturns 'main' or 'workspace:<name>'
zjj whoamiReturns agent ID or 'unregistered'
zjj contextShow complete environment context
zjj context --field <path>Extract single field
zjj context --no-beadsSkip beads database query (faster)
zjj context --no-healthSkip health checks (faster)

13. Introspection & Query

CommandPurpose
zjj introspectDiscover zjj capabilities
zjj introspect <command>Inspect specific command
zjj introspect --aiAI-optimized output
zjj introspect --env-varsShow environment variables
zjj introspect --workflowsShow common workflow patterns
zjj introspect --session-statesShow valid state transitions
zjj query session-exists <name>Check if session exists
zjj query session-countCount active sessions
zjj query can-runCheck if zjj can run
zjj query suggest-name <pattern>Suggest next available name
zjj doctorRun system health checks
zjj doctor --fixAuto-fix issues where possible
zjj doctor --dry-runPreview what would be fixed
zjj doctor --verboseShow detailed progress
zjj can-i <action> [resource]Check if action is permitted
zjj contract [command]Show command contracts
zjj examples [command]Show usage examples
zjj examples --use-case <case>Filter by use case
zjj validate <command> [args]...Pre-validate inputs
zjj whatif <command> [args]...Preview command effects

14. Template Management

CommandPurpose
zjj template listList all available templates
zjj template create <name>Create a new template
zjj template create -d "desc" <name>Create with description
zjj template create -f <file> <name>Import from KDL file
zjj template create -b <base> <name>Use builtin as base (minimal, standard, full, split, review)
zjj template show <name>Show template details
zjj template delete -f <name>Delete without confirmation

15. Integrity & Recovery

CommandPurpose
zjj integrity validate <workspace>Validate workspace integrity
zjj integrity repair <workspace>Repair corrupted workspace
zjj integrity repair -f <workspace>Repair without confirmation
zjj integrity backup listList available backups
zjj integrity backup restore <id>Restore from backup
zjj integrity backup restore -f <id>Restore without confirmation
zjj recover [session]Recover from inconsistent state
zjj recover --diagnoseOnly diagnose, don't fix
zjj recover --op <id>Restore to specific operation ID
zjj recover --lastRestore to previous operation
zjj recover --listList operation log

16. Locking & Coordination

CommandPurpose
zjj claim <resource>Acquire exclusive lock on resource
zjj claim -t <secs> <resource>Lock with timeout (default: 60s)
zjj yield <resource>Release exclusive lock
zjj lock <session>Acquire lock on session
zjj lock --ttl <secs> <session>Lock with specific TTL
zjj lock --agent-id <id> <session>Lock as specific agent
zjj unlock <session>Release lock on session
zjj unlock --agent-id <id> <session>Unlock as specific agent
zjj queue --listList all queue entries
zjj queue --add <workspace>Add workspace to queue
zjj queue --add <ws> --bead <id>Add with bead association
zjj queue --add <ws> --agent <id>Add with agent assignment
zjj queue --add <ws> --priority <N>Add with priority (1-10, default: 5)
zjj queue --nextGet next pending entry
zjj queue --remove <workspace>Remove from queue
zjj queue --status <workspace>Check workspace status
zjj queue --statsShow queue statistics

17. Batch & Events

CommandPurpose
zjj batch <cmd> <cmd> ...Execute multiple commands
zjj batch -f <file>Execute commands from file
zjj batch --atomic <cmds>All or nothing execution
zjj batch --stop-on-error <cmds>Stop on first failure
zjj eventsView recent events
zjj events --followStream events in real-time
zjj events -l <count>Limit number of events
zjj events --session <name>Filter by session
zjj events --type <type>Filter by event type

18. Pane Management

CommandPurpose
zjj pane focus <session> [pane]Focus specific pane
zjj pane focus -d <dir> <session>Focus pane in direction (up, down, left, right)
zjj pane list <session>List panes in session
zjj pane next <session>Focus next pane

19. Import & Export

CommandPurpose
zjj export [session]Export session state
zjj export <session> -o <file>Export to file
zjj import <file>Import session state
zjj import -f <file>Force overwrite existing
zjj import --skip-existing <file>Skip existing sessions
zjj import --dry-run <file>Preview import

20. Wait & Schema

CommandPurpose
zjj wait session-exists <name>Wait for session to exist
zjj wait session-unlocked <name>Wait for session to be unlocked
zjj wait healthyWait for healthy state
zjj wait session-status <name>Wait for specific status
zjj wait -t <secs> <condition>Set timeout (default: 30s)
zjj wait -i <secs> <condition>Set polling interval (default: 1s)
zjj schemaShow all JSON schemas
zjj schema <name>Show specific schema
zjj schema --listList available schemas

21. Session Lifecycle

CommandPurpose
zjj rename <old> <new>Rename a session
zjj pause [name]Pause an active session
zjj resume [name]Resume a paused session
zjj clone <source> <dest>Clone a session
zjj clone --no-zellij <src> <dest>Clone without Zellij

22. Backup & Maintenance

CommandPurpose
zjj backup --createCreate backups of all databases
zjj backup --listList all available backups
zjj backup --restore <db>Restore database (state.db, beads.db, queue.db)
zjj backup --restore <db> -t <ts>Restore specific timestamp (YYYYMMDD-HHMMSS)
zjj backup --statusShow backup status and retention
zjj backup --retentionApply retention policy
zjj cleanRemove stale sessions
zjj clean --dry-runPreview stale sessions
zjj clean -fForce clean
zjj clean --periodicRun as periodic daemon (1hr interval)
zjj clean --age-threshold <secs>Set age threshold (default: 7200s)

23. Configuration

CommandPurpose
zjj configView all configuration
zjj config <key>View specific config value
zjj config <key> <value>Set config value
zjj config -g <key> <value>Set global config
zjj config --jsonOutput as JSON

Full Configuration Schema (TOML, hierarchy: built-in defaults → global ~/.config/zjj/config.toml → project .zjj/config.tomlZJJ_* env vars → CLI flags):

toml
workspace_dir = "../{repo}__workspaces"   # {repo} = repo folder name
main_branch = ""                           # auto-detected if empty
default_template = "standard"              # minimal | standard | full | split | review
state_db = ".zjj/state.db"

[watch]
enabled = true
debounce_ms = 100
paths = [".beads/beads.db"]

[hooks]
post_create = []                           # run after zjj add (CWD = workspace)
pre_remove = []                            # run before zjj remove
post_merge = []                            # run after zjj done merges

[zellij]
session_prefix = "zjj"
use_tabs = true                            # tabs (inside Zellij) vs sessions (outside)
layout_dir = ".zjj/layouts"

[zellij.panes.main]
command = "claude"
args = []
size = "70%"

[zellij.panes.beads]
command = "bv"
args = []
size = "50%"

[zellij.panes.status]
command = "zjj"
args = ["status", "--watch"]
size = "50%"

[zellij.panes.float]
enabled = true
command = ""
width = "80%"
height = "60%"

[dashboard]
refresh_ms = 1000
theme = "default"
columns = ["name", "status", "branch", "changes", "beads"]
vim_keys = true

[agent]
command = "claude"                         # default agent for zjj spawn

[agent.env]
# Additional agent environment variables

[session]
auto_commit = false
commit_prefix = "wip:"

[recovery]
policy = "warn"                            # warn | error | ignore
log_recovered = true
auto_recover_corrupted_wal = true
delete_corrupted_database = false

Key config paths (dot notation for zjj config <key> <value>):

  • workspace_dir — where workspaces are created
  • main_branch — main branch name (auto-detected if empty)
  • default_template — Zellij layout template (minimal, standard, full, split, review)
  • zellij.use_tabs — tabs vs separate sessions
  • zellij.session_prefix — prefix for session names
  • zellij.panes.main.command — main pane command
  • agent.command — default agent for zjj spawn
  • session.auto_commit / session.commit_prefix — auto-commit behavior
  • hooks.post_create / hooks.pre_remove / hooks.post_merge — lifecycle hooks
  • dashboard.vim_keys — enable hjkl navigation in dashboard
  • recovery.policy — recovery behavior (warn, error, ignore)

24. Completions

CommandPurpose
zjj completions bashGenerate bash completions
zjj completions zshGenerate zsh completions
zjj completions fishGenerate fish completions
zjj completions powershellGenerate PowerShell completions
zjj completions elvishGenerate elvish completions

25. Help

CommandPurpose
zjj helpPrint top-level help
zjj help <command>Print help for specific command

Zellij Layout Templates

minimal

Single pane — lightest weight:

kdl
layout {
    pane {
        command "claude"
        cwd "/path/to/workspace"
        focus true
    }
}

standard (default)

Claude main + beads sidebar + jj log:

code
┌────────────────────────────┬──────────────┐
│                            │  beads (bv)  │
│   main pane (claude) 70%   │     50%      │
│                            ├──────────────┤
│                            │  jj log 50%  │
│                            │ (--limit 20) │
└────────────────────────────┴──────────────┘
kdl
layout {
    pane split_direction="horizontal" {
        pane { command "claude"; cwd "..."; focus true; size "70%" }
        pane split_direction="vertical" {
            pane { command "bv"; cwd "..."; size "50%" }
            pane { command "jj"; args "log" "--limit" "20"; cwd "..."; size "50%" }
        }
    }
}

full

Standard layout + floating pane (80% width, 60% height)

split (NEW in v0.4.0)

Split pane layout for multi-directional work

review (NEW in v0.4.0)

Review-focused layout for code review workflows

Beads Integration

zjj integrates with the beads issue tracker (.beads/issues.jsonl). Bead lifecycle:

code
open → (zjj spawn) → in_progress → (zjj done / agent success) → closed
                           ↓
                    (agent failure) → stays in_progress (retry)
Bead StatusMeaning
openReady for work (required for zjj spawn)
in_progressAgent/workspace actively working
blockedWaiting on dependency
deferredPostponed
closedWork complete (zjj done sets this)

Integration points:

  • zjj spawn <bead-id>: validates bead is open, creates workspace, sets in_progress
  • zjj add -b <bead-id>: associate session with bead
  • zjj done: finds linked bead, sets closed (skip with --no-bead-update)
  • zjj abort: sets bead to abandoned
  • zjj list --bead <id>: filter sessions by bead
  • zjj dashboard: watches .beads/beads.db for real-time updates
  • zjj context: includes beads summary for AI agents

Environment Variables

VariableDescriptionDirection
ZJJ_AGENT_IDAgent identifier for trackingboth
ZJJ_SESSIONCurrent session name (set by zjj)write
ZJJ_BEAD_IDAssociated bead IDboth
ZJJ_WORKSPACEAbsolute path to workspacewrite

JSON Output Envelope

All commands support --json. Responses use a consistent envelope:

json
{
  "$schema": "zjj://schema/<type>/<version>",
  "_schema_version": "1.0",
  "schema_type": "single|array",
  "success": true,
  "data": { ... }
}

On error:

json
{
  "success": false,
  "error": {
    "code": "VALIDATION_ERROR|JJ_COMMAND_ERROR|INVALID_ARGUMENT|...",
    "message": "Human-readable description",
    "exit_code": 1
  }
}

Global Options

Available on ALL commands:

  • --on-success <CMD> - Command to run after successful execution
  • --on-failure <CMD> - Command to run after failed execution
  • --json - Output as JSON

Hooks

Configure hooks to run custom commands at lifecycle events:

bash
# Set a post_create hook (runs after zjj add)
zjj config hooks.post_create '["echo workspace ready"]'

# Set a pre_remove hook (runs before zjj remove)
zjj config hooks.pre_remove '["echo cleaning up"]'

# Set a post_merge hook (runs after zjj done)
zjj config hooks.post_merge '["echo merged to main"]'

Skip hooks on demand: zjj add <name> --no-hooks

Typical Workflows

Feature Development

bash
zjj add feature-auth                # stand up isolated workspace
# ... develop in isolation ...
zjj sync                            # stay current with main
zjj diff feature-auth --stat        # review what changed
zjj done -m "feat: auth system"     # merge back to main

AI Agent Workflow (7-Step)

bash
# 1. Orient
zjj whereami                        # returns 'main' or 'workspace:<name>'

# 2. Register
zjj agents register --id agent-123  # register as agent

# 3. Isolate
zjj work feature-auth -b zjj-abc12  # create workspace + register agent

# 4. Enter
cd ../lewis__workspaces/feature-auth

# 5. Implement
# ... do work ...
zjj agents heartbeat -c "implementing"  # signal liveness

# 6. Heartbeat (periodically)
zjj agents heartbeat

# 7. Complete
zjj done                            # merge to main + cleanup
zjj agents unregister                # unregister agent

Parallel Experiments

bash
zjj add approach-a                  # first approach
zjj add approach-b                  # second approach (independent)
zjj diff approach-a --stat          # compare approach A
zjj diff approach-b --stat          # compare approach B
zjj done                            # merge winner (from its workspace)
zjj abort -w approach-b             # discard loser

Multi-Agent Coordination

bash
# Agent 1 claims session
zjj claim session:feature-x -t 300

# Agent 2 waits for unlock
zjj wait session-unlocked feature-x -t 300

# Agent 1 completes and yields
zjj done
zjj yield session:feature-x

# Agent 2 proceeds
zjj work feature-y

Merge Queue

bash
# Add workspaces to queue for ordered processing
zjj queue --add feature-x --bead zjj-001 --priority 1
zjj queue --add feature-y --bead zjj-002 --priority 2

# Agent processes queue
zjj queue --next                    # get next pending entry
# ... work ...
zjj done

# Check queue status
zjj queue --stats

Session Cleanup

bash
zjj list --all                      # see everything including stale
zjj clean --dry-run                 # preview what would be removed
zjj clean                           # remove stale sessions
zjj doctor                          # health check
zjj doctor --fix                    # auto-fix issues

Anti-Patterns to Avoid

Anti-PatternProblemzjj Solution
Using raw jj workspace addNo session tracking, no Zellij integrationzjj add <name> manages everything
Manually creating Zellij tabsDisconnected from workspace statezjj add creates both together
Forgetting to merge backOrphaned workspaces accumulatezjj done merges + cleans up
Manual cleanup of workspacesEasy to leave stale statezjj clean finds and removes stale sessions
Not syncing before mergingMerge conflicts at the endzjj sync regularly during development
zjj remove -f to discard workLoses work silently, bead status not updatedzjj abort — proper discard
Retrying zjj done in a tight loopHammers merge queue, terrible statezjj sync + zjj retry with backoff
Ignoring exit code 3 from doneSilently lost merge attemptCheck exit code, enter backoff loop
Not checkpointing before risky opsCan't recover if merge goes sidewayszjj checkpoint create before done
Spawning agents without timeoutRunaway processeszjj spawn --timeout <secs>
Not using agent heartbeatsAgent appears stalezjj agents heartbeat periodically
Not using locks for coordinationRace conditions in multi-agentzjj claim / zjj yield

Best Practices

Workspace Discipline

  • One concern per workspace: zjj add names should describe the task
  • Sync frequently: zjj sync before starting each work block
  • Use zjj done not zjj remove: done merges your work
  • Use zjj abort not zjj remove -f: abort is the proper discard
  • zjj whatif done before zjj done: Shows steps, prerequisites, reversibility
  • zjj checkpoint create before zjj done: Safety snapshot
  • Clean up regularly: zjj clean --dry-run then zjj clean

Session Management

  • Use zjj focus to switch between sessions
  • Use zjj status --watch in a side pane for live monitoring
  • Use zjj dashboard for kanban view
  • Use zjj list --all to see completed/failed sessions
  • Name sessions descriptively: name becomes workspace directory and tab name

Agent Spawning

  • Use zjj spawn for AI work: creates isolated workspace, runs agent
  • Use zjj work for unified workflow: workspace + agent registration
  • Use -b for background spawning: don't block terminal
  • Set --no-auto-merge when you want to review output first
  • Set --timeout for long-running agents
  • Send heartbeats: zjj agents heartbeat periodically

Multi-Agent Coordination

  • Use zjj claim / zjj yield: for resource locks
  • Use zjj queue: for ordered merge processing
  • Use zjj wait: for condition-based synchronization
  • Use zjj broadcast: for agent-to-agent messaging

Quality Gates Checklist

Before running zjj done:

  • zjj can-i done returns OK
  • Work is complete and described
  • Synced with main (zjj sync)
  • Tests pass
  • Diff looks correct (zjj diff <name> --stat)
  • zjj whatif done reviewed
  • zjj checkpoint create run

After zjj done:

  • Main branch has merged changes
  • Session removed from zjj list
  • Workspace directory gone from disk
  • If exit code 3: backoff loop was used

Troubleshooting

"Not in a JJ repository"

bash
zjj init                    # initializes both jj and zjj

"Session already exists"

bash
zjj list                    # verify it exists
zjj remove <name> -f        # force remove if stale
zjj add <name>              # recreate

Stale sessions

bash
zjj clean --dry-run         # preview stale sessions
zjj clean                   # remove them

Workspace out of sync

bash
zjj sync <name>             # rebase onto latest main

Dependency issues

bash
zjj doctor                  # diagnose issues
zjj doctor --fix            # auto-fix where possible
zjj introspect              # check dependency versions

Zellij tab not opening

bash
zjj focus <name>            # try to focus the tab
zjj attach <name>           # attach to the session

Merge conflict (exit code 3)

bash
zjj checkpoint create       # safety snapshot
zjj sync                    # re-sync
zjj retry                   # retry the done
# If still failing after 6 retries:
zjj recover --diagnose      # diagnose without fixing

Agent spawn fails

bash
zjj query can-run            # check system readiness
zjj introspect               # verify agent dependency
zjj spawn <bead> --agent-command=<path>  # specify full path

Corrupted state

bash
zjj recover --diagnose       # diagnose issues
zjj integrity validate <ws>  # validate workspace
zjj integrity repair <ws>    # repair workspace
zjj rollback --to <cp> <session>  # rollback to checkpoint

Guidelines

  • When the user asks for workspace isolation, always use zjj add, never raw jj workspace add
  • When the user says "spin up a workspace" or "isolate this work", run zjj add <name>
  • When the user is done with isolated work, guide them to zjj done (not zjj remove)
  • Always suggest zjj sync before zjj done to minimize merge surprises
  • For AI agent workflows, use zjj spawn or zjj work with appropriate flags
  • Use --json flag when integrating zjj into scripts or automation
  • Always check zjj doctor if something seems wrong
  • Remind users that zjj init is required once per repo

Session Completion (Landing the Plane)

CRITICAL: Before ending any work session using this skill, you MUST complete the Landing the Plane workflow.

When to Land

  • After completing work in an isolated workspace
  • Before going AFK
  • When switching contexts
  • At end of work session

Landing Checklist

bash
# 1. File beads for remaining work (NOT gh issues — beads are the single source of truth)
br create "[process] Follow-up: description" --type task --priority 2 --labels "smell:process"

# 2. Verify workspace state
zjj status                    # all sessions accounted for
zjj diff <name> --stat        # review changes

# 3. Sync and complete — if zjj done fails with exit code 3, use exponential backoff
zjj sync                      # rebase onto latest main
zjj done -m "description"     # merge to main + cleanup
# Or if not ready to merge:
jj describe -m "WIP: description"
jj git push --change @ --allow-new

# 4. Verify — sessions AND directories
zjj list                      # no orphaned sessions
zjj clean --dry-run           # no stale sessions
# Verify workspace directories are actually gone from disk:
WORKSPACE_BASE=$(zjj config workspace_dir 2>/dev/null || echo "../lewis__workspaces")
[ -d "$WORKSPACE_BASE" ] && ls "$WORKSPACE_BASE"/  # should be empty or non-existent

# 5. Hand off
# Provide summary of work completed, sessions created/closed, next steps

For detailed workflow, invoke: /land or use the landing-skill


Skill Version: 2.0.0 Last Updated: February 2026 zjj Version Support: 0.4.0 (verified against installed binary at /home/lewis/.local/bin/zjj) Status: Production-Ready Backoff: Exponential backoff on merge conflicts (exit code 3). Uses zjj retry natively. Max 6 retries, 60s cap. Checkpoint before loop. recover on exhaustion. Workspace preserved.