kanbot 0.5.0 → 0.5.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 +7 -7
- package/package.json +1 -1
- package/src/cli.ts +7 -0
- package/src/commands/doctor.ts +32 -1
- package/src/commands/init.ts +2 -1
- package/src/known-hashes.json +3 -1
- package/src/templates.ts +63 -0
- package/templates/.agents/skills/kanbot-guide/SKILL.md +18 -17
package/README.md
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
# kanbot
|
|
5
5
|
|
|
6
6
|
Run an autonomous dev team from a GitHub Project board. You define, specify and prioritize work while Claude or Codex agents work as your team.
|
|
7
|
-
|
|
7
|
+
It runs on your Claude or Codex subscription, not API keys. Agents work on their own, and you steer them by commenting.
|
|
8
8
|
|
|
9
9
|
```mermaid
|
|
10
10
|
flowchart LR
|
|
@@ -26,11 +26,11 @@ Full docs: [docs/](./docs/00-index.md). Demo video: [docs/assets/demo.mp4](./doc
|
|
|
26
26
|
| **Ready** | Moving a card here approves the plan. Cards are picked top-down. |
|
|
27
27
|
| **In Progress** | An agent implements it in its own worktree and opens a PR. |
|
|
28
28
|
| **Review** | Two agent reviews, with fixes. Then you're notified. Comment on the PR and an agent addresses it. CI failures and merge conflicts are fixed too. |
|
|
29
|
-
| **Done** | You merge, or approve and kanbot merges ([`merge.onApproval`](./docs/
|
|
29
|
+
| **Done** | You merge, or approve and kanbot merges ([`merge.onApproval`](./docs/12-identity.md#merge-on-approval)). |
|
|
30
30
|
|
|
31
31
|
A Bun daemon polls the board and runs one `claude -p` / `codex exec` process per job. GitHub is the only state, so you can restart it any time. Agents never get a GitHub token; the daemon makes every comment, push and PR. Only collaborators with write access can steer agents.
|
|
32
32
|
|
|
33
|
-
kanbot talks as you by default. Run `kanbot app create` to have it talk as its own bot instead, so you can tell its messages apart and approve its PRs. Commits stay yours. With `merge.onApproval`, approving a PR merges it. [More](./docs/
|
|
33
|
+
kanbot talks as you by default. Run `kanbot app create` to have it talk as its own bot instead, so you can tell its messages apart and approve its PRs. Commits stay yours. With `merge.onApproval`, approving a PR merges it. [More](./docs/12-identity.md)
|
|
34
34
|
|
|
35
35
|
## Setup
|
|
36
36
|
|
|
@@ -64,19 +64,19 @@ For a guided setup, run `bunx kanbot skills install` and ask your agent "help me
|
|
|
64
64
|
|
|
65
65
|
- **Capture ideas by chatting.** Ask your agent to file an idea; the `kanbot-idea` skill shapes it and puts it in Ideas. [More](./docs/03-capturing-ideas.md)
|
|
66
66
|
- **Your own PRs.** Label a PR `kanbot-review` for agent review without a card. Commits to `main` that break kanbot PRs get merged in and fixed. [More](./docs/04-outside-the-board.md)
|
|
67
|
-
- **Project memory.** Corrections you give on PRs become facts agents read on every job. [More](./docs/
|
|
68
|
-
- **Copilot review.** Optionally add GitHub Copilot as a cloud reviewer. [More](./docs/
|
|
67
|
+
- **Project memory.** Corrections you give on PRs become facts agents read on every job. [More](./docs/09-project-memory.md)
|
|
68
|
+
- **Copilot review.** Optionally add GitHub Copilot as a cloud reviewer. [More](./docs/13-copilot-review.md)
|
|
69
69
|
|
|
70
70
|
## Customizing
|
|
71
71
|
|
|
72
72
|
- `.kanbot/config.yml`: concurrency, timeouts, notifications, column names.
|
|
73
73
|
- `.kanbot/agents/*.md`: agent definitions. Run `kanbot sync` after editing; don't edit the generated `.claude/` or `.codex/` files.
|
|
74
|
-
- `.agents/skills/`: skills shared by agents. Fill in `project-conventions` first.
|
|
74
|
+
- `.agents/skills/`: skills shared by agents. Fill in [`project-conventions`](./docs/08-project-conventions.md) first.
|
|
75
75
|
- `capabilities` in config: your own skills and agents for building, testing and reviewing. [More](./docs/05-capabilities.md)
|
|
76
76
|
|
|
77
77
|
## Upgrading
|
|
78
78
|
|
|
79
|
-
`bunx kanbot@latest upgrade` updates agents and skills you haven't edited. For edited ones, it writes the new version next to yours as `<file>.kanbot-new` to merge. See [Upgrading](./docs/
|
|
79
|
+
`bunx kanbot@latest upgrade` updates agents and skills you haven't edited. For edited ones, it writes the new version next to yours as `<file>.kanbot-new` to merge. See [Upgrading](./docs/14-upgrading.md).
|
|
80
80
|
|
|
81
81
|
## Shell completion
|
|
82
82
|
|
package/package.json
CHANGED
package/src/cli.ts
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
#!/usr/bin/env bun
|
|
2
2
|
import { runCommand, runMain } from "citty";
|
|
3
3
|
import { formatError } from "./errors.ts";
|
|
4
|
+
import { log } from "./log.ts";
|
|
4
5
|
import { main } from "./main.ts";
|
|
6
|
+
import { versionNotice } from "./templates.ts";
|
|
5
7
|
|
|
6
8
|
const args = process.argv.slice(2);
|
|
7
9
|
const usage =
|
|
@@ -13,6 +15,11 @@ const usage =
|
|
|
13
15
|
if (usage) {
|
|
14
16
|
await runMain(main);
|
|
15
17
|
} else {
|
|
18
|
+
// These set the version themselves, report it, or print shell code.
|
|
19
|
+
if (!["init", "upgrade", "doctor", "completion"].includes(args[0] ?? "")) {
|
|
20
|
+
const notice = await versionNotice(process.cwd());
|
|
21
|
+
if (notice) log.warn(notice);
|
|
22
|
+
}
|
|
16
23
|
try {
|
|
17
24
|
await runCommand(main, { rawArgs: args });
|
|
18
25
|
} catch (e) {
|
package/src/commands/doctor.ts
CHANGED
|
@@ -21,7 +21,13 @@ import {
|
|
|
21
21
|
type McpServer,
|
|
22
22
|
readMcpServers,
|
|
23
23
|
} from "../providers/mcp.ts";
|
|
24
|
-
import {
|
|
24
|
+
import {
|
|
25
|
+
FILL_IN,
|
|
26
|
+
NEW_SUFFIX,
|
|
27
|
+
pendingMerges,
|
|
28
|
+
planUpgrade,
|
|
29
|
+
unfilledTemplates,
|
|
30
|
+
} from "../templates.ts";
|
|
25
31
|
import { REPO_LABELS } from "./board.ts";
|
|
26
32
|
|
|
27
33
|
type Check = {
|
|
@@ -323,6 +329,31 @@ export default defineCommand({
|
|
|
323
329
|
fix: `merge each into the file next to it and delete it (kanbot-admin skill can help)`,
|
|
324
330
|
});
|
|
325
331
|
|
|
332
|
+
const unfilled = await unfilledTemplates(root);
|
|
333
|
+
for (const path of FILL_IN) {
|
|
334
|
+
const u = unfilled.find((x) => x.path === path);
|
|
335
|
+
const conventions = path.includes("project-conventions");
|
|
336
|
+
add({
|
|
337
|
+
name: `${path} filled in`,
|
|
338
|
+
ok: true,
|
|
339
|
+
warn: !!u,
|
|
340
|
+
detail: u?.detail,
|
|
341
|
+
why: u
|
|
342
|
+
? conventions
|
|
343
|
+
? "Every agent reads it first for commands and conventions. Until it's filled in, they guess."
|
|
344
|
+
: "Agents fix failing CI, so it should run your real install, lint and test commands."
|
|
345
|
+
: undefined,
|
|
346
|
+
fix: u
|
|
347
|
+
? conventions
|
|
348
|
+
? "replace each <placeholder> and delete the TEMPLATE note (kanbot-guide skill can help)"
|
|
349
|
+
: "replace the starter steps with your stack's commands"
|
|
350
|
+
: undefined,
|
|
351
|
+
docs: conventions
|
|
352
|
+
? "project-conventions#fill-it-in"
|
|
353
|
+
: "getting-started#set-up-a-repository",
|
|
354
|
+
});
|
|
355
|
+
}
|
|
356
|
+
|
|
326
357
|
section(`Pushed to origin/${config.baseBranch}`);
|
|
327
358
|
await git(root, "fetch", "origin", config.baseBranch).catch(() => {});
|
|
328
359
|
const tree = await git(
|
package/src/commands/init.ts
CHANGED
|
@@ -5,7 +5,7 @@ import { loadAgents } from "../agents/load.ts";
|
|
|
5
5
|
import { sync } from "../agents/sync.ts";
|
|
6
6
|
import { askCapabilities, compact, ownWorkers } from "../capabilities.ts";
|
|
7
7
|
import { configPath, saveConfig, writeConfigSchema } from "../config.ts";
|
|
8
|
-
import { UserError } from "../errors.ts";
|
|
8
|
+
import { DOCS_URL, UserError } from "../errors.ts";
|
|
9
9
|
import { run } from "../github/gh.ts";
|
|
10
10
|
import { log } from "../log.ts";
|
|
11
11
|
import { applyUpgrade, NEW_SUFFIX, planUpgrade } from "../templates.ts";
|
|
@@ -111,6 +111,7 @@ export default defineCommand({
|
|
|
111
111
|
console.log(`
|
|
112
112
|
Next steps:
|
|
113
113
|
1. Review AGENTS.md and fill in .agents/skills/project-conventions/SKILL.md
|
|
114
|
+
(ask your agent to draft it; see ${DOCS_URL}/project-conventions)
|
|
114
115
|
2. Adjust .github/workflows/ci.yml to your stack (agents fix failing CI)
|
|
115
116
|
3. Map your own skills under capabilities in .kanbot/config.yml (kanbot-guide can help)
|
|
116
117
|
4. kanbot board create # board and labels; enable the workflows it prints
|
package/src/known-hashes.json
CHANGED
|
@@ -18,13 +18,15 @@
|
|
|
18
18
|
],
|
|
19
19
|
".agents/skills/kanbot-guide/SKILL.md": [
|
|
20
20
|
"1251194ba34a8b6eae8508037b0a76c60d7a26b8",
|
|
21
|
+
"1329454d5b81912e856591caa036c93f88ef8c69",
|
|
21
22
|
"2c6c77a225c5b880eff023d4b3c1305bfc91bfb3",
|
|
22
23
|
"2ccb86b12e5af121b79ef9f53c2a35dbbdb2ddeb",
|
|
23
24
|
"53c73b1be4a1e8d863a52043eae4ca911c8be71b",
|
|
24
25
|
"a24c0a655d6485e65bd5dea2a71f3afe67f04404",
|
|
25
26
|
"b5a2d074ea61f2552890ca1d78bf8a043d7b73b3",
|
|
26
27
|
"bde0364d60525598bbb28f1648d06d1407c62a73",
|
|
27
|
-
"cf3e95d137a5a58a273262bca6ba25fbc95fa037"
|
|
28
|
+
"cf3e95d137a5a58a273262bca6ba25fbc95fa037",
|
|
29
|
+
"f9b76db4afbad14ad9d14dff805c71703099bdeb"
|
|
28
30
|
],
|
|
29
31
|
".agents/skills/kanbot-idea/SKILL.md": [
|
|
30
32
|
"8ab28cec8d3f30250ffe080106d0de8e3c2eaa8a",
|
package/src/templates.ts
CHANGED
|
@@ -54,6 +54,18 @@ export async function readManifest(root: string): Promise<Manifest | null> {
|
|
|
54
54
|
return (await file.exists()) ? ((await file.json()) as Manifest) : null;
|
|
55
55
|
}
|
|
56
56
|
|
|
57
|
+
/** Warning when this repo's templates and the running kanbot differ in version. */
|
|
58
|
+
export async function versionNotice(root: string, current = pkg.version) {
|
|
59
|
+
const installed = (await readManifest(root).catch(() => null))?.version;
|
|
60
|
+
if (!installed) return null;
|
|
61
|
+
const order = Bun.semver.order(installed, current);
|
|
62
|
+
if (order < 0)
|
|
63
|
+
return `kanbot ${current} is out, this repo has ${installed}. Run \`kanbot upgrade\` to get the new agents, skills and workflows.`;
|
|
64
|
+
if (order > 0)
|
|
65
|
+
return `This repo uses kanbot ${installed}, but you run ${current}. Use \`bunx kanbot@latest\`.`;
|
|
66
|
+
return null;
|
|
67
|
+
}
|
|
68
|
+
|
|
57
69
|
async function writeManifest(root: string, files: Record<string, string>) {
|
|
58
70
|
const sorted = Object.fromEntries(
|
|
59
71
|
Object.entries(files).sort(([a], [b]) => a.localeCompare(b)),
|
|
@@ -191,3 +203,54 @@ export async function pendingMerges(root: string, dir = TEMPLATES) {
|
|
|
191
203
|
const paths = [...(await listTemplates(dir)).keys()];
|
|
192
204
|
return paths.filter((p) => existsSync(join(root, `${p}${NEW_SUFFIX}`)));
|
|
193
205
|
}
|
|
206
|
+
|
|
207
|
+
/** User templates you are meant to fill in after install. */
|
|
208
|
+
export const FILL_IN = [
|
|
209
|
+
".agents/skills/project-conventions/SKILL.md",
|
|
210
|
+
".github/workflows/ci.yml",
|
|
211
|
+
];
|
|
212
|
+
|
|
213
|
+
const clip = (s: string) => (s.length > 72 ? `${s.slice(0, 71)}…` : s);
|
|
214
|
+
|
|
215
|
+
export type Unfilled = { path: string; detail: string };
|
|
216
|
+
|
|
217
|
+
/**
|
|
218
|
+
* Fill-in templates still unedited, or still holding the template's
|
|
219
|
+
* `<placeholder>`s. Missing files are left to other checks.
|
|
220
|
+
*/
|
|
221
|
+
export async function unfilledTemplates(
|
|
222
|
+
root: string,
|
|
223
|
+
opts: Pick<Options, "templates" | "known"> = {},
|
|
224
|
+
): Promise<Unfilled[]> {
|
|
225
|
+
const templates = await listTemplates(opts.templates);
|
|
226
|
+
const known: Record<string, string[]> = opts.known ?? knownHashes;
|
|
227
|
+
const out: Unfilled[] = [];
|
|
228
|
+
for (const path of FILL_IN) {
|
|
229
|
+
const tpl = templates.get(path);
|
|
230
|
+
const file = Bun.file(join(root, path));
|
|
231
|
+
if (!tpl || !(await file.exists())) continue;
|
|
232
|
+
const bytes = await file.bytes();
|
|
233
|
+
const current = hash(bytes);
|
|
234
|
+
if (current === hash(tpl) || (known[path] ?? []).includes(current)) {
|
|
235
|
+
out.push({ path, detail: "unchanged from the template" });
|
|
236
|
+
continue;
|
|
237
|
+
}
|
|
238
|
+
const placeholders = new Set(
|
|
239
|
+
new TextDecoder().decode(tpl).match(/<[^<>`\n]+>/g) ?? [],
|
|
240
|
+
);
|
|
241
|
+
const left = new TextDecoder()
|
|
242
|
+
.decode(bytes)
|
|
243
|
+
.split("\n")
|
|
244
|
+
.flatMap((line, i) =>
|
|
245
|
+
[...placeholders].some((p) => line.includes(p))
|
|
246
|
+
? [`line ${i + 1}: ${clip(line.trim())}`]
|
|
247
|
+
: [],
|
|
248
|
+
);
|
|
249
|
+
if (left.length)
|
|
250
|
+
out.push({
|
|
251
|
+
path,
|
|
252
|
+
detail: `${left.length} line(s) with placeholders left:\n${left.slice(0, 5).join("\n")}${left.length > 5 ? "\n…" : ""}`,
|
|
253
|
+
});
|
|
254
|
+
}
|
|
255
|
+
return out;
|
|
256
|
+
}
|
|
@@ -12,22 +12,23 @@ Explain in plain words. Ask before choosing for them; give a recommendation with
|
|
|
12
12
|
|
|
13
13
|
## Docs
|
|
14
14
|
|
|
15
|
-
| Question | Slug
|
|
16
|
-
| --------------------------------------------- |
|
|
17
|
-
| How do I install and set up a repo? | `getting-started`
|
|
18
|
-
| How does a card move across the board? | `workflow`
|
|
19
|
-
| How do I file ideas
|
|
20
|
-
| My own PRs, local sessions, direct commits? | `outside-the-board`
|
|
21
|
-
| Which agents are there, how do I change them? | `agents`
|
|
22
|
-
| Skills? | `skills`
|
|
23
|
-
|
|
|
24
|
-
|
|
|
25
|
-
|
|
|
26
|
-
|
|
|
27
|
-
|
|
|
28
|
-
|
|
|
29
|
-
|
|
|
30
|
-
|
|
|
15
|
+
| Question | Slug |
|
|
16
|
+
| --------------------------------------------- | --------------------- |
|
|
17
|
+
| How do I install and set up a repo? | `getting-started` |
|
|
18
|
+
| How does a card move across the board? | `workflow` |
|
|
19
|
+
| How do I add or file ideas? | `capturing-ideas` |
|
|
20
|
+
| My own PRs, local sessions, direct commits? | `outside-the-board` |
|
|
21
|
+
| Which agents are there, how do I change them? | `agents` |
|
|
22
|
+
| Skills? | `skills` |
|
|
23
|
+
| Filling in stack, commands and rules | `project-conventions` |
|
|
24
|
+
| Project memory, facts from corrections | `project-memory` |
|
|
25
|
+
| Claude or Codex? | `providers` |
|
|
26
|
+
| Every config field, labels, notifications | `configuration` |
|
|
27
|
+
| Using our own skills and agents for the work | `capabilities` |
|
|
28
|
+
| Copilot as an extra reviewer | `copilot-review` |
|
|
29
|
+
| Bot or user identity, merge by approving | `identity` |
|
|
30
|
+
| Upgrading and `.kanbot-new` files | `upgrading` |
|
|
31
|
+
| Every command and flag | `usage` |
|
|
31
32
|
|
|
32
33
|
## Board flow
|
|
33
34
|
|
|
@@ -43,7 +44,7 @@ Go step by step. Run each command, check its output, then go on. If `.kanbot/con
|
|
|
43
44
|
|
|
44
45
|
1. **Requirements.** Bun 1.3+, `gh` logged in, `claude` or `codex` logged in with a subscription (not an API key). Run `gh auth refresh -s project`.
|
|
45
46
|
2. **Provider.** Ask which subscription they have, then `bunx kanbot init --provider claude|codex` in the repo root.
|
|
46
|
-
3. **Conventions.** Fill in `.agents/skills/project-conventions/SKILL.md` with them: stack, commands to test, lint and typecheck. Adjust `.github/workflows/ci.yml` to run the same. Every agent reads this first.
|
|
47
|
+
3. **Conventions.** Fill in `.agents/skills/project-conventions/SKILL.md` with them: stack, commands to test, lint and typecheck. Adjust `.github/workflows/ci.yml` to run the same. Every agent reads this first. Draft it from manifests and CI, ask what you can't find, and have them run each command. Link `project-conventions`.
|
|
47
48
|
4. **Capabilities.** kanbot runs the process; the repo's own skills and agents do the work. Ask which skills they have for proving acceptance criteria (`verify`), technical review (`review`) and something a human can try (`preview`), and map them under `capabilities` in `.kanbot/config.yml`. See [Capabilities](#capabilities).
|
|
48
49
|
5. **Board.** `kanbot board create`, or `kanbot board link --owner <login> --number <n>` for an existing project. Have them enable the four built-in project workflows it prints; they can't be set through the API.
|
|
49
50
|
6. **Options.** Go through [Choose options](#choose-options). For app mode, run `kanbot app create` and have them install the app on the repo.
|