The pb command

pb reads and edits a Project Board file (.pb) from a shell. It exists for three users:

1. Getting the command

The extension installs it for you. Every integrated terminal of VS Code has pb on its PATH, and so has every shell Claude Code starts from one. Outside VS Code, call the same program directly:

node <extension folder>/out/cli.js <command> …

<extension folder> is the folder the extension is installed in, one of the folders in ~/.vscode/extensions/. The Assistant section of the board’s settings page shows the exact command of your installation.

2. Working together with the editor

When a board is open in VS Code, pb does not touch the file. It talks to the editor that has the board open, and the editor makes the change:

When no editor has the board open, pb edits the file itself. A lock file next to the board (.<name>.pb.lock) lets several commands run at the same time without overwriting each other, and the file is replaced in one step, so nobody ever reads half a board.

pb where tells which of the two is the case. --no-live forces the file even when an editor has the board open; the editor then sees a file that changed on disk, as with any other outside edit.

The editor and the command find each other through a folder only your user can read ($XDG_RUNTIME_DIR/project-board, or project-board-<uid> in the temporary folder; PB_BRIDGE_DIR overrides it). Each running editor leaves a small file there with the address of a local socket and a random token. Nothing listens on the network.

3. Which board, and who signs

The board is, in this order: the .pb file named right after the command, --file <path>, the PB_FILE environment variable, or the only .pb file in the current folder.

Edits are signed, in this order: --as <name>, the PB_ACTOR environment variable, Claude when the command runs inside Claude Code (which sets CLAUDECODE in its shells), or your git name.

4. Commands

Read
  pb show                      project, milestones with progress, workflow columns, labels
  pb issues                    open issues; --all, --state closed, --milestone "0.4", --label bug,
                               --assignee ada, --kind requirement, --column "In review", --search text, --limit 20
  pb issue 12                  one issue in full, with links and every comment
  pb milestones
  pb labels
  pb log --limit 30            who did what, newest first

Change
  pb add-issue "Title" [--body text | --body-file path|-] [--milestone title] [--label name]…
               [--assignee name] [--kind task|requirement|heading] [--column name] [--parent number]
               [--start date] [--due date]
  pb edit 12 [--title text] [--body text | --body-file path|-] [--milestone title|none]
             [--label name]… [--add-label name]… [--remove-label name]… [--assignee name] [--kind kind]
             [--start date|none] [--due date|none]     planned dates for the Gantt chart
  pb comment 12 "Text"         or --body text, or --body-file path|-
  pb close 12 13 [--comment text]
  pb reopen 12 [--comment text]
  pb move 12 "In progress"     a column name, or todo / doing / done; [--milestone title|none]
  pb link 12 depends 7         satisfies, derives, verifies, refines, depends,
                               conflicts, relates
  pb add-milestone "Version 1.0" [--body text] [--start date] [--due date]
  pb edit-milestone "1.0" [--title text] [--body text] [--start date|none] [--due date|none]
  pb close-milestone "1.0"
  pb reopen-milestone "1.0"
  pb add-label "needs design" [--color "#8b5cf6"] [--body text]
  pb apply --actions file|-    many changes in one step (see below)
  pb apply --events file|-     raw events of the file format, without "seq"

File
  pb init [name.pb] [--name "Project"]   a new, empty board
  pb validate                  is this a board this version reads? exit code 1 when not
  pb upgrade                   rewrite a board of an older format in the current one
  pb consolidate               fold the event list into the tree
  pb where                     which board, who signs, is an editor involved

In and out
  pb report --out folder [--format html-book] [--title text] [--milestone title]
            [--no-closed] [--no-comments] [--no-activity] [--no-requirements]
  pb export --format csv [--out file or folder] [--no-closed] [--no-comments]
  pb import --from file|- [--format id] [--dry-run] [--no-closed] [--no-comments]
  pb formats                   the report, export and import formats
  pb skill [--install] [--dir folder]    the Claude Code skill for boards

An issue is named by its number (12 or #12), a milestone by its title or a unique part of it ("0.4" finds “Version 0.4 - Presentation Changes”), a label by its name. --body-file - reads standard input, which is the safe way to pass several lines of Markdown:

pb comment 12 --body-file - <<'EOF'
Fixed in `abc1234`.

- the parser accepts empty files
- added a test
EOF

Every command takes --json and then prints one JSON document: the data for reading commands, and { ok, file, live, saved, dirty, outcomes: [{ ok, error?, result? }] } for changing ones.

Exit codes: 0 done, 1 the board refused something or the file is not usable, 2 the command was not understood. With several steps in one command (pb close 7 8 9), a refused step is reported and the others still run.

5. Many changes at once

pb apply --actions takes a JSON list of the same actions the editor itself uses:

[
  { "action": "issue.create", "ref": "parser",
    "payload": { "title": "Write the parser", "labels": ["feature"], "milestone": "0.4" } },
  { "action": "issue.create", "payload": { "title": "Test the parser", "parent": "$parser" } },
  { "action": "comment.add", "payload": { "issue": 12, "body": "Split into two issues." } },
  { "action": "issue.close", "payload": { "issue": 12 } }
]

"ref" names what an action creates and "$name" uses it later in the list. The actions most useful here are issue.create, issue.update (with addLabels and removeLabels), issue.close, issue.reopen, issue.move, comment.add, link.add, milestone.create, milestone.update, milestone.close and label.create; ai-agents.md describes them.

6. Claude Code

Two things make Claude good at this:

  1. The skill. “Install the Claude skill” on the settings page (or pb skill --install in the project folder) writes .claude/skills/project-board/SKILL.md. It tells Claude that boards exist, how to call pb, and how to behave on a board: read the comments first, comment on what it did, close only what is done, open an issue instead of fixing unrelated things silently.
  2. The live editing described above. Run Claude Code in the integrated terminal, keep the board open beside it, and watch the issues move.

Ask Claude things like “work on issue 12 and record what you did on the board” or “split the 0.5 milestone into issues”.

The page has its own assistant too (the sparkle button and “Ask the assistant” on an issue). That one answers inside the editor and proposes changes you accept or discard; pb is for Claude working on its own in the terminal.

7. Limits