flowbook 0.1.6 → 0.2.1
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 +57 -29
- package/dist/cli.js +212 -47
- package/package.json +1 -1
- package/src/commands/flowbook.md +13 -0
- package/src/commands/flowbook.plain.md +13 -0
- package/src/node/cli.ts +15 -0
- package/src/node/init.ts +5 -37
- package/src/node/skill.ts +230 -0
package/README.md
CHANGED
|
@@ -30,6 +30,7 @@ npm run build-flowbook
|
|
|
30
30
|
flowbook init Set up Flowbook in your project
|
|
31
31
|
flowbook dev [--port 6200] Start the dev server
|
|
32
32
|
flowbook build [--out-dir d] Build a static site
|
|
33
|
+
flowbook skill <agent> [-g] Install AI agent skill & /flowbook command
|
|
33
34
|
```
|
|
34
35
|
|
|
35
36
|
### `flowbook init`
|
|
@@ -91,7 +92,7 @@ Ignores `node_modules/`, `.git/`, and `dist/`.
|
|
|
91
92
|
|
|
92
93
|
## AI Agent Skill
|
|
93
94
|
|
|
94
|
-
`flowbook
|
|
95
|
+
Use `flowbook skill` to install AI agent skills and `/flowbook` slash commands for your coding agents.
|
|
95
96
|
When a coding agent (Claude Code, OpenAI Codex, VS Code Copilot, Cursor, Gemini CLI, etc.) detects the keyword **"flowbook"** in your prompt, it will:
|
|
96
97
|
|
|
97
98
|
1. Analyze your codebase for logical flows (API routes, auth, state management, business logic, etc.)
|
|
@@ -99,56 +100,77 @@ When a coding agent (Claude Code, OpenAI Codex, VS Code Copilot, Cursor, Gemini
|
|
|
99
100
|
3. Generate `.flow.md` files with Mermaid diagrams for every significant flow
|
|
100
101
|
4. Verify the build
|
|
101
102
|
|
|
102
|
-
###
|
|
103
|
+
### `flowbook skill`
|
|
103
104
|
|
|
104
|
-
|
|
105
|
+
Install skills and `/flowbook` slash commands for specific agents:
|
|
105
106
|
|
|
106
107
|
```bash
|
|
107
|
-
|
|
108
|
+
# Install for a specific agent (project-level)
|
|
109
|
+
flowbook skill opencode
|
|
110
|
+
flowbook skill claude
|
|
111
|
+
flowbook skill cursor
|
|
112
|
+
|
|
113
|
+
# Install for all agents
|
|
114
|
+
flowbook skill all
|
|
115
|
+
|
|
116
|
+
# Install globally (available across all projects)
|
|
117
|
+
flowbook skill opencode -g
|
|
118
|
+
flowbook skill all --global
|
|
108
119
|
```
|
|
109
120
|
|
|
110
|
-
|
|
121
|
+
**What gets installed:**
|
|
122
|
+
|
|
123
|
+
| Component | Description |
|
|
124
|
+
|-----------|-------------|
|
|
125
|
+
| **Skill** (`SKILL.md`) | Auto-triggers when you mention "flowbook" in prompts |
|
|
126
|
+
| **Slash command** (`/flowbook`) | Explicit trigger — type `/flowbook` to generate flowcharts |
|
|
111
127
|
|
|
112
|
-
|
|
128
|
+
Slash commands are installed for agents that support them: **Claude Code**, **Cursor**, **Windsurf**, **OpenCode**.
|
|
113
129
|
|
|
114
|
-
|
|
130
|
+
### Install via skills.sh
|
|
131
|
+
|
|
132
|
+
You can also install the skill standalone using [skills.sh](https://skills.sh):
|
|
115
133
|
|
|
116
134
|
```bash
|
|
135
|
+
# Project-level
|
|
136
|
+
npx skills add Epsilondelta-ai/flowbook
|
|
137
|
+
|
|
138
|
+
# Global
|
|
117
139
|
npx skills add -g Epsilondelta-ai/flowbook
|
|
118
140
|
```
|
|
119
141
|
|
|
120
|
-
|
|
142
|
+
> **Note:** `npx skills add` installs skills only (SKILL.md). Use `flowbook skill` to also install `/flowbook` slash commands.
|
|
121
143
|
|
|
122
|
-
###
|
|
144
|
+
### Supported Agents
|
|
123
145
|
|
|
124
|
-
| Agent | Skill
|
|
125
|
-
|
|
126
|
-
| Claude Code | `.claude/skills/flowbook/SKILL.md` |
|
|
127
|
-
| OpenAI Codex | `.agents/skills/flowbook/SKILL.md` |
|
|
128
|
-
| VS Code / GitHub Copilot | `.github/skills/flowbook/SKILL.md` |
|
|
129
|
-
| Google Antigravity | `.agent/skills/flowbook/SKILL.md` |
|
|
130
|
-
| Gemini CLI | `.gemini/skills/flowbook/SKILL.md` |
|
|
131
|
-
| Cursor | `.cursor/skills/flowbook/SKILL.md` |
|
|
132
|
-
| Windsurf (Codeium) | `.windsurf/skills/flowbook/SKILL.md` |
|
|
133
|
-
| AmpCode | `.amp/skills/flowbook/SKILL.md` |
|
|
134
|
-
| OpenCode / oh-my-opencode | `.opencode/skills/flowbook/SKILL.md` |
|
|
146
|
+
| Agent | Skill | Slash Command |
|
|
147
|
+
|-------|-------|---------------|
|
|
148
|
+
| Claude Code | `.claude/skills/flowbook/SKILL.md` | `.claude/commands/flowbook.md` |
|
|
149
|
+
| OpenAI Codex | `.agents/skills/flowbook/SKILL.md` | — |
|
|
150
|
+
| VS Code / GitHub Copilot | `.github/skills/flowbook/SKILL.md` | — |
|
|
151
|
+
| Google Antigravity | `.agent/skills/flowbook/SKILL.md` | — |
|
|
152
|
+
| Gemini CLI | `.gemini/skills/flowbook/SKILL.md` | — |
|
|
153
|
+
| Cursor | `.cursor/skills/flowbook/SKILL.md` | `.cursor/commands/flowbook.md` |
|
|
154
|
+
| Windsurf (Codeium) | `.windsurf/skills/flowbook/SKILL.md` | `.windsurf/workflows/flowbook.md` |
|
|
155
|
+
| AmpCode | `.amp/skills/flowbook/SKILL.md` | — |
|
|
156
|
+
| OpenCode / oh-my-opencode | `.opencode/skills/flowbook/SKILL.md` | `.opencode/command/flowbook.md` |
|
|
135
157
|
|
|
136
158
|
<details>
|
|
137
|
-
<summary>Manual
|
|
159
|
+
<summary>Manual Installation</summary>
|
|
138
160
|
|
|
139
|
-
If you didn't use `flowbook
|
|
161
|
+
If you didn't use `flowbook skill` or `npx skills add`, copy files manually:
|
|
140
162
|
|
|
141
163
|
```bash
|
|
142
|
-
#
|
|
164
|
+
# Skill
|
|
143
165
|
mkdir -p .claude/skills/flowbook
|
|
144
166
|
cp node_modules/flowbook/src/skills/flowbook/SKILL.md .claude/skills/flowbook/
|
|
145
167
|
|
|
146
|
-
#
|
|
147
|
-
mkdir -p .
|
|
148
|
-
cp node_modules/flowbook/src/
|
|
168
|
+
# Slash command (Claude Code)
|
|
169
|
+
mkdir -p .claude/commands
|
|
170
|
+
cp node_modules/flowbook/src/commands/flowbook.md .claude/commands/
|
|
149
171
|
```
|
|
150
172
|
|
|
151
|
-
Replace
|
|
173
|
+
Replace directories with the appropriate paths from the table above.
|
|
152
174
|
|
|
153
175
|
</details>
|
|
154
176
|
## How It Works
|
|
@@ -175,12 +197,19 @@ Replace the directory with the appropriate path from the Compatible Agents table
|
|
|
175
197
|
src/
|
|
176
198
|
├── types.ts # Shared types (FlowEntry, FlowbookData)
|
|
177
199
|
├── node/
|
|
178
|
-
│ ├── cli.ts # CLI entry point (init, dev, build)
|
|
200
|
+
│ ├── cli.ts # CLI entry point (init, dev, build, skill)
|
|
179
201
|
│ ├── server.ts # Programmatic Vite server & build
|
|
180
202
|
│ ├── init.ts # Project initialization logic
|
|
203
|
+
│ ├── skill.ts # AI agent skill & command installer
|
|
181
204
|
│ ├── discovery.ts # File scanner (fast-glob)
|
|
182
205
|
│ ├── parser.ts # Frontmatter + mermaid extraction
|
|
183
206
|
│ └── plugin.ts # Vite virtual module plugin
|
|
207
|
+
├── skills/
|
|
208
|
+
│ └── flowbook/
|
|
209
|
+
│ └── SKILL.md # AI agent skill definition
|
|
210
|
+
├── commands/
|
|
211
|
+
│ ├── flowbook.md # Slash command (frontmatter format)
|
|
212
|
+
│ └── flowbook.plain.md # Slash command (plain markdown format)
|
|
184
213
|
└── client/
|
|
185
214
|
├── index.html # Entry HTML
|
|
186
215
|
├── main.tsx # React entry
|
|
@@ -193,7 +222,6 @@ src/
|
|
|
193
222
|
├── MermaidRenderer.tsx # Mermaid diagram rendering
|
|
194
223
|
├── FlowView.tsx # Single flow detail view
|
|
195
224
|
└── EmptyState.tsx # Empty state with guide
|
|
196
|
-
```
|
|
197
225
|
|
|
198
226
|
## Development (Contributing)
|
|
199
227
|
|
package/dist/cli.js
CHANGED
|
@@ -1,11 +1,9 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
// src/node/init.ts
|
|
4
|
-
import { readFileSync, writeFileSync, existsSync, mkdirSync
|
|
5
|
-
import { resolve
|
|
4
|
+
import { readFileSync, writeFileSync, existsSync, mkdirSync } from "fs";
|
|
5
|
+
import { resolve } from "path";
|
|
6
6
|
import { execSync } from "child_process";
|
|
7
|
-
import { fileURLToPath } from "url";
|
|
8
|
-
var __dirname = dirname(fileURLToPath(import.meta.url));
|
|
9
7
|
var EXAMPLE_FLOW = `---
|
|
10
8
|
title: Example Flow
|
|
11
9
|
category: Getting Started
|
|
@@ -74,48 +72,12 @@ async function initFlowbook() {
|
|
|
74
72
|
console.log(" \u2713 Added flowbook-static to .gitignore");
|
|
75
73
|
}
|
|
76
74
|
}
|
|
77
|
-
const skillSrc = resolve(__dirname, "..", "src", "skills", "flowbook", "SKILL.md");
|
|
78
|
-
const skillDirs = [
|
|
79
|
-
resolve(cwd, ".claude", "skills", "flowbook"),
|
|
80
|
-
// Claude Code
|
|
81
|
-
resolve(cwd, ".agents", "skills", "flowbook"),
|
|
82
|
-
// OpenAI Codex / cross-tool alias
|
|
83
|
-
resolve(cwd, ".github", "skills", "flowbook"),
|
|
84
|
-
// VS Code / GitHub Copilot
|
|
85
|
-
resolve(cwd, ".agent", "skills", "flowbook"),
|
|
86
|
-
// Google Antigravity
|
|
87
|
-
resolve(cwd, ".gemini", "skills", "flowbook"),
|
|
88
|
-
// Gemini CLI
|
|
89
|
-
resolve(cwd, ".cursor", "skills", "flowbook"),
|
|
90
|
-
// Cursor
|
|
91
|
-
resolve(cwd, ".windsurf", "skills", "flowbook"),
|
|
92
|
-
// Windsurf (Codeium)
|
|
93
|
-
resolve(cwd, ".amp", "skills", "flowbook"),
|
|
94
|
-
// AmpCode
|
|
95
|
-
resolve(cwd, ".opencode", "skills", "flowbook")
|
|
96
|
-
// OpenCode / oh-my-opencode
|
|
97
|
-
];
|
|
98
|
-
if (existsSync(skillSrc)) {
|
|
99
|
-
let installed = 0;
|
|
100
|
-
for (const dir of skillDirs) {
|
|
101
|
-
const dest = resolve(dir, "SKILL.md");
|
|
102
|
-
if (!existsSync(dest)) {
|
|
103
|
-
mkdirSync(dir, { recursive: true });
|
|
104
|
-
copyFileSync(skillSrc, dest);
|
|
105
|
-
installed++;
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
if (installed > 0) {
|
|
109
|
-
console.log(` \u2713 Installed AI agent skill to ${installed} agent directories`);
|
|
110
|
-
} else {
|
|
111
|
-
console.log(" \u2713 AI agent skills already installed");
|
|
112
|
-
}
|
|
113
|
-
}
|
|
114
75
|
const run = pm === "yarn" ? "yarn" : `${pm} run`;
|
|
115
76
|
console.log("");
|
|
116
77
|
console.log(" Next steps:");
|
|
117
|
-
console.log(` ${run} flowbook
|
|
118
|
-
console.log(` ${run} build-flowbook
|
|
78
|
+
console.log(` ${run} flowbook Start the dev server`);
|
|
79
|
+
console.log(` ${run} build-flowbook Build static site`);
|
|
80
|
+
console.log(` flowbook skill <agent> [-g] Install AI skill & /flowbook command`);
|
|
119
81
|
console.log("");
|
|
120
82
|
}
|
|
121
83
|
function detectPackageManager(cwd) {
|
|
@@ -228,11 +190,11 @@ function flowbookPlugin(options = {}) {
|
|
|
228
190
|
}
|
|
229
191
|
|
|
230
192
|
// src/node/server.ts
|
|
231
|
-
import { resolve as resolve2, dirname
|
|
232
|
-
import { fileURLToPath
|
|
233
|
-
var
|
|
193
|
+
import { resolve as resolve2, dirname } from "path";
|
|
194
|
+
import { fileURLToPath } from "url";
|
|
195
|
+
var __dirname = dirname(fileURLToPath(import.meta.url));
|
|
234
196
|
function getClientDir() {
|
|
235
|
-
return resolve2(
|
|
197
|
+
return resolve2(__dirname, "..", "src", "client");
|
|
236
198
|
}
|
|
237
199
|
function createConfig(options) {
|
|
238
200
|
const cwd = options.cwd ?? process.cwd();
|
|
@@ -272,6 +234,196 @@ async function buildStatic(options) {
|
|
|
272
234
|
`);
|
|
273
235
|
}
|
|
274
236
|
|
|
237
|
+
// src/node/skill.ts
|
|
238
|
+
import { existsSync as existsSync2, mkdirSync as mkdirSync2, copyFileSync } from "fs";
|
|
239
|
+
import { resolve as resolve3, dirname as dirname2 } from "path";
|
|
240
|
+
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
241
|
+
import { homedir } from "os";
|
|
242
|
+
var __dirname2 = dirname2(fileURLToPath2(import.meta.url));
|
|
243
|
+
var AGENTS = [
|
|
244
|
+
{
|
|
245
|
+
name: "Claude Code",
|
|
246
|
+
aliases: ["claude"],
|
|
247
|
+
skill: {
|
|
248
|
+
project: ".claude/skills/flowbook",
|
|
249
|
+
global: ".claude/skills/flowbook"
|
|
250
|
+
},
|
|
251
|
+
command: {
|
|
252
|
+
project: ".claude/commands",
|
|
253
|
+
global: ".claude/commands",
|
|
254
|
+
format: "frontmatter"
|
|
255
|
+
}
|
|
256
|
+
},
|
|
257
|
+
{
|
|
258
|
+
name: "OpenAI Codex",
|
|
259
|
+
aliases: ["codex"],
|
|
260
|
+
skill: {
|
|
261
|
+
project: ".agents/skills/flowbook",
|
|
262
|
+
global: ".codex/skills/flowbook"
|
|
263
|
+
}
|
|
264
|
+
},
|
|
265
|
+
{
|
|
266
|
+
name: "VS Code / GitHub Copilot",
|
|
267
|
+
aliases: ["copilot", "vscode"],
|
|
268
|
+
skill: {
|
|
269
|
+
project: ".github/skills/flowbook",
|
|
270
|
+
global: ".copilot/skills/flowbook"
|
|
271
|
+
}
|
|
272
|
+
},
|
|
273
|
+
{
|
|
274
|
+
name: "Google Antigravity",
|
|
275
|
+
aliases: ["antigravity"],
|
|
276
|
+
skill: {
|
|
277
|
+
project: ".agent/skills/flowbook",
|
|
278
|
+
global: ".gemini/antigravity/skills/flowbook"
|
|
279
|
+
}
|
|
280
|
+
},
|
|
281
|
+
{
|
|
282
|
+
name: "Gemini CLI",
|
|
283
|
+
aliases: ["gemini"],
|
|
284
|
+
skill: {
|
|
285
|
+
project: ".gemini/skills/flowbook",
|
|
286
|
+
global: ".gemini/skills/flowbook"
|
|
287
|
+
}
|
|
288
|
+
},
|
|
289
|
+
{
|
|
290
|
+
name: "Cursor",
|
|
291
|
+
aliases: ["cursor"],
|
|
292
|
+
skill: {
|
|
293
|
+
project: ".cursor/skills/flowbook",
|
|
294
|
+
global: ".cursor/skills/flowbook"
|
|
295
|
+
},
|
|
296
|
+
command: {
|
|
297
|
+
project: ".cursor/commands",
|
|
298
|
+
global: ".cursor/commands",
|
|
299
|
+
format: "plain"
|
|
300
|
+
}
|
|
301
|
+
},
|
|
302
|
+
{
|
|
303
|
+
name: "Windsurf",
|
|
304
|
+
aliases: ["windsurf"],
|
|
305
|
+
skill: {
|
|
306
|
+
project: ".windsurf/skills/flowbook",
|
|
307
|
+
global: ".codeium/windsurf/skills/flowbook"
|
|
308
|
+
},
|
|
309
|
+
command: {
|
|
310
|
+
project: ".windsurf/workflows",
|
|
311
|
+
global: ".codeium/windsurf/workflows",
|
|
312
|
+
format: "plain"
|
|
313
|
+
}
|
|
314
|
+
},
|
|
315
|
+
{
|
|
316
|
+
name: "AmpCode",
|
|
317
|
+
aliases: ["amp"],
|
|
318
|
+
skill: {
|
|
319
|
+
project: ".amp/skills/flowbook",
|
|
320
|
+
global: ".config/agents/skills/flowbook"
|
|
321
|
+
}
|
|
322
|
+
},
|
|
323
|
+
{
|
|
324
|
+
name: "OpenCode",
|
|
325
|
+
aliases: ["opencode"],
|
|
326
|
+
skill: {
|
|
327
|
+
project: ".opencode/skills/flowbook",
|
|
328
|
+
global: ".config/opencode/skills/flowbook"
|
|
329
|
+
},
|
|
330
|
+
command: {
|
|
331
|
+
project: ".opencode/command",
|
|
332
|
+
global: ".config/opencode/command",
|
|
333
|
+
format: "frontmatter"
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
];
|
|
337
|
+
function getSkillSrc() {
|
|
338
|
+
return resolve3(__dirname2, "..", "src", "skills", "flowbook", "SKILL.md");
|
|
339
|
+
}
|
|
340
|
+
function getCommandSrc(format) {
|
|
341
|
+
const file = format === "frontmatter" ? "flowbook.md" : "flowbook.plain.md";
|
|
342
|
+
return resolve3(__dirname2, "..", "src", "commands", file);
|
|
343
|
+
}
|
|
344
|
+
function resolveAgents(agentArg) {
|
|
345
|
+
if (agentArg === "all") return AGENTS;
|
|
346
|
+
const lower = agentArg.toLowerCase();
|
|
347
|
+
const found = AGENTS.filter(
|
|
348
|
+
(a) => a.aliases.includes(lower) || a.name.toLowerCase().includes(lower)
|
|
349
|
+
);
|
|
350
|
+
if (found.length === 0) {
|
|
351
|
+
console.error(` Unknown agent: "${agentArg}"`);
|
|
352
|
+
console.error(` Available: all, ${AGENTS.flatMap((a) => a.aliases).join(", ")}`);
|
|
353
|
+
process.exit(1);
|
|
354
|
+
}
|
|
355
|
+
return found;
|
|
356
|
+
}
|
|
357
|
+
function installFile(src, destDir, destFilename) {
|
|
358
|
+
const dest = resolve3(destDir, destFilename);
|
|
359
|
+
if (existsSync2(dest)) return false;
|
|
360
|
+
mkdirSync2(destDir, { recursive: true });
|
|
361
|
+
copyFileSync(src, dest);
|
|
362
|
+
return true;
|
|
363
|
+
}
|
|
364
|
+
function installSkills(agentArg, global) {
|
|
365
|
+
const agents = resolveAgents(agentArg);
|
|
366
|
+
const base = global ? homedir() : process.cwd();
|
|
367
|
+
const skillSrc = getSkillSrc();
|
|
368
|
+
if (!existsSync2(skillSrc)) {
|
|
369
|
+
console.error(" \u2717 Skill source file not found. Reinstall flowbook.");
|
|
370
|
+
process.exit(1);
|
|
371
|
+
}
|
|
372
|
+
let skillCount = 0;
|
|
373
|
+
let cmdCount = 0;
|
|
374
|
+
for (const agent of agents) {
|
|
375
|
+
const skillDir = resolve3(base, global ? agent.skill.global : agent.skill.project);
|
|
376
|
+
if (installFile(skillSrc, skillDir, "SKILL.md")) {
|
|
377
|
+
skillCount++;
|
|
378
|
+
}
|
|
379
|
+
if (agent.command) {
|
|
380
|
+
const cmdSrc = getCommandSrc(agent.command.format);
|
|
381
|
+
if (existsSync2(cmdSrc)) {
|
|
382
|
+
const cmdDir = resolve3(base, global ? agent.command.global : agent.command.project);
|
|
383
|
+
if (installFile(cmdSrc, cmdDir, "flowbook.md")) {
|
|
384
|
+
cmdCount++;
|
|
385
|
+
}
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
}
|
|
389
|
+
const scope = global ? "global" : "project";
|
|
390
|
+
const agentNames = agents.map((a) => a.name).join(", ");
|
|
391
|
+
if (skillCount > 0 || cmdCount > 0) {
|
|
392
|
+
if (skillCount > 0) console.log(` \u2713 Installed skill to ${skillCount} ${scope} director${skillCount > 1 ? "ies" : "y"}`);
|
|
393
|
+
if (cmdCount > 0) console.log(` \u2713 Installed /flowbook command to ${cmdCount} ${scope} director${cmdCount > 1 ? "ies" : "y"}`);
|
|
394
|
+
console.log(` Agents: ${agentNames}`);
|
|
395
|
+
} else {
|
|
396
|
+
console.log(` \u2713 Already installed for: ${agentNames}`);
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
function printSkillUsage() {
|
|
400
|
+
console.log(`
|
|
401
|
+
flowbook skill \u2014 Install AI agent skill & /flowbook command
|
|
402
|
+
|
|
403
|
+
Usage:
|
|
404
|
+
flowbook skill <agent> Install to project
|
|
405
|
+
flowbook skill <agent> --global Install globally
|
|
406
|
+
flowbook skill <agent> -g Install globally (short)
|
|
407
|
+
|
|
408
|
+
Agents:
|
|
409
|
+
all All supported agents
|
|
410
|
+
claude Claude Code
|
|
411
|
+
codex OpenAI Codex
|
|
412
|
+
copilot VS Code / GitHub Copilot
|
|
413
|
+
antigravity Google Antigravity
|
|
414
|
+
gemini Gemini CLI
|
|
415
|
+
cursor Cursor
|
|
416
|
+
windsurf Windsurf (Codeium)
|
|
417
|
+
amp AmpCode
|
|
418
|
+
opencode OpenCode / oh-my-opencode
|
|
419
|
+
|
|
420
|
+
Examples:
|
|
421
|
+
flowbook skill all Install to all agents (project)
|
|
422
|
+
flowbook skill opencode -g Install globally for OpenCode
|
|
423
|
+
flowbook skill claude --global Install globally for Claude Code
|
|
424
|
+
`);
|
|
425
|
+
}
|
|
426
|
+
|
|
275
427
|
// src/node/cli.ts
|
|
276
428
|
async function main() {
|
|
277
429
|
const args = process.argv.slice(2);
|
|
@@ -290,6 +442,16 @@ async function main() {
|
|
|
290
442
|
await buildStatic({ outDir });
|
|
291
443
|
break;
|
|
292
444
|
}
|
|
445
|
+
case "skill": {
|
|
446
|
+
const agent = args[1];
|
|
447
|
+
if (!agent) {
|
|
448
|
+
printSkillUsage();
|
|
449
|
+
break;
|
|
450
|
+
}
|
|
451
|
+
const isGlobal = args.includes("--global") || args.includes("-g");
|
|
452
|
+
installSkills(agent, isGlobal);
|
|
453
|
+
break;
|
|
454
|
+
}
|
|
293
455
|
default:
|
|
294
456
|
printUsage();
|
|
295
457
|
break;
|
|
@@ -308,10 +470,13 @@ function printUsage() {
|
|
|
308
470
|
flowbook init Set up Flowbook in your project
|
|
309
471
|
flowbook dev [--port 6200] Start the dev server
|
|
310
472
|
flowbook build [--out-dir d] Build a static site
|
|
473
|
+
flowbook skill <agent> [-g] Install AI agent skill & command
|
|
311
474
|
|
|
312
475
|
Options:
|
|
313
476
|
--port <number> Dev server port (default: 6200)
|
|
314
477
|
--out-dir <path> Build output directory (default: flowbook-static)
|
|
478
|
+
|
|
479
|
+
Run 'flowbook skill' for agent-specific options.
|
|
315
480
|
`);
|
|
316
481
|
}
|
|
317
482
|
main().catch((err) => {
|
package/package.json
CHANGED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Analyze codebase and generate Mermaid flowchart documentation using Flowbook
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
Load the **flowbook** skill and execute the full flowchart generation workflow.
|
|
6
|
+
|
|
7
|
+
When prompted with `/flowbook`, you MUST:
|
|
8
|
+
|
|
9
|
+
1. Load the `flowbook` skill (SKILL.md) for detailed instructions
|
|
10
|
+
2. Analyze the codebase for logical flows (API routes, auth, state management, business logic)
|
|
11
|
+
3. Set up Flowbook if not already initialized (`npx flowbook@latest init`)
|
|
12
|
+
4. Generate `.flow.md` files with Mermaid diagrams for every significant flow
|
|
13
|
+
5. Run `npm run flowbook` to verify the build
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# /flowbook — Flowchart Documentation Generator
|
|
2
|
+
|
|
3
|
+
Analyze codebase and generate Mermaid flowchart documentation using Flowbook.
|
|
4
|
+
|
|
5
|
+
Load the **flowbook** skill and execute the full flowchart generation workflow.
|
|
6
|
+
|
|
7
|
+
When prompted with `/flowbook`, you MUST:
|
|
8
|
+
|
|
9
|
+
1. Load the `flowbook` skill (SKILL.md) for detailed instructions
|
|
10
|
+
2. Analyze the codebase for logical flows (API routes, auth, state management, business logic)
|
|
11
|
+
3. Set up Flowbook if not already initialized (`npx flowbook@latest init`)
|
|
12
|
+
4. Generate `.flow.md` files with Mermaid diagrams for every significant flow
|
|
13
|
+
5. Run `npm run flowbook` to verify the build
|
package/src/node/cli.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { initFlowbook } from "./init";
|
|
2
2
|
import { startDevServer, buildStatic } from "./server";
|
|
3
|
+
import { installSkills, printSkillUsage } from "./skill";
|
|
3
4
|
|
|
4
5
|
async function main() {
|
|
5
6
|
const args = process.argv.slice(2);
|
|
@@ -22,6 +23,17 @@ async function main() {
|
|
|
22
23
|
break;
|
|
23
24
|
}
|
|
24
25
|
|
|
26
|
+
case "skill": {
|
|
27
|
+
const agent = args[1];
|
|
28
|
+
if (!agent) {
|
|
29
|
+
printSkillUsage();
|
|
30
|
+
break;
|
|
31
|
+
}
|
|
32
|
+
const isGlobal = args.includes("--global") || args.includes("-g");
|
|
33
|
+
installSkills(agent, isGlobal);
|
|
34
|
+
break;
|
|
35
|
+
}
|
|
36
|
+
|
|
25
37
|
default:
|
|
26
38
|
printUsage();
|
|
27
39
|
break;
|
|
@@ -46,10 +58,13 @@ function printUsage() {
|
|
|
46
58
|
flowbook init Set up Flowbook in your project
|
|
47
59
|
flowbook dev [--port 6200] Start the dev server
|
|
48
60
|
flowbook build [--out-dir d] Build a static site
|
|
61
|
+
flowbook skill <agent> [-g] Install AI agent skill & command
|
|
49
62
|
|
|
50
63
|
Options:
|
|
51
64
|
--port <number> Dev server port (default: 6200)
|
|
52
65
|
--out-dir <path> Build output directory (default: flowbook-static)
|
|
66
|
+
|
|
67
|
+
Run 'flowbook skill' for agent-specific options.
|
|
53
68
|
`);
|
|
54
69
|
}
|
|
55
70
|
|
package/src/node/init.ts
CHANGED
|
@@ -1,9 +1,7 @@
|
|
|
1
|
-
import { readFileSync, writeFileSync, existsSync, mkdirSync
|
|
2
|
-
import { resolve
|
|
1
|
+
import { readFileSync, writeFileSync, existsSync, mkdirSync } from "node:fs";
|
|
2
|
+
import { resolve } from "node:path";
|
|
3
3
|
import { execSync } from "node:child_process";
|
|
4
|
-
import { fileURLToPath } from "node:url";
|
|
5
4
|
|
|
6
|
-
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
7
5
|
|
|
8
6
|
const EXAMPLE_FLOW = `---
|
|
9
7
|
title: Example Flow
|
|
@@ -88,42 +86,12 @@ export async function initFlowbook() {
|
|
|
88
86
|
}
|
|
89
87
|
}
|
|
90
88
|
|
|
91
|
-
// 5. Install AI agent skill to all supported agent directories
|
|
92
|
-
const skillSrc = resolve(__dirname, "..", "src", "skills", "flowbook", "SKILL.md");
|
|
93
|
-
const skillDirs = [
|
|
94
|
-
resolve(cwd, ".claude", "skills", "flowbook"), // Claude Code
|
|
95
|
-
resolve(cwd, ".agents", "skills", "flowbook"), // OpenAI Codex / cross-tool alias
|
|
96
|
-
resolve(cwd, ".github", "skills", "flowbook"), // VS Code / GitHub Copilot
|
|
97
|
-
resolve(cwd, ".agent", "skills", "flowbook"), // Google Antigravity
|
|
98
|
-
resolve(cwd, ".gemini", "skills", "flowbook"), // Gemini CLI
|
|
99
|
-
resolve(cwd, ".cursor", "skills", "flowbook"), // Cursor
|
|
100
|
-
resolve(cwd, ".windsurf", "skills", "flowbook"), // Windsurf (Codeium)
|
|
101
|
-
resolve(cwd, ".amp", "skills", "flowbook"), // AmpCode
|
|
102
|
-
resolve(cwd, ".opencode", "skills", "flowbook"), // OpenCode / oh-my-opencode
|
|
103
|
-
];
|
|
104
|
-
|
|
105
|
-
if (existsSync(skillSrc)) {
|
|
106
|
-
let installed = 0;
|
|
107
|
-
for (const dir of skillDirs) {
|
|
108
|
-
const dest = resolve(dir, "SKILL.md");
|
|
109
|
-
if (!existsSync(dest)) {
|
|
110
|
-
mkdirSync(dir, { recursive: true });
|
|
111
|
-
copyFileSync(skillSrc, dest);
|
|
112
|
-
installed++;
|
|
113
|
-
}
|
|
114
|
-
}
|
|
115
|
-
if (installed > 0) {
|
|
116
|
-
console.log(` \u2713 Installed AI agent skill to ${installed} agent directories`);
|
|
117
|
-
} else {
|
|
118
|
-
console.log(" \u2713 AI agent skills already installed");
|
|
119
|
-
}
|
|
120
|
-
}
|
|
121
|
-
|
|
122
89
|
const run = pm === "yarn" ? "yarn" : `${pm} run`;
|
|
123
90
|
console.log("");
|
|
124
91
|
console.log(" Next steps:");
|
|
125
|
-
console.log(` ${run} flowbook
|
|
126
|
-
console.log(` ${run} build-flowbook
|
|
92
|
+
console.log(` ${run} flowbook Start the dev server`);
|
|
93
|
+
console.log(` ${run} build-flowbook Build static site`);
|
|
94
|
+
console.log(` flowbook skill <agent> [-g] Install AI skill & /flowbook command`);
|
|
127
95
|
console.log("");
|
|
128
96
|
}
|
|
129
97
|
|
|
@@ -0,0 +1,230 @@
|
|
|
1
|
+
import { existsSync, mkdirSync, copyFileSync } from "node:fs";
|
|
2
|
+
import { resolve, dirname } from "node:path";
|
|
3
|
+
import { fileURLToPath } from "node:url";
|
|
4
|
+
import { homedir } from "node:os";
|
|
5
|
+
|
|
6
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
7
|
+
|
|
8
|
+
interface AgentConfig {
|
|
9
|
+
name: string;
|
|
10
|
+
aliases: string[];
|
|
11
|
+
skill: { project: string; global: string };
|
|
12
|
+
command?: { project: string; global: string; format: "frontmatter" | "plain" };
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
const AGENTS: AgentConfig[] = [
|
|
16
|
+
{
|
|
17
|
+
name: "Claude Code",
|
|
18
|
+
aliases: ["claude"],
|
|
19
|
+
skill: {
|
|
20
|
+
project: ".claude/skills/flowbook",
|
|
21
|
+
global: ".claude/skills/flowbook",
|
|
22
|
+
},
|
|
23
|
+
command: {
|
|
24
|
+
project: ".claude/commands",
|
|
25
|
+
global: ".claude/commands",
|
|
26
|
+
format: "frontmatter",
|
|
27
|
+
},
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
name: "OpenAI Codex",
|
|
31
|
+
aliases: ["codex"],
|
|
32
|
+
skill: {
|
|
33
|
+
project: ".agents/skills/flowbook",
|
|
34
|
+
global: ".codex/skills/flowbook",
|
|
35
|
+
},
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
name: "VS Code / GitHub Copilot",
|
|
39
|
+
aliases: ["copilot", "vscode"],
|
|
40
|
+
skill: {
|
|
41
|
+
project: ".github/skills/flowbook",
|
|
42
|
+
global: ".copilot/skills/flowbook",
|
|
43
|
+
},
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
name: "Google Antigravity",
|
|
47
|
+
aliases: ["antigravity"],
|
|
48
|
+
skill: {
|
|
49
|
+
project: ".agent/skills/flowbook",
|
|
50
|
+
global: ".gemini/antigravity/skills/flowbook",
|
|
51
|
+
},
|
|
52
|
+
},
|
|
53
|
+
{
|
|
54
|
+
name: "Gemini CLI",
|
|
55
|
+
aliases: ["gemini"],
|
|
56
|
+
skill: {
|
|
57
|
+
project: ".gemini/skills/flowbook",
|
|
58
|
+
global: ".gemini/skills/flowbook",
|
|
59
|
+
},
|
|
60
|
+
},
|
|
61
|
+
{
|
|
62
|
+
name: "Cursor",
|
|
63
|
+
aliases: ["cursor"],
|
|
64
|
+
skill: {
|
|
65
|
+
project: ".cursor/skills/flowbook",
|
|
66
|
+
global: ".cursor/skills/flowbook",
|
|
67
|
+
},
|
|
68
|
+
command: {
|
|
69
|
+
project: ".cursor/commands",
|
|
70
|
+
global: ".cursor/commands",
|
|
71
|
+
format: "plain",
|
|
72
|
+
},
|
|
73
|
+
},
|
|
74
|
+
{
|
|
75
|
+
name: "Windsurf",
|
|
76
|
+
aliases: ["windsurf"],
|
|
77
|
+
skill: {
|
|
78
|
+
project: ".windsurf/skills/flowbook",
|
|
79
|
+
global: ".codeium/windsurf/skills/flowbook",
|
|
80
|
+
},
|
|
81
|
+
command: {
|
|
82
|
+
project: ".windsurf/workflows",
|
|
83
|
+
global: ".codeium/windsurf/workflows",
|
|
84
|
+
format: "plain",
|
|
85
|
+
},
|
|
86
|
+
},
|
|
87
|
+
{
|
|
88
|
+
name: "AmpCode",
|
|
89
|
+
aliases: ["amp"],
|
|
90
|
+
skill: {
|
|
91
|
+
project: ".amp/skills/flowbook",
|
|
92
|
+
global: ".config/agents/skills/flowbook",
|
|
93
|
+
},
|
|
94
|
+
},
|
|
95
|
+
{
|
|
96
|
+
name: "OpenCode",
|
|
97
|
+
aliases: ["opencode"],
|
|
98
|
+
skill: {
|
|
99
|
+
project: ".opencode/skills/flowbook",
|
|
100
|
+
global: ".config/opencode/skills/flowbook",
|
|
101
|
+
},
|
|
102
|
+
command: {
|
|
103
|
+
project: ".opencode/command",
|
|
104
|
+
global: ".config/opencode/command",
|
|
105
|
+
format: "frontmatter",
|
|
106
|
+
},
|
|
107
|
+
},
|
|
108
|
+
];
|
|
109
|
+
|
|
110
|
+
function getSkillSrc(): string {
|
|
111
|
+
return resolve(__dirname, "..", "src", "skills", "flowbook", "SKILL.md");
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
function getCommandSrc(format: "frontmatter" | "plain"): string {
|
|
115
|
+
const file = format === "frontmatter" ? "flowbook.md" : "flowbook.plain.md";
|
|
116
|
+
return resolve(__dirname, "..", "src", "commands", file);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
function resolveAgents(agentArg: string): AgentConfig[] {
|
|
120
|
+
if (agentArg === "all") return AGENTS;
|
|
121
|
+
|
|
122
|
+
const lower = agentArg.toLowerCase();
|
|
123
|
+
const found = AGENTS.filter(
|
|
124
|
+
(a) =>
|
|
125
|
+
a.aliases.includes(lower) ||
|
|
126
|
+
a.name.toLowerCase().includes(lower),
|
|
127
|
+
);
|
|
128
|
+
|
|
129
|
+
if (found.length === 0) {
|
|
130
|
+
console.error(` Unknown agent: "${agentArg}"`);
|
|
131
|
+
console.error(` Available: all, ${AGENTS.flatMap((a) => a.aliases).join(", ")}`);
|
|
132
|
+
process.exit(1);
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
return found;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
function installFile(src: string, destDir: string, destFilename: string): boolean {
|
|
139
|
+
const dest = resolve(destDir, destFilename);
|
|
140
|
+
if (existsSync(dest)) return false;
|
|
141
|
+
mkdirSync(destDir, { recursive: true });
|
|
142
|
+
copyFileSync(src, dest);
|
|
143
|
+
return true;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
export function installSkills(agentArg: string, global: boolean): void {
|
|
147
|
+
const agents = resolveAgents(agentArg);
|
|
148
|
+
const base = global ? homedir() : process.cwd();
|
|
149
|
+
const skillSrc = getSkillSrc();
|
|
150
|
+
|
|
151
|
+
if (!existsSync(skillSrc)) {
|
|
152
|
+
console.error(" ✗ Skill source file not found. Reinstall flowbook.");
|
|
153
|
+
process.exit(1);
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
let skillCount = 0;
|
|
157
|
+
let cmdCount = 0;
|
|
158
|
+
|
|
159
|
+
for (const agent of agents) {
|
|
160
|
+
const skillDir = resolve(base, global ? agent.skill.global : agent.skill.project);
|
|
161
|
+
if (installFile(skillSrc, skillDir, "SKILL.md")) {
|
|
162
|
+
skillCount++;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
if (agent.command) {
|
|
166
|
+
const cmdSrc = getCommandSrc(agent.command.format);
|
|
167
|
+
if (existsSync(cmdSrc)) {
|
|
168
|
+
const cmdDir = resolve(base, global ? agent.command.global : agent.command.project);
|
|
169
|
+
if (installFile(cmdSrc, cmdDir, "flowbook.md")) {
|
|
170
|
+
cmdCount++;
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
const scope = global ? "global" : "project";
|
|
177
|
+
const agentNames = agents.map((a) => a.name).join(", ");
|
|
178
|
+
|
|
179
|
+
if (skillCount > 0 || cmdCount > 0) {
|
|
180
|
+
if (skillCount > 0) console.log(` ✓ Installed skill to ${skillCount} ${scope} director${skillCount > 1 ? "ies" : "y"}`);
|
|
181
|
+
if (cmdCount > 0) console.log(` ✓ Installed /flowbook command to ${cmdCount} ${scope} director${cmdCount > 1 ? "ies" : "y"}`);
|
|
182
|
+
console.log(` Agents: ${agentNames}`);
|
|
183
|
+
} else {
|
|
184
|
+
console.log(` ✓ Already installed for: ${agentNames}`);
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
/** Used by init.ts — installs skills only (no commands) to all agents at project level */
|
|
189
|
+
export function installAllProjectSkills(): number {
|
|
190
|
+
const cwd = process.cwd();
|
|
191
|
+
const skillSrc = getSkillSrc();
|
|
192
|
+
if (!existsSync(skillSrc)) return 0;
|
|
193
|
+
|
|
194
|
+
let installed = 0;
|
|
195
|
+
for (const agent of AGENTS) {
|
|
196
|
+
const dir = resolve(cwd, agent.skill.project);
|
|
197
|
+
if (installFile(skillSrc, dir, "SKILL.md")) {
|
|
198
|
+
installed++;
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
return installed;
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
export function printSkillUsage(): void {
|
|
205
|
+
console.log(`
|
|
206
|
+
flowbook skill — Install AI agent skill & /flowbook command
|
|
207
|
+
|
|
208
|
+
Usage:
|
|
209
|
+
flowbook skill <agent> Install to project
|
|
210
|
+
flowbook skill <agent> --global Install globally
|
|
211
|
+
flowbook skill <agent> -g Install globally (short)
|
|
212
|
+
|
|
213
|
+
Agents:
|
|
214
|
+
all All supported agents
|
|
215
|
+
claude Claude Code
|
|
216
|
+
codex OpenAI Codex
|
|
217
|
+
copilot VS Code / GitHub Copilot
|
|
218
|
+
antigravity Google Antigravity
|
|
219
|
+
gemini Gemini CLI
|
|
220
|
+
cursor Cursor
|
|
221
|
+
windsurf Windsurf (Codeium)
|
|
222
|
+
amp AmpCode
|
|
223
|
+
opencode OpenCode / oh-my-opencode
|
|
224
|
+
|
|
225
|
+
Examples:
|
|
226
|
+
flowbook skill all Install to all agents (project)
|
|
227
|
+
flowbook skill opencode -g Install globally for OpenCode
|
|
228
|
+
flowbook skill claude --global Install globally for Claude Code
|
|
229
|
+
`);
|
|
230
|
+
}
|