@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 +6 -2
- package/dist/cli/commands/new.js +3 -0
- package/dist/cli/commands/skills.js +80 -0
- package/dist/cli/dispatch.js +9 -1
- package/dist/cli/update.js +1 -1
- package/package.json +2 -1
- package/skills/c4builder/SKILL.md +199 -0
- package/skills/c4builder/references/bpmn.md +138 -0
- package/skills/c4builder/references/config.md +111 -0
- package/skills/c4builder/references/diagrams.md +77 -0
- package/skills/c4builder/references/mermaid.md +78 -0
- package/skills/c4builder/references/plugins.md +68 -0
- package/skills/c4builder-review/SKILL.md +97 -0
- package/skills/c4builder-setup/SKILL.md +130 -0
- package/template/AGENTS.md +13 -2
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: `
|
|
61
|
-
`"generateLLMS": true` adds `llms.txt` /
|
|
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
|
|
package/dist/cli/commands/new.js
CHANGED
|
@@ -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
|
+
};
|
package/dist/cli/dispatch.js
CHANGED
|
@@ -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
|
// Опции сборки после визарда: строгий разбор итогового конфига. Штатно валиден
|
package/dist/cli/update.js
CHANGED
|
@@ -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.
|
|
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
|
+
`` — 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 ``. 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; `` /
|
|
66
|
+
`` / `` / `` 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
|
+
``. `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.
|
package/template/AGENTS.md
CHANGED
|
@@ -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
|