kanbo-cli 0.1.1 → 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -14,6 +14,7 @@
14
14
  - **Status lines and runs.** Every card says what it is doing right now, and every launch of a card is recorded as a run with an attempt number.
15
15
  - **Subtasks, comments, pull request links, sprints** and **column entry rules** (`checklist_complete`, `pull_request_linked`, `ci_green`, `approved`).
16
16
  - **Storage you choose.** A board file in the project (`.kanbo/board.db`), or an external Postgres database such as Supabase shared by a team, with `kanban_person` / `kanban_agent` roles.
17
+ - **MCP alone is enough to start.** `kanbo mcp` sends the board's basic rules as MCP server instructions when a client connects, so an agent needs no instruction file for the basics.
17
18
  - **One-command project setup.** `kanbo init` binds the project, writes an instruction block into `CLAUDE.md` or `AGENTS.md`, and registers the MCP server with Claude Code, Codex or Cursor.
18
19
  - **Board over HTTP.** `kanbo serve` answers a JSON API and serves a board page on `http://127.0.0.1:4318`, loopback-only and token-guarded.
19
20
  - **Machine-readable capabilities.** `kanbo capabilities --json` describes every tool, command, rule and limit for an orchestrator to read.
package/dist/cli.cjs CHANGED
@@ -3083,7 +3083,7 @@ var import_picocolors = /* @__PURE__ */ __toESM((/* @__PURE__ */ __commonJSMin((
3083
3083
  * `package.version`. A build carries it as a literal; running from source
3084
3084
  * (tests, `tsx`) reads the package's own `package.json` instead.
3085
3085
  */
3086
- const KANBO_PACKAGE_VERSION = "0.1.1";
3086
+ const KANBO_PACKAGE_VERSION = "0.1.2";
3087
3087
  /**
3088
3088
  * Every exit code this tool promises, and what it means — the capabilities
3089
3089
  * manifest's `exitCodes` reads this rather than naming the codes again. `0` and
@@ -11178,32 +11178,61 @@ async function migrateCards(store, input) {
11178
11178
  };
11179
11179
  }
11180
11180
  //#endregion
11181
- //#region src/ops/prime.ts
11181
+ //#region src/ops/agent-rules.ts
11182
11182
  /**
11183
- * The rules of this board, as an agent needs to hear them.
11183
+ * The sentences that tell an agent how to work this board, written once.
11184
+ *
11185
+ * Four surfaces say them: the text `kanbo prime` returns (`BOARD_RULES`), the
11186
+ * block `kanbo init` writes into a project's `CLAUDE.md` / `AGENTS.md`, the
11187
+ * `instructions` the `kanbo mcp` server sends when a client connects, and the
11188
+ * `kanbo_card_create` tool's description. Each surface adds its own way of
11189
+ * doing the thing — a command, a tool name — but the rule itself is read from
11190
+ * here, so the four cannot come to say different things.
11191
+ *
11192
+ * No sentence names a tool or a command: the same text reaches an agent holding
11193
+ * MCP tools, one with a command line, and one talking to a server over HTTP.
11194
+ */
11195
+ const MOVE_CARD_RULE = "You move the card between columns yourself, at the moment its real state changes. The board never moves a card for you.";
11196
+ const STATUS_LINE_RULE = "Write a status line at every step, including before and after anything long-running. One sentence, present tense, about what is happening right now.";
11197
+ const WAIT_FOR_PERSON_RULE = "When you need a person, mark the card as waiting for approval and end your turn. You will be told when the answer comes.";
11198
+ const PERSON_ONLY_RULE = "Only a person approves a card, and only a person takes one out of waiting. Never do either yourself.";
11199
+ const EXECUTION_MODE_RULE = "Each card says where it runs: `worktree` means a separate copy of the project, `main` means the project folder itself. Work in the mode the card names.";
11200
+ /** When to split a card at all — said on its own where the surface names the parent its own way. */
11201
+ const SUBTASK_WHEN_SENTENCE = "Create subtasks only when the person asks for them, or when a task has parts that can be done and checked separately (different stages, owners or pull requests); do not split small work you will finish in one go.";
11202
+ /** How to split one, with the way this surface names the parent card. */
11203
+ function subtaskSplitSentence(parentReference) {
11204
+ return `When you do split a card, make the parts subtasks of it (${parentReference}), not separate top-level cards.`;
11205
+ }
11206
+ const SUBTASK_RULE = `${SUBTASK_WHEN_SENTENCE} ${subtaskSplitSentence("the parent card's id")}`;
11207
+ const PULL_REQUEST_RULE = "Opened a pull request? Link it to the card. Its state and CI checks then reach the card as comments on their own — nothing else tells the board a pull request exists.";
11208
+ const OWN_SESSION_RULE = "Started the work yourself, not launched by an app that tracks the run for you? Say so when you start the run — `claude:<session id>` from Claude Code, `codex:<session id>` from Codex (the session id Codex prints) — so your own log of it can be found later.";
11209
+ /** Said by the `kanbo init` block and the MCP instructions, which name the comment command or tool beside it. */
11210
+ const COMMENT_RULE = "Findings, results, decisions and questions go on the card as comments.";
11211
+ /**
11212
+ * The rules of this board, as `kanbo prime` says them under its column list.
11184
11213
  *
11185
11214
  * They are about the board and nothing else. The board does not hand out a role, a
11186
11215
  * method or a pipeline — that belongs to the instructions the person wrote for
11187
11216
  * their own agent — so the list stops at what the board itself guarantees and
11188
- * expects. No tool is named either: the same text reaches an agent holding MCP
11189
- * tools, one with a command line, and one talking to a server over HTTP, and each
11190
- * of them already knows what it is holding.
11217
+ * expects.
11191
11218
  *
11192
- * Exported because it is also the source `buildCapabilitiesManifest` reads its
11193
- * `rules` from — one list, read by the prompt an agent sees and by the manifest
11194
- * an orchestrator reads about the board.
11219
+ * Also the source `buildCapabilitiesManifest` reads its `rules` from — one list,
11220
+ * read by the prompt an agent sees and by the manifest an orchestrator reads
11221
+ * about the board.
11195
11222
  */
11196
11223
  const BOARD_RULES = [
11197
- "You move the card between columns yourself, at the moment its real state changes. The board never moves a card for you.",
11198
- "Write a status line at every step, including before and after anything long-running. One sentence, present tense, about what is happening right now.",
11199
- "When you need a person, mark the card as waiting for approval and end your turn. You will be told when the answer comes.",
11200
- "Only a person approves a card, and only a person takes one out of waiting. Never do either yourself.",
11201
- "Each card says where it runs: `worktree` means a separate copy of the project, `main` means the project folder itself. Work in the mode the card names.",
11202
- "Create subtasks only when the person asks for them, or when a task has parts that can be done and checked separately (different stages, owners or pull requests); do not split small work you will finish in one go. When you do split a card, make the parts subtasks of it (the parent card's id), not separate top-level cards.",
11203
- "Opened a pull request? Link it to the card. Its state and CI checks then reach the card as comments on their own — nothing else tells the board a pull request exists.",
11204
- "Started the work yourself, not launched by an app that tracks the run for you? Say so when you start the run — `claude:<session id>` from Claude Code, `codex:<session id>` from Codex (the session id Codex prints) — so your own log of it can be found later.",
11224
+ MOVE_CARD_RULE,
11225
+ STATUS_LINE_RULE,
11226
+ WAIT_FOR_PERSON_RULE,
11227
+ PERSON_ONLY_RULE,
11228
+ EXECUTION_MODE_RULE,
11229
+ SUBTASK_RULE,
11230
+ PULL_REQUEST_RULE,
11231
+ OWN_SESSION_RULE,
11205
11232
  "Read the column descriptions above before moving a card, and do all of this through the board tools or commands you have — a statement in your reply changes nothing."
11206
11233
  ];
11234
+ //#endregion
11235
+ //#region src/ops/prime.ts
11207
11236
  /**
11208
11237
  * What the board tells an agent about itself: the columns it has, what each one
11209
11238
  * means, and how a card is expected to travel across them.
@@ -23117,7 +23146,7 @@ const SUBTASK_SENTENCE = "To create a subtask (sub-card) under another card, pas
23117
23146
  const cardCreateTool = defineKanboTool({
23118
23147
  name: "kanbo_card_create",
23119
23148
  title: "Create a card",
23120
- description: `Put a new card on this board. ${SUBTASK_SENTENCE} Create subtasks only when the person asks for them, or when a task has parts that can be done and checked separately (different stages, owners or pull requests); do not split small work you will finish in one go. When you do split a card, make the parts subtasks of it (pass \`parent\`), not separate top-level cards.`,
23149
+ description: `Put a new card on this board. ${SUBTASK_SENTENCE} ${SUBTASK_WHEN_SENTENCE} ${subtaskSplitSentence("pass `parent`")}`,
23121
23150
  inputSchema: {
23122
23151
  title: string().optional().describe("What the card is called. Leave it out and the card is titled with its own key; the description then says what the task is."),
23123
23152
  description: string().optional().describe("What the card is about, spelled out for whoever picks it up."),
@@ -24181,7 +24210,8 @@ const CODEX_TABLE_PATTERN = new RegExp(String.raw`^\s*\[\s*mcp_servers\s*\.\s*(?
24181
24210
  *
24182
24211
  * It says what to run and when, and nothing about how to do the work: the
24183
24212
  * method is the person's own instructions to their agent, and the board only
24184
- * insists on the part that keeps the card honest.
24213
+ * insists on the part that keeps the card honest. The rules are the sentences
24214
+ * `ops/agent-rules.ts` holds for every surface, with the command beside each.
24185
24215
  */
24186
24216
  const INSTRUCTION_BLOCK = [
24187
24217
  INSTRUCTION_START,
@@ -24190,12 +24220,13 @@ const INSTRUCTION_BLOCK = [
24190
24220
  "Work on this project is tracked on a kanbo board. Before starting a task run `kanbo prime` — it prints the board's columns and what each one means.",
24191
24221
  "",
24192
24222
  "- Take a card from `kanbo ready`.",
24193
- "- Move the card yourself (`kanbo card move <id> <column>`) — a card in the wrong column is a lie.",
24194
- "- Write a status line at every step (`kanbo card status-line <id> --text \"...\"`).",
24195
- "- Create subtasks only when the person asks for them, or when a task has parts that can be done and checked separately (different stages, owners or pull requests); do not split small work you will finish in one go. When you do split a card, make the parts subtasks of it (the parent card's id), not separate top-level cards. (`kanbo card create --description \"...\" --parent <id>`).",
24196
- "- Findings, decisions and questions go on the card (`kanbo card comment <id> --content \"...\"`).",
24197
- "- When you need a person, run `kanbo card wait-approval <id>` and end your turn. Never approve your own work, and never take a card out of a column where it is waiting for a person.",
24198
- "- Started the work yourself, not launched by an app that tracks the run? Pass your own session to `kanbo run start --session` — `claude:<session id>` from Claude Code, `codex:<session id>` from Codex (the session id Codex prints).",
24223
+ `- ${MOVE_CARD_RULE} (\`kanbo card move <id> <column>\`)`,
24224
+ `- ${STATUS_LINE_RULE} (\`kanbo card status-line <id> --text "..."\`)`,
24225
+ `- ${SUBTASK_RULE} (\`kanbo card create --description "..." --parent <id>\`)`,
24226
+ `- ${COMMENT_RULE} (\`kanbo card comment <id> --content "..."\`)`,
24227
+ `- ${WAIT_FOR_PERSON_RULE} (\`kanbo card wait-approval <id>\`)`,
24228
+ `- ${PERSON_ONLY_RULE}`,
24229
+ `- ${OWN_SESSION_RULE} (\`kanbo run start <id> --agent <name> --session <ref>\`)`,
24199
24230
  "- Run `kanbo capabilities` for the full list of tools, commands and rules.",
24200
24231
  INSTRUCTION_END
24201
24232
  ].join("\n");
@@ -40719,6 +40750,36 @@ function registerKanboCapabilitiesResources(server) {
40719
40750
  }] }));
40720
40751
  }
40721
40752
  //#endregion
40753
+ //#region src/mcp/instructions.ts
40754
+ /** A tool name as the instructions print it — typed, so a renamed tool fails the build here. */
40755
+ function tool(name) {
40756
+ return `\`${name}\``;
40757
+ }
40758
+ /**
40759
+ * What `kanbo mcp` tells a client when it connects — the `instructions` of the
40760
+ * MCP initialize result, which a client hands its model before any tool is
40761
+ * called. An agent with nothing but this server connected learns from it how
40762
+ * to work the board, with no instruction file in the project.
40763
+ *
40764
+ * Static on purpose: it is sent before any board is resolved, so it says
40765
+ * nothing about columns — `kanbo_prime` returns those. The rules are the
40766
+ * sentences `ops/agent-rules.ts` holds for every surface, with the tool beside
40767
+ * each; the full manifest stays a resource.
40768
+ */
40769
+ const KANBO_MCP_INSTRUCTIONS = [
40770
+ "kanbo is a kanban board shared by people and agents; these tools read and change its cards.",
40771
+ "",
40772
+ `- At the start of a session call ${tool("kanbo_prime")} — it returns this board's columns and what each one means.`,
40773
+ `- Take work from ${tool("kanbo_ready")}.`,
40774
+ `- ${MOVE_CARD_RULE} (${tool("kanbo_card_move")})`,
40775
+ `- ${STATUS_LINE_RULE} (${tool("kanbo_status_line")})`,
40776
+ `- ${COMMENT_RULE} (${tool("kanbo_card_comment")})`,
40777
+ `- ${SUBTASK_RULE} (${tool("kanbo_card_create")} with \`parent\`)`,
40778
+ `- ${WAIT_FOR_PERSON_RULE} (${tool("kanbo_wait_approval")})`,
40779
+ `- ${PERSON_ONLY_RULE}`,
40780
+ `- Every tool, rule and canonical string: the resource \`${KANBO_CAPABILITIES_MARKDOWN_RESOURCE_URI}\`.`
40781
+ ].join("\n");
40782
+ //#endregion
40722
40783
  //#region src/mcp/server.ts
40723
40784
  /** The name a client sees this server under. */
40724
40785
  const KANBO_MCP_SERVER_NAME = "kanbo";
@@ -40745,12 +40806,15 @@ function registerKanboTools(server, transport, options) {
40745
40806
  * function: it documents its capabilities its own way, and adding a second
40746
40807
  * `kanbo://` resource namespace to an inventory that is not only the board's
40747
40808
  * is a decision for that server to make, not this one.
40809
+ *
40810
+ * For the same reason it alone sends `KANBO_MCP_INSTRUCTIONS` in the initialize
40811
+ * result: the instructions of a server that is only the board.
40748
40812
  */
40749
40813
  function createKanboMcpServer(transport, options) {
40750
40814
  const server = new McpServer({
40751
40815
  name: KANBO_MCP_SERVER_NAME,
40752
40816
  version: KANBO_MCP_SERVER_VERSION
40753
- });
40817
+ }, { instructions: KANBO_MCP_INSTRUCTIONS });
40754
40818
  registerKanboTools(server, transport, options);
40755
40819
  registerKanboCapabilitiesResources(server);
40756
40820
  return server;