@alfacapital-tech/c4builder 0.9.0-rc.4 → 0.10.0-rc.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 CHANGED
@@ -31,6 +31,9 @@ than a hundred diagrams, so we continue it as a maintained fork, adapted to work
31
31
  and lays it out with horizontal pools and lanes.
32
32
  - **Mermaid** `.mmd` files and ```` ```mermaid ```` blocks are rendered at build time by real mermaid,
33
33
  without a browser: images in every output instead of client-side rendering.
34
+ - **Review from the page.** In `c4builder --site -w` a selection becomes a question in the source
35
+ `.md` or feedback for the agent; `c4builder feedback --wait --as <name>` hands the batch to the
36
+ agent, and the page reloads with its edits.
34
37
  - **Maintained.** TypeScript, golden rendering snapshots, CI on every pull request, releases to
35
38
  npm and GHCR. The PDF output of the original was removed.
36
39
 
@@ -57,8 +60,9 @@ c4builder check src/context.puml # exit code 0 or 1, "✗ file: line N: messag
57
60
  c4builder --site -w # rebuilds and reloads the browser on every save
58
61
  ```
59
62
 
60
- For agents: `npx skills add AlfaCapital-Tech/C4-Builder/skills` installs the skills, and
61
- `"generateLLMS": true` adds `llms.txt` / `llms-full.txt` (diagram sources included) to the site.
63
+ For agents: `c4builder skills` installs the agent skills of the installed version into the project
64
+ (`c4builder --new` does it for a new one), and `"generateLLMS": true` adds `llms.txt` /
65
+ `llms-full.txt` (diagram sources included) to the site.
62
66
 
63
67
  Or with Docker (Node, JRE, PlantUML, fonts and D2 included):
64
68
 
@@ -7,6 +7,7 @@ import Configstore from 'configstore';
7
7
  import { readFile, writeFile, makeDirectory } from "../../util/utils.js";
8
8
  import { defaultConfig } from "../../config/defaults.js";
9
9
  import { TEMPLATE_DIR } from "../../util/paths.js";
10
+ import cmdSkills from "./skills.js";
10
11
  // Общая проверка имени проекта: возвращает текст ошибки или null (валидно).
11
12
  // Интерактив показывает её и переспрашивает; --yes падает с ней (exit≠0), без ре-промпта.
12
13
  const validateProjectName = (name) => {
@@ -55,6 +56,8 @@ export default async (opts = {}) => {
55
56
  }
56
57
  await makeDirectory(projectName);
57
58
  await generateTemplate(TEMPLATE_DIR, projectName);
59
+ // Скиллы рядом с src/, как AGENTS.md: сборка их не видит (change skills-install, D6).
60
+ cmdSkills(path.join(process.cwd(), projectName));
58
61
  const conf = new Configstore(path.join(process.cwd(), projectName).split(path.sep).splice(1).join('_'), {}, { configPath: path.join(process.cwd(), projectName, '.c4builder') });
59
62
  // --yes: полный конфиг из единого defaultConfig → последующий c4builder собирает
60
63
  // без wizard'а. Интерактив пишет только projectName (первая сборка ведёт через wizard).
@@ -0,0 +1,80 @@
1
+ import fs from 'node:fs';
2
+ import os from 'node:os';
3
+ import path from 'node:path';
4
+ import { detectAgent } from "../agent.js";
5
+ import { compareVersions, disabled } from "../update.js";
6
+ import { PACKAGE_ROOT, packageJson as pkg } from "../../util/paths.js";
7
+ // Скиллы агентов (change skills-install): входят в пакет, поэтому ставятся офлайн и той же версии,
8
+ // что и CLI. По основному скиллу судим обо всём наборе — ставятся все сразу (D3).
9
+ const SKILLS_DIR = path.join(PACKAGE_ROOT, 'skills');
10
+ const MAIN = 'c4builder';
11
+ const RUN = 'c4builder skills';
12
+ // Отметка версии из frontmatter `<root>/c4builder/SKILL.md` регуляркой, без YAML-парсера (D4):
13
+ // undefined — скилла нет, '' — скилл без отметки (поставлен `npx skills add` или руками).
14
+ const stampIn = (root) => {
15
+ let text;
16
+ try {
17
+ text = fs.readFileSync(path.join(root, MAIN, 'SKILL.md'), 'utf8');
18
+ }
19
+ catch {
20
+ return undefined;
21
+ }
22
+ const front = text.match(/^---\r?\n([\s\S]*?)\r?\n---/)?.[1] ?? '';
23
+ return front.match(/^\s+generatedBy:\s*["']?([^"'\s]+)/m)?.[1] ?? '';
24
+ };
25
+ // Копия новее CLI не устаревшая: о старом CLI скажет уведомление о новой версии (D4).
26
+ const outdated = (stamp) => !stamp || compareVersions(stamp, pkg.version) < 0;
27
+ const personalRoot = (dir) => path.join(os.homedir(), dir, 'skills');
28
+ const overrides = (dir, stamp) => `~/${dir}/skills/${MAIN} (${stamp || 'no version'}) overrides project skills. Ask the user to remove it`;
29
+ // `c4builder skills` и `--new` (D2, D6): каталог каждого скилла пакета заменяется целиком — так уходят
30
+ // файлы прошлых версий, а чужие скиллы рядом не трогаются. `.claude` — только под Claude Code или если
31
+ // он уже есть: Claude Code не читает `.agents`, а создавать `.claude/` в чужом проекте незачем.
32
+ export default (root = process.cwd()) => {
33
+ const names = fs
34
+ .readdirSync(SKILLS_DIR, { withFileTypes: true })
35
+ .filter((d) => d.isDirectory())
36
+ .map((d) => d.name);
37
+ const dirs = ['.agents'];
38
+ if (process.env.CLAUDECODE || fs.existsSync(path.join(root, '.claude')))
39
+ dirs.push('.claude');
40
+ for (const dir of dirs) {
41
+ for (const name of names) {
42
+ const target = path.join(root, dir, 'skills', name);
43
+ fs.rmSync(target, { recursive: true, force: true });
44
+ fs.cpSync(path.join(SKILLS_DIR, name), target, { recursive: true });
45
+ const file = path.join(target, 'SKILL.md');
46
+ const text = fs.readFileSync(file, 'utf8');
47
+ fs.writeFileSync(file, text.replace(/^description:.*$/m, `$&\nmetadata:\n generatedBy: "${pkg.version}"`));
48
+ console.log(`installed ${path.relative(process.cwd(), target)}`);
49
+ }
50
+ // Личную копию не трогаем: её поставил пользователь, удалять — ему (D3).
51
+ const personal = stampIn(personalRoot(dir));
52
+ if (personal !== undefined && outdated(personal))
53
+ console.error(overrides(dir, personal));
54
+ }
55
+ };
56
+ // Строка о скиллах при старте сборки и `site` под агентом (D3–D5), undefined — молчим. Агент — только
57
+ // по окружению: флаги --agent/--no-agent управляют замечаниями со страницы, а не этим.
58
+ export const skillsNotice = (cwd = process.cwd()) => {
59
+ const agent = detectAgent(process.env, {});
60
+ if (!agent.on || disabled())
61
+ return undefined;
62
+ const dir = agent.name === 'claude-code' ? '.claude' : '.agents';
63
+ // Личная копия побеждает проектную при одинаковом имени (так выбирает Claude Code).
64
+ const personal = stampIn(personalRoot(dir));
65
+ if (personal !== undefined)
66
+ return outdated(personal) ? `${overrides(dir, personal)}, then run: ${RUN}` : undefined;
67
+ // Проектная — ближайшая от cwd вверх до корня git-репозитория: агента обычно запускают в корне
68
+ // репозитория, а сборку — в подкаталоге документации, и он видит скиллы обоих уровней.
69
+ let stamp;
70
+ for (let d = path.resolve(cwd); stamp === undefined; d = path.dirname(d)) {
71
+ stamp = stampIn(path.join(d, dir, 'skills'));
72
+ if (fs.existsSync(path.join(d, '.git')) || path.dirname(d) === d)
73
+ break;
74
+ }
75
+ if (stamp === undefined)
76
+ return `c4builder agent skills are not installed here. Ask the user, then run: ${RUN}`;
77
+ if (!outdated(stamp))
78
+ return undefined;
79
+ return `c4builder agent skills here are from ${stamp || 'an unknown version'} (current ${pkg.version}). Ask the user, then run: ${RUN}`;
80
+ };
@@ -10,6 +10,7 @@ import cmdCheck from "./commands/check.js";
10
10
  import cmdList from "./commands/list.js";
11
11
  import cmdSite from "./commands/site.js";
12
12
  import cmdFeedback from "./commands/feedback.js";
13
+ import cmdSkills, { skillsNotice } from "./commands/skills.js";
13
14
  import { detectAgent } from "./agent.js";
14
15
  import { cmdUpdate, pendingUpdate, startUpdateCheck } from "./update.js";
15
16
  import cmdCollect from "./wizard/collect.js";
@@ -30,7 +31,7 @@ import { packageJson as pkg } from "../util/paths.js";
30
31
  import { outputDirs, parseConfig } from "../config/options.js";
31
32
  import { isValidPort } from "../config/schema.js";
32
33
  // Позиционные подкоманды: allowExcessArguments пропускает любые, список — единственный фильтр.
33
- const COMMANDS = ['check', 'jre', 'site', 'new', 'config', 'update', 'feedback'];
34
+ const COMMANDS = ['check', 'jre', 'site', 'new', 'config', 'update', 'feedback', 'skills'];
34
35
  const intro = () => {
35
36
  console.log(chalk.blue(figlet.textSync('c4builder')));
36
37
  console.log(chalk.gray('Blow up your software documentation writing skills'));
@@ -167,6 +168,9 @@ export default async () => {
167
168
  // Замечания со страницы `site -w` — тоже до Configstore: команду запускают в любом каталоге.
168
169
  if (cmd === 'feedback')
169
170
  return cmdFeedback(path.join(process.cwd(), opts.configFile ?? '.c4builder'), opts);
171
+ // Установка скиллов — до Configstore: ставит их и в каталог без проекта.
172
+ if (cmd === 'skills')
173
+ return cmdSkills();
170
174
  // `site`/`new`/`config` — позиционные синонимы одноимённых флагов: эту форму печатают
171
175
  // подсказки CLI и учат README, шаблон и скиллы.
172
176
  if (cmd)
@@ -247,6 +251,10 @@ export default async () => {
247
251
  }
248
252
  await cmdCollect(currentConfig, conf, opts);
249
253
  if (!opts.config) {
254
+ // При старте, а не при выходе, как уведомление о версии: `site -w` живёт до остановки.
255
+ const skills = skillsNotice();
256
+ if (skills)
257
+ process.stderr.write(`${skills}\n`);
250
258
  let isBuilding = false;
251
259
  let attemptedWatchBuild = false;
252
260
  // Опции сборки после визарда: строгий разбор итогового конфига. Штатно валиден
@@ -19,7 +19,7 @@ const npmSync = (args, options) => {
19
19
  };
20
20
  // CI ставят GitLab CI, GitHub Actions и большинство CI; C4BUILDER_DOCKER — наш Dockerfile;
21
21
  // NO_UPDATE_NOTIFIER — общая конвенция с пакетом update-notifier.
22
- const disabled = () => !!(process.env.CI || process.env.NO_UPDATE_NOTIFIER || process.env.C4BUILDER_DOCKER);
22
+ export const disabled = () => !!(process.env.CI || process.env.NO_UPDATE_NOTIFIER || process.env.C4BUILDER_DOCKER);
23
23
  const cacheFile = () => path.join(process.env.XDG_CONFIG_HOME || path.join(os.homedir(), '.config'), 'c4builder', 'dist-tags.json');
24
24
  // Порядок semver без зависимости semver: numeric-коллатор сравнивает цифровые серии численно
25
25
  // (0.10.0 > 0.9.0, rc.10 > rc.2); стабильная версия старше пререлиза того же ядра.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@alfacapital-tech/c4builder",
3
- "version": "0.9.0-rc.4",
3
+ "version": "0.10.0-rc.1",
4
4
  "description": "A CLI tool designed to compile a folder structure of markdowns and plant uml files into a site, single file markdown or a collection of markdowns with links",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -13,6 +13,7 @@
13
13
  "!template/docs",
14
14
  "!template/.c4builder",
15
15
  "vendor/",
16
+ "skills/",
16
17
  "README.MD",
17
18
  "license"
18
19
  ],
@@ -0,0 +1,199 @@
1
+ ---
2
+ name: c4builder
3
+ description: Work on a c4builder architecture-docs project - C4 model diagrams in PlantUML (C4-PlantUML stdlib) or D2, BPMN process diagrams, Mermaid diagrams, plus markdown, built into a docsify site or markdown files. Use when creating or editing .puml, .iuml, .d2, .bpmn, .mmd or .md files in a project that has a .c4builder config, when changing .c4builder settings or plugins (openspec, openapi), or when building, validating or previewing the docs. Teaches the edit, c4builder check, build loop and the C4-PlantUML conventions.
4
+ ---
5
+
6
+ # c4builder
7
+
8
+ c4builder compiles a folder tree of markdown and diagrams into documentation: a docsify
9
+ site, a collection of markdown files with navigation and/or one complete markdown file.
10
+ Installing or repairing the CLI itself is the `c4builder-setup` skill.
11
+
12
+ A c4builder project is a folder with a `.c4builder` file (JSON config) next to the source
13
+ folder (`rootFolder`, `src` by default).
14
+
15
+ ## Project layout
16
+
17
+ ```text
18
+ .c4builder config (JSON) -> references/config.md
19
+ .c4builder.cache render checksums (git-ignored)
20
+ src/ rootFolder: one folder = one page
21
+ context.md page text
22
+ context.puml diagram attached to the same page
23
+ styles.iuml shared PlantUML styles, included by diagrams
24
+ _c4lib.d2 "_" prefix: never rendered or published, still includable
25
+ 1 Internet Banking System/
26
+ system.md
27
+ system.puml
28
+ API Application/
29
+ container.md
30
+ container.puml
31
+ docs/ distFolder: generated, wiped on every build
32
+ ```
33
+
34
+ How the source tree becomes pages:
35
+
36
+ - Every folder is one page and one node in the navigation; the page title is the folder
37
+ name (the root page is `homepageName`). Siblings are sorted by name — prefix folders with
38
+ numbers (`1 …`, `2 …`) to order them.
39
+ - All `.md` files of a folder are concatenated into its page.
40
+ - Every `.puml` / `.d2` / `.bpmn` / `.mmd` in a folder is rendered and attached to the page (on top by
41
+ default, `diagramsOnTop`), unless the markdown places it explicitly with
42
+ `![name](container.puml)` — then it appears exactly there.
43
+ - Files and folders starting with `_` are skipped (use it for shared libraries and drafts);
44
+ `CLAUDE.md` is skipped too. Other files (images, `.iuml`) are copied next to the page —
45
+ keep their names unique across the project.
46
+ - `foo.puml`, `foo.d2`, `foo.bpmn` and `foo.mmd` in one folder render to the same image name → build error.
47
+ - Never edit `docs/` (or whatever `distFolder` is): every build regenerates it.
48
+
49
+ ## The loop: edit → check → build
50
+
51
+ 1. **Edit** markdown and diagrams under `src/`.
52
+ 2. **Check every diagram you changed** — fast, no project build, writes nothing:
53
+
54
+ ```bash
55
+ c4builder check src/context.puml "src/1 Internet Banking System/system.puml"
56
+ ```
57
+
58
+ Exit code 0 means every file compiles. Otherwise each broken file is reported as
59
+ `✗ <file>: line <N>: <message>` (PlantUML lines count from the top of the file). Errors
60
+ in a `.iuml` carry no line number; D2 errors end with `<file>:<line>:<col>: <message>`;
61
+ BPMN problems are `✗ <file>: <element id> [<rule>] <description>`, one line each;
62
+ mermaid errors are `✗ <file>: line <N>: <message>`.
63
+ Fix and re-run until the exit code is 0. A changed `.iuml` is checked directly too: a
64
+ styles file calling C4 macros (`UpdateElementStyle`) is checked with the C4 stdlib
65
+ included. Same engines as the build (bundled PlantUML jar, bundled D2, BPMN pipeline, mermaid), no
66
+ `.c4builder` needed.
67
+ 3. **Build** the whole project:
68
+
69
+ ```bash
70
+ c4builder
71
+ ```
72
+
73
+ With a complete `.c4builder` (written by `c4builder --new --name <name> -y` or by the
74
+ first interactive run) this is a one-off, non-interactive build. A missing or partial
75
+ config starts an interactive wizard — do not drive it, ask the user or write the full
76
+ config (references/config.md). A diagram that fails here aborts the build with a long
77
+ Java stack trace and keeps the previous output in `docs_bk/`; run `c4builder check` on
78
+ the changed files to get the short message.
79
+ 4. **Look at the result** in `docs/`: `docs/<folder>/README.md` (markdown collection),
80
+ `docs/index.html` + `docs/<folder>/<folder>.md` (site), `docs/<folder>/<diagram>.svg`.
81
+ 5. **Live preview for a human:** `c4builder --site -w` builds, serves on
82
+ `http://localhost:3000` (`webPort`, or `-p <n>`), rebuilds on save and reloads the
83
+ browser; `-o` opens it. It never exits — start it in the background or leave it to the
84
+ user. `c4builder site` builds and serves without watching (also never exits). In `-w` a
85
+ human can select text on a page and add a question: it lands in the source `.md` under the
86
+ `questionsHeading` section (`Open questions` by default) — read it there, not in `docs/`.
87
+
88
+ ## Feedback from the page
89
+
90
+ When the user wants to look at the pages and tell you what to fix, use the `c4builder-review`
91
+ skill (`/c4builder-review [change-id|page]`): it checks the server, gives the link to the page and
92
+ runs the batch loop.
93
+
94
+ In short: under an agent (`CLAUDECODE`, `CODEX_THREAD_ID`, `GEMINI_CLI`, `OPENCODE`, `COPILOT_CLI`,
95
+ `AI_AGENT`, or `--agent`) `c4builder --site -w` adds a **Feedback** button to text selected on a
96
+ page. The comments do not go into the files: `c4builder feedback --wait --as <name>`, run in the
97
+ background with your change or task as `<name>`, exits with one batch on stdout. Apply it to the
98
+ sources, run the command again with the same name and stop on `Decision: approved`.
99
+
100
+ ## Writing C4 diagrams (PlantUML)
101
+
102
+ ```plantuml
103
+ @startuml
104
+ !include <C4/C4_Container>
105
+ !include ../styles.iuml
106
+
107
+ Person(user, "Customer", "Uses the web app")
108
+ System_Boundary(shop, "Shop") {
109
+ Container(web, "Web App", "TypeScript", "Catalog and checkout")
110
+ ContainerDb(db, "Database", "PostgreSQL", "Orders")
111
+ }
112
+ Rel(user, web, "Uses", "HTTPS")
113
+ Rel(web, db, "Reads/writes", "SQL")
114
+ @enduml
115
+ ```
116
+
117
+ - Include C4 from the PlantUML stdlib: `!include <C4/C4_Context>`, `<C4/C4_Container>`,
118
+ `<C4/C4_Component>`, `<C4/C4_Dynamic>`, `<C4/C4_Deployment>`. It is bundled in the jar —
119
+ builds work offline. Never `!include https://…` (network on every build, breaks CI).
120
+ - Shared look lives in one `.iuml` (the template's `src/styles.iuml`), included **after**
121
+ the C4 include by a path relative to the diagram: `!include styles.iuml` from `src/`,
122
+ `!include ../styles.iuml` one level down.
123
+ - One diagram per file, `@startuml` … `@enduml`, file name = image name.
124
+ - Non-Latin text (Cyrillic etc.) works: sources are UTF-8, the bundled font covers it.
125
+
126
+ Details — sequence/class diagrams, D2, fonts, PNG output: read
127
+ [references/diagrams.md](references/diagrams.md) when writing anything beyond a plain
128
+ C4-PlantUML diagram.
129
+
130
+ ## Business processes (BPMN)
131
+
132
+ A `.bpmn` file is BPMN 2.0 XML with **only the semantic model** — no `bpmndi` coordinates:
133
+ the build validates the model and lays it out with horizontal pools and lanes. Read
134
+ [references/bpmn.md](references/bpmn.md) before creating or editing any `.bpmn` file: source
135
+ format, pool/lane conventions and how to fix every `c4builder check` message.
136
+
137
+ ## Mermaid
138
+
139
+ `.mmd` files and ```` ```mermaid ```` blocks in pages and OpenSpec artifacts are rendered at
140
+ build time into images (real mermaid, no browser). Use them for flows, sequences, states and
141
+ ER inside the docs; keep the C4 model in PlantUML. Read
142
+ [references/mermaid.md](references/mermaid.md) before writing mermaid: supported types,
143
+ fixed config keys and the `c4builder check` loop.
144
+
145
+ ## Config and plugins
146
+
147
+ - Read [references/config.md](references/config.md) before editing `.c4builder`: unknown
148
+ keys are **silently dropped**, so a typo does nothing. `c4builder --list` prints the
149
+ current config.
150
+ - Read [references/plugins.md](references/plugins.md) when the project has or needs
151
+ `plugins` — `openspec` (OpenSpec store as a site section) or `openapi` (swagger-ui pages).
152
+
153
+ ## Reading an existing architecture
154
+
155
+ With `generateLLMS: true` the built site has `llms.txt` (every page in sidebar order, links
156
+ to its `.md`) and `llms-full.txt` (all pages in one file, diagrams inlined as PlantUML/D2/BPMN/Mermaid
157
+ source, shared local includes once in an appendix). To answer questions about a documented
158
+ system, read `llms-full.txt` from the site or `distFolder` instead of crawling pages or
159
+ images: the C4 source (`Person`, `System`, `Rel`) is the model itself.
160
+
161
+ ## New version notice
162
+
163
+ When c4builder output ends with a stderr line
164
+
165
+ ```text
166
+ c4builder <new> is available (current <current>). Run: c4builder update
167
+ ```
168
+
169
+ a newer c4builder is published. Tell the user. Run `c4builder update` only when the user asks
170
+ for it: it reinstalls the global CLI. The notice changes neither stdout nor the exit code.
171
+
172
+ ## Skills notice
173
+
174
+ When a build or `c4builder site` run by an agent starts with one of these stderr lines
175
+
176
+ ```text
177
+ c4builder agent skills are not installed here. Ask the user, then run: c4builder skills
178
+ c4builder agent skills here are from <stamp> (current <version>). Ask the user, then run: c4builder skills
179
+ ~/.claude/skills/c4builder (<stamp|no version>) overrides project skills. Ask the user to remove it, then run: c4builder skills
180
+ ```
181
+
182
+ the c4builder skills you work with are missing, older than the CLI, or shadowed by a stale personal
183
+ copy (`~/.agents/skills/c4builder` for agents other than Claude Code). Tell the user. Run
184
+ `c4builder skills` only when the user agrees: it writes the skills of the installed CLI into
185
+ `.agents/skills/` of the current folder (and `.claude/skills/` under Claude Code), replacing the
186
+ c4builder skills there. Remove a personal copy only when the user agrees. The notice changes
187
+ neither stdout nor the exit code.
188
+
189
+ ## Common mistakes
190
+
191
+ - Editing generated files in `docs/` instead of `src/`.
192
+ - Remote `!include` URLs instead of `<C4/...>` stdlib includes.
193
+ - Running `c4builder --site -w` or `c4builder feedback --wait --as <name>` in the foreground — the
194
+ agent hangs.
195
+ - Forgetting `c4builder check` and reading a Java stack trace from the full build instead.
196
+ - A page "missing" from the output because its file or folder starts with `_`.
197
+ - `generateLocalImages: false` in a project with `.d2`, `.bpmn` or `.mmd` files — they have no online
198
+ renderer, the build stops with an error.
199
+ - Writing `bpmndi` coordinates into a `.bpmn` — they are ignored; the layout is always automatic.
@@ -0,0 +1,138 @@
1
+ # BPMN reference
2
+
3
+ `.bpmn` files are business processes in BPMN 2.0 notation. Write **only the semantic model**;
4
+ c4builder validates it, lays it out (horizontal pools and lanes, flow left to right) and
5
+ renders it in the standard bpmn.io notation — offline and deterministically.
6
+
7
+ ## Source format
8
+
9
+ - Standard BPMN 2.0 XML, namespace `http://www.omg.org/spec/BPMN/20100524/MODEL`.
10
+ - **No coordinates.** Do not write a `bpmndi:BPMNDiagram` section: it is ignored anyway, the
11
+ build always computes the layout. There is no way to hand-tune positions.
12
+ - `incoming` / `outgoing` elements are optional — connections are taken from
13
+ `sourceRef` / `targetRef` of the flows.
14
+ - `isExecutable="false"`: this is documentation, not an executable process; no Camunda or
15
+ Flowable extensions are needed.
16
+ - Give elements readable ids with a type prefix (`Task_CheckDocuments`, `Gateway_Decision`,
17
+ `Flow_Approved`): every error message points to an id.
18
+
19
+ Minimal example — a pool with two lanes, an external "black-box" pool, a gateway with
20
+ labelled branches, a boundary timer and message flows:
21
+
22
+ ```xml
23
+ <?xml version="1.0" encoding="UTF-8"?>
24
+ <bpmn:definitions xmlns:bpmn="http://www.omg.org/spec/BPMN/20100524/MODEL"
25
+ id="Definitions_Order" targetNamespace="https://example.com/bpmn/order">
26
+ <bpmn:collaboration id="Collaboration_Order">
27
+ <bpmn:participant id="Pool_Shop" name="Shop" processRef="Process_Order" />
28
+ <bpmn:participant id="Pool_Bank" name="Payment bank" />
29
+ <bpmn:messageFlow id="Message_Charge" name="Charge request"
30
+ sourceRef="Task_Charge" targetRef="Pool_Bank" />
31
+ <bpmn:messageFlow id="Message_Result" name="Payment result"
32
+ sourceRef="Pool_Bank" targetRef="Task_AwaitPayment" />
33
+ </bpmn:collaboration>
34
+ <bpmn:process id="Process_Order" name="Order" isExecutable="false">
35
+ <bpmn:laneSet id="LaneSet_Shop">
36
+ <bpmn:lane id="Lane_Sales" name="Sales">
37
+ <bpmn:flowNodeRef>Start_Order</bpmn:flowNodeRef>
38
+ <bpmn:flowNodeRef>Task_Charge</bpmn:flowNodeRef>
39
+ <bpmn:flowNodeRef>Task_AwaitPayment</bpmn:flowNodeRef>
40
+ <bpmn:flowNodeRef>Gateway_Paid</bpmn:flowNodeRef>
41
+ <bpmn:flowNodeRef>End_Cancelled</bpmn:flowNodeRef>
42
+ <bpmn:flowNodeRef>End_Expired</bpmn:flowNodeRef>
43
+ </bpmn:lane>
44
+ <bpmn:lane id="Lane_Warehouse" name="Warehouse">
45
+ <bpmn:flowNodeRef>Task_Ship</bpmn:flowNodeRef>
46
+ <bpmn:flowNodeRef>End_Shipped</bpmn:flowNodeRef>
47
+ </bpmn:lane>
48
+ </bpmn:laneSet>
49
+ <bpmn:startEvent id="Start_Order" name="Order placed" />
50
+ <bpmn:sendTask id="Task_Charge" name="Request payment" />
51
+ <bpmn:receiveTask id="Task_AwaitPayment" name="Await payment" />
52
+ <bpmn:boundaryEvent id="Timer_PaymentTimeout" name="1 hour" attachedToRef="Task_AwaitPayment">
53
+ <bpmn:timerEventDefinition id="TimerDef_PaymentTimeout" />
54
+ </bpmn:boundaryEvent>
55
+ <bpmn:exclusiveGateway id="Gateway_Paid" name="Paid?" />
56
+ <bpmn:userTask id="Task_Ship" name="Ship order" />
57
+ <bpmn:endEvent id="End_Shipped" name="Order shipped" />
58
+ <bpmn:endEvent id="End_Cancelled" name="Order cancelled" />
59
+ <bpmn:endEvent id="End_Expired" name="Payment expired" />
60
+ <bpmn:sequenceFlow id="Flow_Start" sourceRef="Start_Order" targetRef="Task_Charge" />
61
+ <bpmn:sequenceFlow id="Flow_Charged" sourceRef="Task_Charge" targetRef="Task_AwaitPayment" />
62
+ <bpmn:sequenceFlow id="Flow_Answered" sourceRef="Task_AwaitPayment" targetRef="Gateway_Paid" />
63
+ <bpmn:sequenceFlow id="Flow_Yes" name="Yes" sourceRef="Gateway_Paid" targetRef="Task_Ship" />
64
+ <bpmn:sequenceFlow id="Flow_No" name="No" sourceRef="Gateway_Paid" targetRef="End_Cancelled" />
65
+ <bpmn:sequenceFlow id="Flow_Timeout" sourceRef="Timer_PaymentTimeout" targetRef="End_Expired" />
66
+ <bpmn:sequenceFlow id="Flow_Shipped" sourceRef="Task_Ship" targetRef="End_Shipped" />
67
+ </bpmn:process>
68
+ </bpmn:definitions>
69
+ ```
70
+
71
+ Elements that render: start/end/intermediate events with timer, message, error and other
72
+ definitions, boundary events, `task`, `userTask`, `serviceTask`, `sendTask`, `receiveTask`,
73
+ `manualTask`, `scriptTask`, `businessRuleTask`, exclusive/parallel/inclusive/event-based
74
+ gateways, `subProcess`, `textAnnotation` with `association`, `dataObjectReference`.
75
+ `complexGateway` is not supported by the layout engine.
76
+
77
+ ## Modelling conventions
78
+
79
+ - **Pool = organization**, **lane = role or unit inside it.** An external party whose
80
+ internals you do not describe is a pool without `processRef` (a black box).
81
+ - **Between pools — only message flows.** Sequence flows stay inside one pool; a message
82
+ flow may target a node or the black-box pool itself.
83
+ - **Lanes:** when a process has lanes, list every flow node in exactly one lane
84
+ (`flowNodeRef`). Boundary events may be left out — they sit on their task.
85
+ - **Label everything:** events, tasks, participants, lanes and diverging gateways need a
86
+ `name`. Label every outgoing flow of an exclusive/inclusive gateway (`Yes` / `No`).
87
+ - **Exactly the start and end you mean:** a process needs a start and an end event; a node
88
+ without incoming or outgoing flows is an error, not an implicit start or end.
89
+ - **Overview plus detail** instead of one huge diagram: above ~40 nodes the picture stops
90
+ being readable. Sub-processes are always drawn collapsed — describe their inside in a
91
+ separate `.bpmn` on its own page.
92
+
93
+ ## The loop
94
+
95
+ ```bash
96
+ c4builder check "src/3 Processes/order.bpmn"
97
+ ```
98
+
99
+ `check` runs the whole pipeline — parse, rules, layout and rendering — without a project.
100
+ Exit code 0 means the diagram builds; warnings are printed but do not change the code. Each
101
+ problem is one line:
102
+
103
+ ```text
104
+ ✗ src/3 Processes/order.bpmn: Task_Ship [no-disconnected] Element is not connected
105
+ ⚠ src/3 Processes/order.bpmn: Flow_No [c4builder/gateway-flow-labels] Outgoing flow of a diverging gateway has no label
106
+ ```
107
+
108
+ Format: `<file>: <element id> [<rule>] <description>`. Fix the element with that id and run
109
+ `check` again until the exit code is 0.
110
+
111
+ | Message | Fix |
112
+ |---|---|
113
+ | `[no-disconnected]`, `[no-implicit-start]`, `[no-implicit-end]` | connect the node with sequence flows (check `sourceRef`/`targetRef` spelling) |
114
+ | `[start-event-required]`, `[end-event-required]` | add the missing start or end event |
115
+ | `[label-required]` | add a `name` |
116
+ | `[c4builder/lane-membership]` | list the node in exactly one `flowNodeRef` of its process lanes |
117
+ | `[c4builder/sequence-flow-in-pool]` | replace the sequence flow between pools with a `messageFlow` in the collaboration |
118
+ | `[c4builder/message-flow-between-pools]` | a message flow inside one pool must be a sequence flow |
119
+ | `[c4builder/gateway-flow-labels]` (warning) | name the gateway's outgoing flows |
120
+ | `[no-inclusive-gateway]` (warning) | prefer exclusive or parallel gateways where possible |
121
+ | `X: unresolved reference <Y>` | element `X` refers to an id `Y` that does not exist |
122
+ | `invalid BPMN XML: …` | the file is not well-formed XML or not BPMN 2.0 |
123
+ | `layout failed: …` / `layout lost N element(s): …` | the layout engine could not place the model: simplify it, split it into overview and detail, or move the listed elements |
124
+
125
+ The rule set is fixed (bpmnlint `recommended` without `no-bpmndi`, plus the `c4builder/*`
126
+ rules) and is the same in `check` and in the build — there is no project config for it.
127
+
128
+ ## Output and dependencies
129
+
130
+ - The image is `<name>.svg` (or `.png` with `diagramFormat: png`) next to the page; place
131
+ it inline with `![title](name.bpmn)`. In `llms-full.txt` the source appears in an `xml`
132
+ block.
133
+ - Text is measured with the bundled Nimbus Sans: the SVG is identical on every machine;
134
+ `useSystemFonts` does not affect BPMN.
135
+ - The engine packages (`bpmn-js`, `bpmn-moddle`, `bpmnlint`, `bpmn-auto-layout`, `jsdom`)
136
+ are optional npm dependencies, loaded only when the project has a `.bpmn`. An install with
137
+ `--omit=optional` stops such a build with a hint to reinstall c4builder.
138
+ - Like D2, BPMN has no online renderer: `generateLocalImages` must stay `true`.
@@ -0,0 +1,111 @@
1
+ # `.c4builder` reference
2
+
3
+ `.c4builder` is a JSON file in the project root (another path: `c4builder -c <path>`).
4
+ `c4builder --list` prints the effective values, `c4builder --docs` explains the wizard
5
+ questions, `c4builder --config` re-runs the wizard (interactive — prefer editing the JSON).
6
+
7
+ Validation rules:
8
+
9
+ - **Unknown keys are silently dropped.** A misspelled key (`generateWeb`) changes nothing —
10
+ compare every key with the tables below.
11
+ - A wrong type (a string where a boolean is expected, a bad port) fails the build with a
12
+ message naming the key. `null` means "not set" → default.
13
+ - The wizard asks for every key it knows that is **missing** from the file, so a
14
+ non-interactive build needs a complete config — like the one
15
+ `c4builder --new --name <name> -y` writes (below). `hasRun: true` (set after the first
16
+ successful build) makes invalid values fail the build instead of being asked again.
17
+
18
+ ## Sources and outputs
19
+
20
+ | Key | Default | Meaning |
21
+ |---|---|---|
22
+ | `projectName` | — | documentation title; name of the complete markdown file |
23
+ | `homepageName` | `Overview` | title of the root page |
24
+ | `rootFolder` | `src` | source folder |
25
+ | `distFolder` | `docs` | output folder — **wiped on every build** |
26
+ | `generateMD` | `true` | markdown collection: `README.md` per folder |
27
+ | `generateCompleteMD` | `false` | one `<projectName>.md` with everything |
28
+ | `generateWEB` | `true` | docsify site (`index.html`, `<folder>.md` per folder) |
29
+ | `generateLLMS` | `true` in new projects, off when absent | `llms.txt` (page index) and `llms-full.txt` (full text, diagrams as source) in the site root; needs `generateWEB` |
30
+ | `excludeOtherFiles` | `false` | do not copy non-diagram, non-markdown files (images…) |
31
+
32
+ ## Page content
33
+
34
+ | Key | Default | Meaning |
35
+ |---|---|---|
36
+ | `diagramsOnTop` | `true` | attached diagrams before the text (after a leading `#` title) |
37
+ | `includeBreadcrumbs` | `true` | folder path under the title |
38
+ | `includeNavigation` | `false` | markdown collection: links to parent and children |
39
+ | `includeTableOfContents` | `true` | markdown collection: tree of all pages on every page |
40
+ | `includeLinkToDiagram` | `false` | a link to the image instead of the image |
41
+ | `embedDiagram` | `false` | images inlined as base64 data URIs |
42
+ | `charset` | `UTF-8` | encoding of diagram sources |
43
+
44
+ ## Diagrams
45
+
46
+ | Key | Default | Meaning |
47
+ |---|---|---|
48
+ | `generateLocalImages` | `true` | render locally (Java + bundled PlantUML, bundled D2). `false` = PlantUML images are links to `plantumlServerUrl`; a project with `.d2` files then fails |
49
+ | `plantumlServerUrl` | `https://www.plantuml.com/plantuml` | server for `generateLocalImages: false` |
50
+ | `diagramFormat` | `svg` | `svg` or `png` (PNG is rasterized from SVG; ditaa is always PNG) |
51
+ | `d2Layout` | `dagre` | D2 layout engine: `dagre` or `elk` |
52
+ | `useSystemFonts` | `false` | machine fonts instead of the bundled one — output differs per machine (`--system-fonts` for one run) |
53
+
54
+ ## Site (docsify)
55
+
56
+ | Key | Default | Meaning |
57
+ |---|---|---|
58
+ | `webPort` | `3000` | port of `c4builder --site` (`-p <n>` overrides) |
59
+ | `questionsHeading` | `Open questions` | heading of the section in the source `.md` where `site -w` appends questions left on the page |
60
+ | `uiLanguage` | `auto` | language of the `site -w` page interface: `auto` (browser language), `en` or `ru`; CLI output and feedback batches stay English |
61
+ | `webTheme` | `vendor/vue.css` | docsify theme stylesheet |
62
+ | `supportSearch` | `true` | search box in the sidebar |
63
+ | `repoUrl` | `""` | repository link in the site corner |
64
+ | `executeScript` | `false` | let docsify run `<script>` in pages (forced on by `openapi`) |
65
+ | `docsifyTemplate` | `""` | path to a JS module exporting a function that returns `index.html` |
66
+ | `webFileName` | — | fixed file name for every site page instead of the folder name |
67
+ | `excludeSidebarFolderByPath` | — | array of folder paths, **including** `rootFolder` (`"src/2 Deployment"`), hidden from the sidebar |
68
+
69
+ ## Plugins
70
+
71
+ | Key | Default | Meaning |
72
+ |---|---|---|
73
+ | `plugins` | `[]` | `"name"` or `["name", { options }]` — see [plugins.md](plugins.md). Unlike other keys, a malformed entry always fails the build |
74
+
75
+ Legacy keys (`plantumlVersion`, `generatePDF`, `generateCompletePDF`) only produce a
76
+ warning — remove them when you see one.
77
+
78
+ Complete config written by `c4builder --new --name demo -y` — start from it when adding
79
+ c4builder to an existing repository:
80
+
81
+ ```json
82
+ {
83
+ "projectName": "demo",
84
+ "homepageName": "Overview",
85
+ "rootFolder": "src",
86
+ "distFolder": "docs",
87
+ "generateMD": true,
88
+ "generateCompleteMD": false,
89
+ "generateWEB": true,
90
+ "generateLLMS": true,
91
+ "includeNavigation": false,
92
+ "includeTableOfContents": true,
93
+ "webTheme": "vendor/vue.css",
94
+ "supportSearch": true,
95
+ "repoUrl": "",
96
+ "executeScript": false,
97
+ "docsifyTemplate": "",
98
+ "webPort": "3000",
99
+ "includeBreadcrumbs": true,
100
+ "includeLinkToDiagram": false,
101
+ "diagramsOnTop": true,
102
+ "embedDiagram": false,
103
+ "excludeOtherFiles": false,
104
+ "generateLocalImages": true,
105
+ "plantumlServerUrl": "https://www.plantuml.com/plantuml",
106
+ "diagramFormat": "svg",
107
+ "d2Layout": "dagre",
108
+ "charset": "UTF-8",
109
+ "useSystemFonts": false
110
+ }
111
+ ```
@@ -0,0 +1,77 @@
1
+ # Diagrams reference
2
+
3
+ The backend is chosen by file extension: `.puml` → PlantUML, `.d2` → D2, `.bpmn` → BPMN
4
+ (validation + automatic layout + bpmn-js, see [bpmn.md](bpmn.md)), `.mmd` → mermaid (see
5
+ [mermaid.md](mermaid.md)). All of them can live in one project and one folder (with different
6
+ base names).
7
+
8
+ ## PlantUML and C4-PlantUML
9
+
10
+ Rendering is offline: the PlantUML jar is bundled and runs on Java 17+ with the built-in
11
+ Smetana layout — Graphviz is not used. `!pragma layout elk` needs Java 21.
12
+
13
+ **C4 includes** come from the PlantUML stdlib (C4-PlantUML is inside the jar):
14
+
15
+ | Level | Include | Main macros |
16
+ |---|---|---|
17
+ | System context | `!include <C4/C4_Context>` | `Person`, `System`, `System_Ext`, `Rel` |
18
+ | Container | `!include <C4/C4_Container>` | `Container`, `ContainerDb`, `ContainerQueue`, `System_Boundary` |
19
+ | Component | `!include <C4/C4_Component>` | `Component`, `ComponentDb`, `Container_Boundary` |
20
+ | Dynamic | `!include <C4/C4_Dynamic>` | numbered `Rel` steps |
21
+ | Deployment | `!include <C4/C4_Deployment>` | `Deployment_Node`, `Node` |
22
+
23
+ Each level includes the previous ones. `LAYOUT_WITH_LEGEND()`, `LAYOUT_TOP_DOWN()`,
24
+ `LAYOUT_LEFT_RIGHT()` control layout and legend. Do not include C4 by URL
25
+ (`!include https://…`, `!includeurl`): it needs network on every build and pins nothing.
26
+
27
+ **Shared styles** — one `.iuml` library included after the C4 include, by a path relative
28
+ to the including diagram:
29
+
30
+ ```plantuml
31
+ @startuml
32
+ !include <C4/C4_Context>
33
+ !include ../styles.iuml
34
+ ...
35
+ @enduml
36
+ ```
37
+
38
+ Put `skinparam`s and `UpdateElementStyle(...)` / `AddElementTag(...)` calls there. A `.iuml`
39
+ is never rendered on its own; it is copied to the output like any other file (prefix it
40
+ with `_` to keep it out). Editing an included file re-renders every diagram that includes
41
+ it.
42
+
43
+ **Other PlantUML diagrams** (sequence, class, activity, state, ditaa…) work the same way —
44
+ any `@startuml` file is rendered. ditaa (`@startditaa`) always produces PNG.
45
+
46
+ **Non-Latin text.** Sources are read as UTF-8 (`charset`). The bundled Nimbus Sans font
47
+ covers Latin, Cyrillic and Greek, so diagrams look identical on every machine. Scripts it
48
+ lacks (e.g. CJK) need `useSystemFonts: true` (or `c4builder --system-fonts` for one run)
49
+ and a system font that has them — the output then depends on the machine.
50
+
51
+ ## D2
52
+
53
+ `.d2` files are rendered by the bundled D2 engine (WASM → SVG), which is the optional npm
54
+ dependency `@terrastruct/d2`. A `.d2` file in a project without it stops the build with an
55
+ install hint. D2 has no online renderer, so `generateLocalImages` must stay `true`.
56
+
57
+ - Imports: `@file` / spread `...@file` (without the `.d2` extension), resolved by
58
+ c4builder itself — no network. Keep shared classes in a `_`-prefixed file
59
+ (`src/_c4lib.d2`) and import it with `...@../_c4lib` from a nested folder.
60
+ - Layout: `d2Layout` — `dagre` (default) or `elk`.
61
+ - Validate like PlantUML: `c4builder check path/to/diagram.d2`.
62
+
63
+ ## Placement and output
64
+
65
+ - Every diagram of a folder is attached to the folder's page; `![title](name.puml)` /
66
+ `![title](name.d2)` / `![title](name.bpmn)` / `![title](name.mmd)` in a markdown file of the same folder places it
67
+ inline instead.
68
+ - Image file = diagram base name + `.svg` (or `.png` with `diagramFormat: png`), next to
69
+ the page in the output.
70
+ - A ```` ```plantuml ```` block in a page `.md` is rendered at build time like a `.puml`
71
+ file and replaced by its image in every output (`@startuml` optional, `!include` relative
72
+ to the page folder, a broken block becomes a placeholder plus a warning). To show diagram
73
+ source as code, fence it as `puml` or `text` — those, like `d2` blocks, stay code. A
74
+ ```` ```mermaid ```` block is rendered the same way ([mermaid.md](mermaid.md)).
75
+ - `embedDiagram: true` inlines images as base64; `includeLinkToDiagram: true` replaces
76
+ images with links.
77
+ - Unchanged diagrams are reused from the previous build (checksums in `.c4builder.cache`).
@@ -0,0 +1,78 @@
1
+ # Mermaid reference
2
+
3
+ Mermaid diagrams are rendered **at build time** by real mermaid (the official
4
+ `@mermaid-js/tiny` build) running in jsdom — no browser, no network. Text is measured with
5
+ the bundled Nimbus Sans, so the SVG is identical on every machine. Every output (site,
6
+ markdown, complete markdown, PNG) gets an image; the browser never sees diagram source.
7
+
8
+ ## When mermaid, when PlantUML
9
+
10
+ - **C4 model** (context, containers, components, deployment) — PlantUML with the C4 stdlib,
11
+ see [diagrams.md](diagrams.md). Mermaid C4 diagrams may lay out differently than in a browser.
12
+ - **Mermaid** — flows and processes inside documentation and OpenSpec artifacts:
13
+ `flowchart`/`graph` (with `subgraph`), `sequenceDiagram`, `stateDiagram-v2`, `erDiagram`,
14
+ `classDiagram`, `gantt`, `pie` and other types of the tiny build.
15
+ - **Business processes with pools and lanes** — BPMN, see [bpmn.md](bpmn.md).
16
+
17
+ ## Two sources
18
+
19
+ - **A `.mmd` file** in a page folder, like `.puml`/`.d2`/`.bpmn`: rendered to `<name>.svg`
20
+ (or `.png` with `diagramFormat: png`) and attached to the page, or placed inline with
21
+ `![title](flow.mmd)`. `flow.mmd` and `flow.puml` in one folder collide on the image name.
22
+ - **A ```` ```mermaid ```` block** in a page `.md` or in an OpenSpec artifact (`design.md`,
23
+ `proposal.md`, specs): replaced by its image in every output, like a ```` ```plantuml ````
24
+ block. To show mermaid source as code instead, fence it as `text`.
25
+
26
+ ```mermaid
27
+ sequenceDiagram
28
+ participant К as Клиент
29
+ participant Б as Банк
30
+ К->>Б: Заявка на счёт
31
+ Note right of Б: проверка анкеты
32
+ Б-->>К: Счёт открыт
33
+ ```
34
+
35
+ ## Conventions
36
+
37
+ - Keep labels short. A label longer than ~200 px wraps at spaces; a single long word
38
+ without spaces is split by mermaid character by character.
39
+ - Non-Latin text (Cyrillic etc.) works in ids and labels.
40
+ - The look is fixed: `look: classic`, theme `default`, SVG text labels. `%%{init: …}%%` and
41
+ frontmatter `config:` cannot change `look`, `htmlLabels`, `fontFamily`, `securityLevel` or
42
+ `themeCSS`; other keys (`theme`, `flowchart.curve`, spacing) work as in mermaid.
43
+ - Not supported: `mindmap`, `architecture` and KaTeX math (`$$…$$`) — they are not in the
44
+ tiny build and fail with an explicit `unsupported mermaid …` error.
45
+ - Clicks, tooltips and links are not interactive: the image is static.
46
+
47
+ ## The loop
48
+
49
+ ```bash
50
+ c4builder check "src/3 Processes/flow.mmd"
51
+ ```
52
+
53
+ `check` parses and renders the file exactly like the build, without a project. Exit code 0
54
+ means the diagram builds. Errors carry the line of the file (frontmatter and comments
55
+ counted):
56
+
57
+ ```text
58
+ ✗ src/3 Processes/flow.mmd: line 3: ...A --> B B -->> ((C; Expecting 'AMP', 'COLON', 'PIPE', ..., got 'TAGEND'
59
+ ✗ src/3 Processes/map.mmd: line 1: unsupported mermaid diagram type 'mindmap'
60
+ ```
61
+
62
+ Fix the line and run `check` again until the exit code is 0, then build. A
63
+ ```` ```mermaid ```` block cannot be checked on its own: build the project and read the
64
+ warnings, or copy the block into a temporary `.mmd`.
65
+
66
+ - An error in a `.mmd` file fails the build with the file path and line.
67
+ - An error in a ```` ```mermaid ```` block does not: the build exits with 0, the image is
68
+ a placeholder with the error, and the log has a warning naming the source `.md`.
69
+
70
+ ## Output and dependencies
71
+
72
+ - In `llms-full.txt` a mermaid diagram (file or block) appears as its source in a
73
+ `mermaid` block.
74
+ - The engine package `@mermaid-js/tiny` (about 2.7 MB, with `jsdom`) is an optional npm
75
+ dependency, loaded only when the project has mermaid. An install with `--omit=optional`
76
+ stops a `.mmd` build (and turns blocks into placeholders) with a hint to reinstall c4builder
77
+ without that flag.
78
+ - Like D2 and BPMN, mermaid has no online renderer: `generateLocalImages` must stay `true`.
@@ -0,0 +1,68 @@
1
+ # Plugins reference
2
+
3
+ Plugins add pages from outside `rootFolder` (they go through the normal pipeline: sidebar,
4
+ search, markdown outputs, local diagram rendering) and site assets. They are listed in
5
+ `.c4builder`:
6
+
7
+ ```json
8
+ {
9
+ "plugins": [
10
+ "openspec",
11
+ ["openapi", { "dir": "../contracts", "glob": "*/openapi.yaml" }]
12
+ ]
13
+ }
14
+ ```
15
+
16
+ - An entry is `"name"` or `["name", { options }]`. A malformed entry always fails the build.
17
+ - Name resolution: built-in (`openspec`, `openapi`) → local ESM module
18
+ (`./plugins/my.mjs`, relative to the project) → npm package installed in the project.
19
+ - Options are validated before the build; built-in plugins reject unknown option keys.
20
+ - `${ENV_VAR}` inside string options is replaced from the environment (unset → empty) and
21
+ never printed — keep tokens there, not in the file.
22
+ - Plugin folders are watched by `c4builder --site -w`.
23
+ - Hooks run in list order; an exception aborts the build and names the plugin.
24
+
25
+ ## `openspec` — OpenSpec store as a site section
26
+
27
+ Renders an [OpenSpec](https://github.com/Fission-AI/OpenSpec) store: a summary page
28
+ (counters, task progress), one page per active change (header + first artifact, the other
29
+ artifacts and spec deltas as subpages), the specs tree and the archive. `plantuml` / `d2`
30
+ fenced blocks in artifacts are rendered by the local engines; a broken block gets a
31
+ placeholder image and a warning naming the file instead of failing the build.
32
+
33
+ | Option | Default | Meaning |
34
+ |---|---|---|
35
+ | `dir` | `openspec` | store folder, relative to the project |
36
+ | `mount` | `OpenSpec` | section name and its path in the output |
37
+ | `artifacts` | `["proposal", "design", "tasks"]` | artifact order; the first is shown on the change page |
38
+ | `parentKey` | — | `.openspec.yaml` key pointing at the parent change (e.g. `x-parent`); when set, child changes are nested under their parent in the sidebar, the Changes table and the archive |
39
+ | `groupKey` | — | `.openspec.yaml` key with the change's group (e.g. `x-team`); when set, top-level changes go to `Changes/<group>/<id>`, the Changes table and the archive get per-group sections |
40
+ | `nameKey` | — | `.openspec.yaml` key with the change's name (e.g. `x-name`); when set, the name labels the top-level change and is its page path segment (falls back to the id on `/`, `#`, `?` or a duplicate) |
41
+ | `columns` | — | extra Changes table columns from `.openspec.yaml`: `[{ "key": "x-assignee", "title": "Assignee" }]`; missing value — `—` |
42
+
43
+ ## `openapi` — swagger-ui pages for OpenAPI specs
44
+
45
+ One page per spec found by `glob` (named after the spec's parent folder) plus an index;
46
+ swagger-ui is bundled, readers need no network. Exactly one source — `dir` **or**
47
+ `archive` — is required. It forces `executeScript: true`.
48
+
49
+ | Option | Default | Meaning |
50
+ |---|---|---|
51
+ | `mount` | `API` | section name |
52
+ | `dir` | — | local folder with specs (watched) |
53
+ | `archive` | — | HTTP(S) URL of a `tar.gz` / `zip` archive (e.g. a repository archive) |
54
+ | `subdir` | — | folder inside the archive or `dir` |
55
+ | `headers` | — | HTTP headers for the archive request, e.g. `{"PRIVATE-TOKEN": "${GITLAB_TOKEN}"}` |
56
+ | `glob` | `**/openapi.{yaml,yml,json}` | spec pattern (`**`, `*`, `?`, `{a,b}`); directories starting with a dot are skipped |
57
+
58
+ All `yaml`/`yml`/`json` files of the source are published under `<mount>/_specs/…` with
59
+ their relative layout, so relative `$ref`s keep working. Archive download fails with
60
+ `self-signed certificate in certificate chain` behind a TLS-intercepting proxy → set
61
+ `NODE_EXTRA_CA_CERTS` to the proxy CA bundle.
62
+
63
+ ## Custom plugins
64
+
65
+ A plugin is an ESM module whose default export is an object with `name` and optional
66
+ `options` (zod schema), `watchPaths`, `assets`, `requires`, `afterScan(ctx, opts)` (add
67
+ virtual pages with `ctx.addPage`) and `afterBuild(ctx, opts)`. See the "Writing a plugin"
68
+ section of the c4builder README for the full contract and an example.
@@ -0,0 +1,97 @@
1
+ ---
2
+ name: c4builder-review
3
+ description: Review c4builder pages with a human right on the local site - the human selects text in c4builder --site -w and leaves comments with the Feedback button, the agent receives them in batches with c4builder feedback --wait --as <name>, edits the sources and waits for the next batch until Approve. Use when asked to discuss a change on the site, to show the pages or a design, to review a page, the design or OpenSpec artifacts, when the human says they will leave comments on the page, right after proposing an OpenSpec change in a repository with c4builder, and on /c4builder-review [change-id|page].
4
+ ---
5
+
6
+ # c4builder-review: page comments to the agent
7
+
8
+ The human looks at the pages in the browser (`c4builder --site -w`), selects text and presses:
9
+
10
+ - **Feedback** — a comment to you. It is not written to the files and comes to you in a batch:
11
+ **Send now** sends one comment, **Add to review** → **Submit review** sends several (from several
12
+ pages too), **Approve** means nothing more to change.
13
+ - **Question** — a question for people: c4builder appends it to the source `.md` under the
14
+ `questionsHeading` section (`Open questions` by default). It is not a task for you — leave it
15
+ alone unless asked.
16
+
17
+ Invocation: `/c4builder-review [change-id|page]`. The port is `webPort` from `.c4builder`
18
+ (`<port>` below); when the server runs with `-p <n>`, pass the same `-p <n>` to the commands below.
19
+
20
+ The listener name (`<name>` below) is how the page picks the agent when several share one
21
+ `site -w`: the change id from the argument, otherwise the name of your task. Letters, digits,
22
+ `.`, `_`, `-`, up to 64 characters. Keep one name for the whole review.
23
+
24
+ ## 1. Server
25
+
26
+ ```bash
27
+ curl -s -o /dev/null -w '%{http_code}\n' http://127.0.0.1:<port>/
28
+ ```
29
+
30
+ `200` — the server is up; never start a second one. Otherwise ask the user to start
31
+ `c4builder --site -w`, or ask whether you may start it yourself in the background — many teams
32
+ keep the preview server in the human's hands.
33
+
34
+ ## 2. Link
35
+
36
+ - Argument is an OpenSpec change id: find its page in the build output (`distFolder` from
37
+ `.c4builder`, `docs` by default). The path depends on the `mount`, `groupKey` and `nameKey`
38
+ options of the `openspec` plugin — search, do not guess:
39
+ `find <distFolder> -path '*<change-id>*' -name '*.md' | head` (with `nameKey` the folder carries
40
+ the change's name from its `.openspec.yaml` instead of the id). The address is
41
+ `http://localhost:<port>/#/<path without .md>`.
42
+ - Argument is a page or a section: find it in the build output the same way.
43
+ - No argument: the home page `http://localhost:<port>/`.
44
+
45
+ Give the link, remind in two lines what **Feedback** and **Question** do (see above) and say your
46
+ listener name: with several agents the human picks it in **Send to** on the review bar.
47
+
48
+ ## 3. Wait
49
+
50
+ Start in the background (in Claude Code: Bash with `run_in_background`):
51
+
52
+ ```bash
53
+ c4builder feedback --wait --as <name>
54
+ ```
55
+
56
+ It exits when a batch arrives; its stdout is the batch. Connecting turns the **Feedback** button
57
+ on by itself, the server needs no restart. Errors:
58
+
59
+ - `--as <name> is required` (exit code 2) — the name is missing or invalid: fix it and run again;
60
+ - `no c4builder site -w on …` (exit code 1) — no server or it crashed: back to step 1;
61
+ - `agent feedback is disabled on …` (exit code 1) — the server runs without `-w` or with
62
+ `--no-agent`: ask the user to restart `c4builder --site -w`;
63
+ - `unknown command: feedback` or `unknown option '--as'` — the CLI is older than this skill: tell
64
+ the user, `c4builder update` updates it (only when they agree).
65
+
66
+ ## 4. Batch
67
+
68
+ ```text
69
+ # Page feedback (c4builder)
70
+
71
+ Decision: submitted
72
+ Comments: 1 on 1 page
73
+
74
+ ## 1. OpenSpec/Changes/add-dark-mode/design.md (§ D3)
75
+ Sources: openspec/changes/add-dark-mode/design.md
76
+ Quote: "the selected text"
77
+
78
+ > what to change
79
+ ```
80
+
81
+ Every comment names the site page, the page section (`§`), its source files (`Sources`) and the
82
+ quoted selection; `## General` is the overall comment of a review.
83
+
84
+ - Edit the files listed in `Sources` (change artifacts, `src/` and so on), never the build output.
85
+ No `Sources` — find the quote in the sources (`grep -rn`). The page reloads by itself.
86
+ - Do not copy comments into the questions section: they are instructions to you, not questions
87
+ for people.
88
+ - A comment that is unclear or debatable — ask in the chat instead of guessing; do the rest of the
89
+ batch.
90
+ - After the edits report briefly in the chat what you did for each comment number. Then run
91
+ `c4builder feedback --wait --as <name>` in the background again with the same name — batches
92
+ wait in your mailbox.
93
+
94
+ ## 5. Done
95
+
96
+ `Decision: approved` — nothing more to change: apply the comments of that batch, if any, give a
97
+ summary of the changes by file and stop waiting. Do not commit unless the user asks.
@@ -0,0 +1,130 @@
1
+ ---
2
+ name: c4builder-setup
3
+ description: Install, update and diagnose c4builder (npm package @alfacapital-tech/c4builder), the CLI that builds C4 / PlantUML / D2 architecture docs into a docsify site or markdown, and install its agent skills into a project. Use when asked to install or upgrade c4builder, when the c4builder command is missing or fails to render diagrams, when switching between the stable and release-candidate channels, or when onboarding onto a repository documented with c4builder. Optional argument - channel rc; default is the stable latest. Idempotent - a re-run only verifies.
4
+ ---
5
+
6
+ # c4builder setup
7
+
8
+ Goal: a `c4builder` that really renders diagrams, and its skills in the working project.
9
+ `c4builder --version` alone proves nothing — the smoke build (step 5) does.
10
+
11
+ **Channel.** `latest` — stable (default); `rc` — release candidates (`X.Y.Z-rc.N`). npm
12
+ dist-tags and Docker image tags carry the same names.
13
+
14
+ Every step: check → fix only what is broken.
15
+
16
+ ## 1. Node.js
17
+
18
+ ```bash
19
+ node --version # needs >= 22.17
20
+ ```
21
+
22
+ Missing or older → agree with the user on how to install a current LTS (nvm, OS package
23
+ manager, official installer); do not pick a method silently. Docker users skip to step 3.
24
+
25
+ ## 2. Installed version vs. channel
26
+
27
+ ```bash
28
+ c4builder --version
29
+ npm view @alfacapital-tech/c4builder dist-tags
30
+ ```
31
+
32
+ `npm view` fails with a network or certificate error → the public registry may be closed in
33
+ this network. An organization mirror is configured in the user's npmrc (`npm config get
34
+ registry` shows the current one) or passed per command with `--registry <url>`; ask the user for
35
+ the address, never guess one. The update check of c4builder and `c4builder update` use the same
36
+ npmrc.
37
+
38
+ Installed version equals the channel's tag → skip step 3.
39
+ Installed version is **newer** than the requested channel (an `rc` while `latest` was
40
+ asked for) → that is a downgrade: never do it silently, confirm with the user — they
41
+ probably want the `rc` channel.
42
+
43
+ ## 3. Install / update
44
+
45
+ ```bash
46
+ npm install -g @alfacapital-tech/c4builder@latest # stable
47
+ npm install -g @alfacapital-tech/c4builder@rc # release candidate
48
+ ```
49
+
50
+ - An installed global CLI is updated with `c4builder update`: it installs the newest version
51
+ (`latest`; on a release candidate the newer of `latest` and `rc`). For a project dependency
52
+ or the Docker image it installs nothing and prints the command to use instead. Switching the
53
+ channel is the `npm install -g` line above.
54
+ - Do not pass `--omit=optional`: the D2 engine (`@terrastruct/d2`) is an optional
55
+ dependency; without it a project with `.d2` files stops with an install hint.
56
+ - `c4builder: command not found` after a successful install → the global npm bin folder
57
+ is not on `PATH` (`npm prefix -g` shows the prefix; the binary lives in its `bin`).
58
+
59
+ **Docker instead of npm** — the image ships Node, a JRE, the PlantUML jar, fonts and D2,
60
+ so steps 1 and 4 are not needed. Mount the project into `/pwd`:
61
+
62
+ ```bash
63
+ docker run --rm -v "$PWD:/pwd" ghcr.io/alfacapital-tech/c4builder:latest c4builder
64
+ ```
65
+
66
+ Image tags: `latest`, `rc`, `X.Y.Z`, `edge` (last master commit). The same image works as a
67
+ CI job image — `c4builder` is on `PATH`.
68
+
69
+ ## 4. Java for PlantUML
70
+
71
+ Diagrams are rendered by the bundled PlantUML jar → Java 17+ is needed (`JAVA_HOME` is
72
+ checked first, then `PATH`). Graphviz is **not** needed.
73
+
74
+ ```bash
75
+ java -version
76
+ c4builder jre install
77
+ ```
78
+
79
+ `c4builder jre install` reports a suitable system java and stops; otherwise it downloads a
80
+ private Temurin JRE into the user cache once — tell the user it did. A broken system java
81
+ can be bypassed with `c4builder jre install --force` (downloads even when java is present).
82
+ `c4builder jre info` prints the managed JRE parameters as JSON (Temurin major, cache
83
+ folder) — use it to key a CI cache.
84
+
85
+ Download fails with a certificate error (TLS-intercepting proxy) → set
86
+ `NODE_EXTRA_CA_CERTS` to the proxy's CA bundle; Node reads neither the system store nor
87
+ `SSL_CERT_FILE`.
88
+
89
+ ## 5. Smoke build
90
+
91
+ Build the bundled template project in a temporary folder:
92
+
93
+ ```bash
94
+ cd "$(mktemp -d)"
95
+ c4builder --new --name smoke -y
96
+ cd smoke
97
+ c4builder
98
+ ls docs/index.html docs/context.svg
99
+ ```
100
+
101
+ `--new --name smoke -y` creates the project with default settings and no prompts; the
102
+ plain `c4builder` run is a one-off build. Both files listed → Node, CLI, Java/PlantUML and
103
+ the site generator work. `index.html` without `context.svg`, or a non-zero exit code →
104
+ rendering problem: read the error, return to step 4 (Java) or step 3 (D2 hint). Remove the
105
+ temporary folder afterwards.
106
+
107
+ With Docker, run the same two commands through the image: `c4builder --new --name smoke -y`
108
+ in the temporary folder, then the plain build with `smoke` mounted as `/pwd`.
109
+
110
+ ## 6. Skills in the working project
111
+
112
+ In the root of the user's project (not the temporary one):
113
+
114
+ ```bash
115
+ c4builder skills
116
+ ```
117
+
118
+ It installs the skills of the installed CLI version into `.agents/skills/` (and `.claude/skills/`
119
+ under Claude Code or when `.claude/` exists), replacing only the c4builder skills there; each
120
+ installed `SKILL.md` carries `metadata.generatedBy: <version>`. These are files in the user's
121
+ repository — run it when the user asked for the setup of this project, otherwise ask first. A
122
+ stderr line `~/.claude/skills/c4builder (…) overrides project skills` means a stale personal copy
123
+ (for example from `npx skills add -g`) shadows them: tell the user, remove it only with their
124
+ consent. A project created with `c4builder --new` already has the skills.
125
+
126
+ ## Report
127
+
128
+ One short summary: Node version / c4builder version and channel / Java (system or managed
129
+ JRE) / smoke build / skills in the project — each OK or fixed. For working on the diagrams
130
+ themselves, use the `c4builder` skill.
@@ -34,6 +34,9 @@ updates it.
34
34
  pinned by `uiLanguage`); batches are always in English.
35
35
  4. A stderr line `c4builder <new> is available (current <current>). Run: c4builder update`
36
36
  means a newer c4builder is out: tell the user, run `c4builder update` only if they ask.
37
+ 5. A stderr line ending with `Ask the user, then run: c4builder skills` means the c4builder skills
38
+ here are missing, outdated or shadowed by a personal copy: tell the user, run `c4builder skills`
39
+ (or remove the personal copy) only if they agree.
37
40
 
38
41
  ## Layout
39
42
 
@@ -60,8 +63,16 @@ updates it.
60
63
 
61
64
  ## Agent skills
62
65
 
63
- Detailed guidance (project layout, config keys, plugins, installation) as skills for
64
- Claude Code, Codex, Cursor and other agents:
66
+ Detailed guidance (project layout, config keys, plugins, page review, installation) as skills for
67
+ Claude Code, Codex, Cursor and other agents. A project created with `c4builder --new` already has
68
+ them in `.agents/skills/` (and `.claude/skills/` under Claude Code). Install or update them to the
69
+ installed CLI version:
70
+
71
+ ```bash
72
+ c4builder skills
73
+ ```
74
+
75
+ Alternative, also for a personal install (`-g`) and other agents' folders:
65
76
 
66
77
  ```bash
67
78
  npx skills add AlfaCapital-Tech/C4-Builder/skills