diff --git a/.claude-plugin/plugin.json b/.claude-plugin/plugin.json index b403d5f..d611aa6 100644 --- a/.claude-plugin/plugin.json +++ b/.claude-plugin/plugin.json @@ -1,5 +1,5 @@ { - "name": "biff", + "name": "biff-dev", "description": "UNIX-style team communication for Claude Code: /who, /finger, /plan, /write, /read, /mesg, /tty, /last, /wall, /talk", "version": "1.10.0", "author": { diff --git a/README.md b/README.md index bbd4341..065192e 100644 --- a/README.md +++ b/README.md @@ -17,7 +17,7 @@ Named after the Berkeley dog whose 1980 mail notification program was part of th ## Quick Start ```bash -curl -fsSL https://raw.githubusercontent.com/punt-labs/biff/cbca365/install.sh | sh +curl -fsSL https://raw.githubusercontent.com/punt-labs/biff/677d77a/install.sh | sh ``` Restart Claude Code twice. Type `/who` to see your team. @@ -37,7 +37,7 @@ biff doctor Verify before running ```bash -curl -fsSL https://raw.githubusercontent.com/punt-labs/biff/cbca365/install.sh -o install.sh +curl -fsSL https://raw.githubusercontent.com/punt-labs/biff/677d77a/install.sh -o install.sh shasum -a 256 install.sh cat install.sh sh install.sh diff --git a/commands/biff-dev.md b/commands/biff-dev.md new file mode 100644 index 0000000..f77970e --- /dev/null +++ b/commands/biff-dev.md @@ -0,0 +1,16 @@ +--- +description: Enable or disable biff for this repo +argument-hint: "y | n" +allowed-tools: ["ToolSearch", "mcp__plugin_biff-dev_tty__biff"] +--- + + +## Input + +Arguments: $ARGUMENTS + +Parse the argument as `y` or `n`. Map `y` to `enabled=true`, `n` to `enabled=false`. + +## Task + +Call `mcp__plugin_biff-dev_tty__biff` with `enabled` set to the parsed value. The result is already formatted by a PostToolUse hook and displayed above. Do not repeat or reformat the data. Do not send any text after the tool call. diff --git a/commands/finger-dev.md b/commands/finger-dev.md new file mode 100644 index 0000000..48f19e6 --- /dev/null +++ b/commands/finger-dev.md @@ -0,0 +1,16 @@ +--- +description: Check what a teammate is working on and their availability +argument-hint: "@user" +allowed-tools: ["ToolSearch", "mcp__plugin_biff-dev_tty__finger"] +--- + + +## Input + +Arguments: $ARGUMENTS + +Parse the username from arguments, stripping any leading `@` if present. + +## Task + +Call `mcp__plugin_biff-dev_tty__finger` with `user` set to the parsed username. Emit the tool output exactly as returned — character for character, including the leading ▶ unicode character. Do not reformat, add commentary, wrap in code fences, convert to markdown tables, or add boxes around the output. diff --git a/commands/last-dev.md b/commands/last-dev.md new file mode 100644 index 0000000..96346f6 --- /dev/null +++ b/commands/last-dev.md @@ -0,0 +1,12 @@ +--- +description: Show session login/logout history +argument-hint: "[@user] [count]" +allowed-tools: ["ToolSearch", "mcp__plugin_biff-dev_tty__last"] +--- + + +Call `mcp__plugin_biff-dev_tty__last` with optional `user` (e.g. `@kai`) and `count` (default 25) arguments. + +If the result says "No session history.", say "No session history available." + +Otherwise, emit the tool output exactly as returned — character for character, including the leading ▶ unicode character. Do not reformat, add commentary, wrap in code fences, convert to markdown tables, or add boxes around the output. diff --git a/commands/mesg-dev.md b/commands/mesg-dev.md new file mode 100644 index 0000000..a12aeee --- /dev/null +++ b/commands/mesg-dev.md @@ -0,0 +1,16 @@ +--- +description: Control message reception +argument-hint: "y | n" +allowed-tools: ["ToolSearch", "mcp__plugin_biff-dev_tty__mesg"] +--- + + +## Input + +Arguments: $ARGUMENTS + +Parse the argument as `y` or `n`. Map `y` to `enabled=true`, `n` to `enabled=false`. + +## Task + +Call `mcp__plugin_biff-dev_tty__mesg` with `enabled` set to the parsed value. The result is already formatted by a PostToolUse hook and displayed above. Do not repeat or reformat the data. Do not send any text after the tool call. diff --git a/commands/plan-dev.md b/commands/plan-dev.md new file mode 100644 index 0000000..3d6295d --- /dev/null +++ b/commands/plan-dev.md @@ -0,0 +1,14 @@ +--- +description: Set what you're currently working on (visible to teammates) +argument-hint: "" +allowed-tools: ["ToolSearch", "mcp__plugin_biff-dev_tty__plan"] +--- + + +## Input + +Arguments: $ARGUMENTS + +## Task + +Call `mcp__plugin_biff-dev_tty__plan` with `message` set to the full arguments string. The result is already formatted by a PostToolUse hook and displayed above. Do not repeat or reformat the data. Do not send any text after the tool call. diff --git a/commands/poll-dev.md b/commands/poll-dev.md new file mode 100644 index 0000000..e1ab7d8 --- /dev/null +++ b/commands/poll-dev.md @@ -0,0 +1,30 @@ +--- +description: Set the background polling interval +argument-hint: "{N}s | {N}m | n" +allowed-tools: ["ToolSearch", "mcp__plugin_biff-dev_tty__set_poll_interval", "mcp__plugin_biff-dev_tty__get_poll_status", "CronCreate", "CronList", "CronDelete"] +--- + + +## Input + +Arguments: $ARGUMENTS + +If no argument provided, call `mcp__plugin_biff-dev_tty__get_poll_status` and report the result. Stop. + +Otherwise parse the argument as an interval (`{N}s` or `{N}m`, e.g. `2s`, `30s`, `5m`) or `n` (disable). Sub-minute intervals set the server-side tick rate; the durable cron fires at 1-minute minimum (cron granularity limit). + +## Task + +1. Call `mcp__plugin_biff-dev_tty__set_poll_interval` with `interval` set to the parsed value. +2. If the interval is `n` (disable): + - Call `CronList` and find any job whose `prompt` field exactly matches `/biff-dev:read-dev`. + - If found, call `CronDelete` with that job's `id` to remove the polling cron. +3. If the interval is NOT `n`: + - Call `CronList` and check if any job has a `prompt` field that exactly matches `/biff-dev:read-dev`. + - If an existing `/biff-dev:read-dev` cron exists, call `CronDelete` on it first. + - Call `CronCreate` with: + - `cron`: convert the interval to a cron expression (e.g. `2s` -> `*/1 * * * *`, `5s` -> `*/1 * * * *`, `1m` -> `*/1 * * * *`, `2m` -> `*/2 * * * *`, `5m` -> `*/5 * * * *`). For intervals under 1 minute, use `*/1 * * * *` (cron minimum is 1 minute). + - `prompt`: `/biff-dev:read-dev` + - `recurring`: true + - `durable`: true +4. Do not mention the cron setup or send any other text to the user beyond the tool result. diff --git a/commands/read-dev.md b/commands/read-dev.md new file mode 100644 index 0000000..08ee5b2 --- /dev/null +++ b/commands/read-dev.md @@ -0,0 +1,11 @@ +--- +description: Check your inbox for new messages +allowed-tools: ["ToolSearch", "mcp__plugin_biff-dev_tty__read_messages"] +--- + + +Call `mcp__plugin_biff-dev_tty__read_messages` with no arguments. + +If the result says "No new messages.", do not emit any text. + +Otherwise, emit the tool output exactly as returned — character for character, including the leading ▶ unicode character. Do not reformat, add commentary, wrap in code fences, convert to markdown tables, or add boxes around the output. diff --git a/commands/talk-dev.md b/commands/talk-dev.md new file mode 100644 index 0000000..213c7d9 --- /dev/null +++ b/commands/talk-dev.md @@ -0,0 +1,28 @@ +--- +description: Start a real-time conversation with a teammate or agent +argument-hint: "@user [message]" +allowed-tools: ["ToolSearch", "mcp__plugin_biff-dev_tty__talk", "mcp__plugin_biff-dev_tty__talk_end", "mcp__plugin_biff-dev_tty__write"] +--- + + +## Input + +Arguments: $ARGUMENTS + +Parse as: first token is the recipient username (strip leading `@` if present), remaining tokens are the opening message (optional). + +Examples: + +- `@kai` → `to="kai"` +- `@kai hey, got a minute?` → `to="kai"`, `message="hey, got a minute?"` + +## Task + +1. Call `mcp__plugin_biff-dev_tty__talk` with the parsed values. +2. Incoming messages from the partner appear on the status bar automatically (0-2s). No need to poll or call talk_listen. +3. When the user wants to reply, send with `mcp__plugin_biff-dev_tty__write` to the same user. +4. When the user says to stop, call `mcp__plugin_biff-dev_tty__talk_end`. + +If `$ARGUMENTS` is "end", call `mcp__plugin_biff-dev_tty__talk_end` directly. + +Do not repeat or reformat tool output — it is already formatted by hooks. diff --git a/commands/tty-dev.md b/commands/tty-dev.md new file mode 100644 index 0000000..f6539a5 --- /dev/null +++ b/commands/tty-dev.md @@ -0,0 +1,14 @@ +--- +description: Name the current session (visible in /who and /finger) +argument-hint: "[name]" +allowed-tools: ["ToolSearch", "mcp__plugin_biff-dev_tty__tty"] +--- + + +## Input + +Arguments: $ARGUMENTS + +## Task + +Call `mcp__plugin_biff-dev_tty__tty`. If arguments were provided, pass them as `name`. If no arguments, call with no arguments to auto-assign the next ttyN. The result is already formatted by a PostToolUse hook and displayed above. Do not repeat or reformat the data. Do not send any text after the tool call. diff --git a/commands/wall-dev.md b/commands/wall-dev.md new file mode 100644 index 0000000..0a8d8a5 --- /dev/null +++ b/commands/wall-dev.md @@ -0,0 +1,29 @@ +--- +description: Broadcast a message to all teammates +argument-hint: '"message" [duration] | clear' +allowed-tools: ["ToolSearch", "mcp__plugin_biff-dev_tty__wall"] +--- + + +## Input + +Arguments: $ARGUMENTS + +Parse as one of three modes: + +1. **Clear**: if arguments are exactly `clear` → call with `clear=True` +2. **Post with duration**: if the last token matches a duration pattern (`30m`, `2h`, `1d`, `3d`), it is the duration and everything before it is the message → `message="...", duration="2h"` +3. **Post with default**: otherwise the entire argument string is the message → `message="..."` + +If no arguments are provided, call with no parameters (shows current wall). + +Examples: + +- `release freeze — do not push to main` → `message="release freeze — do not push to main"` +- `deploy window open 2h` → `message="deploy window open"`, `duration="2h"` +- `clear` → `clear=true` +- (empty) → no parameters + +## Task + +Call `mcp__plugin_biff-dev_tty__wall` with the parsed values. The result is already formatted by a PostToolUse hook and displayed above. Do not repeat or reformat the data. Do not send any text after the tool call. diff --git a/commands/who-dev.md b/commands/who-dev.md new file mode 100644 index 0000000..0f2fa96 --- /dev/null +++ b/commands/who-dev.md @@ -0,0 +1,11 @@ +--- +description: List active team members and what they're working on +allowed-tools: ["ToolSearch", "mcp__plugin_biff-dev_tty__who"] +--- + + +Call `mcp__plugin_biff-dev_tty__who` with no arguments. + +If the result says "No sessions.", do not emit any text. + +Otherwise, emit the tool output exactly as returned — character for character, including the leading ▶ unicode character. Do not reformat, add commentary, wrap in code fences, convert to markdown tables, or add boxes around the output. diff --git a/commands/write-dev.md b/commands/write-dev.md new file mode 100644 index 0000000..1e8d5b7 --- /dev/null +++ b/commands/write-dev.md @@ -0,0 +1,30 @@ +--- +description: Send a message to a teammate +argument-hint: "@user " +allowed-tools: ["ToolSearch", "mcp__plugin_biff-dev_tty__write", "CronCreate", "CronList"] +--- + + +## Input + +Arguments: $ARGUMENTS + +Parse as: first token is the recipient username (strip leading `@` if present), remaining tokens are the message body. + +Example: `@kai hey, ready for code review?` → `to="kai"`, `message="hey, ready for code review?"` + +## Task + +Call `mcp__plugin_biff-dev_tty__write` with `to` and `message` set to the parsed values. The result is already formatted by a PostToolUse hook and displayed above. Do not repeat or reformat the data. + +## Auto-poll for response + +After sending the message, ensure a polling loop exists to catch replies: + +1. Call `CronList` and check if any listed job has a `prompt` field that exactly matches `/biff-dev:read-dev`. +2. If no existing `/biff-dev:read-dev` cron, call `CronCreate` with: + - `cron`: `*/5 * * * *` + - `prompt`: `/biff-dev:read-dev` + - `recurring`: true + - `durable`: true +3. Do not mention the cron setup or send any other text to the user.