@itsthecsguy/linework 0.1.0 → 0.1.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
@@ -11,28 +11,69 @@ Your agent writes a short YAML spec. Linework lays it out, styles it and writes
11
11
 
12
12
  ## Quick start
13
13
 
14
- You need Node 20+ and Chrome, Edge or another Chromium browser. Then give your agent the skill:
14
+ ### 1. Check what you need
15
+
16
+ - **Node 22.20 or newer** for the skills installer in step 2. Linework itself runs on Node 20+. Check with `node -v`.
17
+ - **Chrome, Edge or another Chromium browser.** Linework uses it in the background to measure text and draw. If you have neither, run `npx -y @itsthecsguy/linework install-browser`.
18
+ - **Using Codex?** Its sandbox stops Chrome from starting. Run `npx -y @itsthecsguy/linework install-browser` once, outside Codex. Linework's own headless Chromium does start inside the sandbox.
19
+
20
+ ### 2. Give your agent the skill
15
21
 
16
22
  ```bash
17
23
  npx skills add itsthecsguy/linework
18
24
  ```
19
25
 
20
- That's it. The [skills](https://github.com/vercel-labs/skills) installer finds the agents on your machine and puts the skill where each one looks: Claude Code, Codex, Cursor, Antigravity, Gemini CLI, GitHub Copilot, Grok Build, OpenCode, Windsurf and about 70 more. Add `-g` to install it for every project instead of this one.
26
+ The [skills](https://github.com/vercel-labs/skills) installer finds the agents on your machine, asks which ones to set up, and puts the skill where each one looks. It covers Claude Code, Codex, Cursor, Antigravity, Gemini CLI, GitHub Copilot, Grok Build, OpenCode, Windsurf and about 70 more.
27
+
28
+ It installs for the current project by default. Add `-g` to install it for every project. To skip the prompts, name the agents:
29
+
30
+ ```bash
31
+ npx skills add itsthecsguy/linework -g -a claude-code -a codex -y
32
+ ```
33
+
34
+ ### 3. Check that it works
35
+
36
+ This builds a two-box diagram without an agent:
37
+
38
+ ```bash
39
+ printf 'type: flow\nnodes: { a: Hello, b: World }\nedges:\n - a -> b\n' | npx -y @itsthecsguy/linework build - -o hello.drawio.svg --png hello.png
40
+ ```
41
+
42
+ It should print `check: 0 errors, 0 warnings` and write `hello.drawio.svg` and `hello.png`. The first run takes a few seconds longer while `npx` downloads the package. If it says no browser was found, run `npx -y @itsthecsguy/linework install-browser` and try again.
43
+
44
+ ### 4. Ask for a diagram
21
45
 
22
- Now ask for a diagram:
46
+ Start a new agent session so it loads the skill, then ask:
23
47
 
24
48
  > Add an architecture diagram of the checkout flow to docs/design.md.
25
49
 
26
- The agent reads the skill, writes the spec, runs `npx -y @itsthecsguy/linework build`, looks at the PNG preview, fixes what's off and embeds the `.drawio.svg`. There's no separate install step. The first run downloads the package through `npx`.
50
+ The agent writes the spec, runs Linework, looks at the PNG preview, fixes what's off and embeds the `.drawio.svg` in the doc. You don't install anything else. The skill runs Linework through `npx`.
27
51
 
28
- **Agent can't run shell commands?** Use the MCP server instead. See [Connect over MCP](#connect-over-mcp).
52
+ ### Optional: install the command
29
53
 
30
- **No skill support at all?** Add this line to your `AGENTS.md`, `CLAUDE.md` or `GEMINI.md`:
54
+ The skill works without this, but a global install skips the `npx` download check on every run and puts `linework` on your PATH:
31
55
 
32
- ```markdown
33
- For diagrams, use Linework: run `npx -y @itsthecsguy/linework skill` to get the guide's path, and read SKILL.md there before your first diagram.
56
+ ```bash
57
+ npm install -g @itsthecsguy/linework
34
58
  ```
35
59
 
60
+ ### Updating
61
+
62
+ ```bash
63
+ npx skills update linework
64
+ ```
65
+
66
+ If you installed the command globally, update it with `npm install -g @itsthecsguy/linework@latest`.
67
+
68
+ ### Other setups
69
+
70
+ - **Agent can't run shell commands?** Use the MCP server. See [Connect over MCP](#connect-over-mcp).
71
+ - **Agent doesn't load skills?** Add this line to your `AGENTS.md`, `CLAUDE.md` or `GEMINI.md`:
72
+
73
+ ```markdown
74
+ For diagrams, use Linework: run `npx -y @itsthecsguy/linework skill` to get the guide's path, and read SKILL.md there before your first diagram.
75
+ ```
76
+
36
77
  ## How it works
37
78
 
38
79
  A spec is a few lines of YAML:
@@ -73,7 +114,7 @@ Color is for meaning. Nodes stay neutral by default, and errors and successes ar
73
114
 
74
115
  Linework sizes every box from the real width of its text in the font it renders with, wrapping long labels instead of widening boxes. Each SVG carries a subset of that font (about 10 to 15KB), so text fits the same way on GitHub, in a browser or in a doc. `check` flags labels that overflow, overlap a box, another label, another edge or a group border, and `build` moves edge labels until they're clear.
75
116
 
76
- Linework needs Node 20+ and a Chromium-based browser, which it uses headless to measure text and render. It tries Playwright's Chromium, then Chrome, then Edge. If none is found, run `npx playwright install chromium`, or set `LINEWORK_CHROME` to a browser binary.
117
+ Linework needs Node 20+ and a Chromium-based browser, which it uses headless to measure text and render. It tries Playwright's Chromium, then Chrome, then Edge. If none is found, run `linework install-browser`, or set `LINEWORK_CHROME` to a browser binary. If a browser is found but crashes on launch, an agent's sandbox is usually blocking it. Linework then retries Playwright's Chromium in single-process mode, which starts inside Codex's sandbox.
77
118
 
78
119
  ## Connect over MCP
79
120
 
@@ -148,6 +189,7 @@ Docs can't hold an SVG, so the diagram lives in Google Drive and draw.io's Googl
148
189
  | `linework mcp [--root dir]` | MCP server over stdio |
149
190
  | `linework kinds [type]` | node kinds per diagram type |
150
191
  | `linework schema` | JSON Schema of the spec |
192
+ | `linework install-browser` | download the headless Chromium build this version uses |
151
193
 
152
194
  ## Status
153
195
 
package/dist/api.js CHANGED
@@ -3,7 +3,7 @@ import fs from 'node:fs';
3
3
  import path from 'node:path';
4
4
  import { parseSpecText } from './spec/parse.js';
5
5
  import { layout } from './layout/layout.js';
6
- import { patchEdges, serialize, stampEdgeRoutes, toMxfile } from './drawio/write.js';
6
+ import { edgeCellId, patchEdges, serialize, stampEdgeRoutes, toMxfile } from './drawio/write.js';
7
7
  import { absBox, fingerprint, readDrawio, specBase } from './drawio/read.js';
8
8
  import { manualEdits, toDiagram, toYaml } from './drawio/show.js';
9
9
  import { merge } from './drawio/merge.js';
@@ -96,7 +96,7 @@ export async function build(specText, opts) {
96
96
  }
97
97
  }
98
98
  else
99
- xml = toMxfile(diagram, l);
99
+ xml = await straightenDetours(b, toMxfile(diagram, l), detourEdges(diagram, l));
100
100
  xml = (await fixLabels(b, xml)).xml;
101
101
  xml = stampEdgeRoutes(xml);
102
102
  return finish(b, xml, { mode, warnings, direction: mode === 'merge' ? (old.meta.aiviz_direction ?? l.direction) : l.direction, edits, old, stats });
@@ -117,6 +117,43 @@ export async function build(specText, opts) {
117
117
  };
118
118
  }
119
119
  }
120
+ /**
121
+ * Edges whose route is far longer than the gap between their ends. Layered layout
122
+ * draws one edge of every cycle backwards, so the reply in a call-and-callback pair
123
+ * (api -> stripe, stripe -> api) can loop around a whole group.
124
+ */
125
+ export function detourEdges(d, l) {
126
+ const out = [];
127
+ for (const e of d.edges) {
128
+ const r = l.edges.get(e.id), a = l.nodes.get(e.from), z = l.nodes.get(e.to);
129
+ if (!r || !a || !z || r.points.length < 2)
130
+ continue;
131
+ let len = 0;
132
+ for (let i = 0; i < r.points.length - 1; i++)
133
+ len += Math.abs(r.points[i + 1].x - r.points[i].x) + Math.abs(r.points[i + 1].y - r.points[i].y);
134
+ const gap = Math.max(0, Math.abs(a.x + a.w / 2 - (z.x + z.w / 2)) - (a.w + z.w) / 2) +
135
+ Math.max(0, Math.abs(a.y + a.h / 2 - (z.y + z.h / 2)) - (a.h + z.h) / 2);
136
+ if (len > 2 * gap + 240)
137
+ out.push(edgeCellId(e.id));
138
+ }
139
+ return out;
140
+ }
141
+ /**
142
+ * Reroute detours with libavoid. Keep the new routes when they're much shorter and
143
+ * cost at most a couple of crossings each: a short hop with a crossing reads better
144
+ * than a line wrapped around half the diagram.
145
+ */
146
+ async function straightenDetours(b, xml, ids) {
147
+ if (!ids.length)
148
+ return xml;
149
+ const candidate = await rerouteInto(b, xml, ids);
150
+ const [before, after] = [await b.inspect(xml), await b.inspect(candidate)];
151
+ const length = (cells) => cells.filter((c) => ids.includes(c.id)).reduce((sum, c) => sum + (c.points ?? []).reduce((s, p, i, a) => (i ? s + Math.abs(p.x - a[i - 1].x) + Math.abs(p.y - a[i - 1].y) : 0), 0), 0);
152
+ const [c0, c1] = [check(before), check(after)];
153
+ const errors = (c) => c.findings.filter((f) => f.level === 'error').length;
154
+ const keep = errors(c1) <= errors(c0) && c1.stats.crossings <= c0.stats.crossings + 2 * ids.length && length(after) < 0.6 * length(before);
155
+ return keep ? candidate : xml;
156
+ }
120
157
  async function rerouteInto(b, xml, edgeIds) {
121
158
  return patchEdges(xml, await b.reroute(xml, edgeIds), edgeIds);
122
159
  }
package/dist/cli.js CHANGED
@@ -48,6 +48,10 @@ Usage:
48
48
  List node kinds for each diagram type.
49
49
  linework schema
50
50
  Print the spec's JSON Schema.
51
+
52
+ linework install-browser
53
+ Download the headless Chromium build that matches this version. Needed only
54
+ when no Chrome or Edge is installed, or to run inside an agent's sandbox.
51
55
  `;
52
56
  async function main(argv) {
53
57
  const [cmd, ...rest] = argv;
@@ -238,6 +242,15 @@ async function main(argv) {
238
242
  case 'schema':
239
243
  console.log(JSON.stringify(jsonSchema(), null, 2));
240
244
  return;
245
+ case 'install-browser': {
246
+ const { browserInstallCommand } = await import('./render/browser.js');
247
+ const { spawnSync } = await import('node:child_process');
248
+ const [bin, ...args] = browserInstallCommand();
249
+ console.log('downloading headless Chromium for linework...');
250
+ const r = spawnSync(bin, args, { stdio: 'inherit' });
251
+ process.exitCode = r.status ?? 1;
252
+ return;
253
+ }
241
254
  default:
242
255
  fail(`unknown command "${cmd}"\n\n${USAGE}`);
243
256
  }
@@ -111,6 +111,10 @@ export function check(cells) {
111
111
  for (const n of nodes)
112
112
  if (inter(e.textBox, grow(n.box, 3)) > 4)
113
113
  findings.push({ level: 'warning', rule: 'label-on-node', message: `label "${e.label}" on edge ${edgeName(e, byId)} covers ${name(n)}`, labelEdges: [e.id] });
114
+ // Same for a group's title.
115
+ for (const g of containers)
116
+ if (!scaffold(g) && g.label && g.textBox && inter(e.textBox, grow(g.textBox, 2)) > 4)
117
+ findings.push({ level: 'warning', rule: 'label-on-node', message: `label "${e.label}" on edge ${edgeName(e, byId)} covers the title of ${name(g)}`, labelEdges: [e.id] });
114
118
  // A label sitting on another edge, or on a group's border, hides part of that line.
115
119
  const tb = grow(e.textBox, -2);
116
120
  const lines = [
@@ -4,6 +4,7 @@
4
4
  import fs from 'node:fs';
5
5
  import path from 'node:path';
6
6
  import { fileURLToPath } from 'node:url';
7
+ import { createRequire } from 'node:module';
7
8
  import { chromium } from 'playwright-core';
8
9
  import { FONT_STACK } from '../drawio/theme.js';
9
10
  import { FACES, embedFonts, fontFaceCss, fontsDir } from './fonts.js';
@@ -188,6 +189,14 @@ export class DrawioBrowser {
188
189
  return this.browser.close();
189
190
  }
190
191
  }
192
+ /** Playwright-core's own installer, so the Chromium build always matches the version we run. */
193
+ export function browserInstallCommand() {
194
+ const pkg = createRequire(import.meta.url).resolve('playwright-core/package.json');
195
+ return [process.execPath, path.join(path.dirname(pkg), 'cli.js'), 'install', 'chromium', '--only-shell'];
196
+ }
197
+ function installHint() {
198
+ return 'linework install-browser';
199
+ }
191
200
  async function launchChromium() {
192
201
  const errors = [];
193
202
  const attempts = [];
@@ -204,7 +213,24 @@ async function launchChromium() {
204
213
  errors.push(e.message.split('\n')[0]);
205
214
  }
206
215
  }
207
- throw new Error('linework needs a Chromium-based browser to lay out and render diagrams, and none was found.\n' +
208
- 'Fix one of these ways:\n npx playwright install chromium\n install Google Chrome\n set LINEWORK_CHROME=/path/to/chrome\n' +
209
- `(tried: ${errors.join(' | ')})`);
216
+ // A browser that exists but dies on launch is almost always a sandbox (Codex,
217
+ // seatbelt, containers without --no-sandbox) blocking it, not a missing install.
218
+ const crashed = errors.some((m) => !/doesn't exist|is not found|not installed|ENOENT/i.test(m));
219
+ if (crashed) {
220
+ // Playwright's headless shell still starts under macOS seatbelt (Codex's sandbox)
221
+ // when it runs as one process. Only as a fallback: single-process mode is less robust.
222
+ try {
223
+ return await chromium.launch({ args: ['--single-process', '--no-zygote'] });
224
+ }
225
+ catch (e) {
226
+ errors.push(e.message.split('\n')[0]);
227
+ }
228
+ }
229
+ throw new Error(crashed
230
+ ? 'linework found a Chromium-based browser but it could not start. If this runs inside a sandbox (an AI agent\'s sandbox, a container), the sandbox is probably blocking it.\n' +
231
+ `Fix: run this command outside the sandbox, or allow it to launch a browser. Linework can start inside some sandboxes (Codex's included) if Playwright's own Chromium is installed: run \`${installHint()}\` once, outside the sandbox.\n` +
232
+ `(tried: ${errors.join(' | ')})`
233
+ : 'linework needs a Chromium-based browser to lay out and render diagrams, and none was found.\n' +
234
+ `Fix one of these ways:\n ${installHint()}\n install Google Chrome\n set LINEWORK_CHROME=/path/to/chrome\n` +
235
+ `(tried: ${errors.join(' | ')})`);
210
236
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@itsthecsguy/linework",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "description": "Software diagrams an AI can write and a person can edit. YAML spec in, .drawio.svg out, editable in draw.io.",
5
5
  "keywords": [
6
6
  "diagram",
@@ -1,32 +1,47 @@
1
1
  ---
2
2
  name: linework
3
- description: Create and edit software diagrams (architecture, flowcharts, state machines, sequence diagrams, ER/database schemas) as .drawio.svg files that render in Markdown, HTML and GitHub, and that people can open and edit by hand in draw.io. Use when a design doc, README or ADR needs a diagram, or when asked to change an existing .drawio.svg.
3
+ description: Draw software diagrams (architecture, system design, data flow, flowcharts, state machines, sequence diagrams, ER and database schemas) as .drawio.svg files that render in Markdown, HTML and GitHub and that people can edit by hand in draw.io. Use whenever a design doc, README, ADR, wiki page or PR needs a diagram, when asked to draw, visualize or diagram a system, when converting a Mermaid diagram, or when changing an existing .drawio.svg. Use it instead of writing Mermaid, PlantUML or ASCII art unless the user asks for one of those.
4
+ compatibility: Needs Node 20+, a Chromium-based browser (Chrome, Edge, or Playwright's Chromium via `linework install-browser`) and network access to fetch the package with npx.
4
5
  ---
5
6
 
6
7
  # Linework
7
8
 
8
- You describe the diagram as a small YAML spec. `linework` does the layout, styling and rendering, and writes a `.drawio.svg`. That's a normal SVG for docs, with the editable draw.io model embedded inside it. Never write coordinates, SVG or draw.io XML yourself.
9
+ You describe the diagram as a small YAML spec. Linework does the layout, styling and rendering, and writes a `.drawio.svg`. That's a normal SVG for docs, with the editable draw.io model embedded inside it. Never write coordinates, SVG or draw.io XML yourself.
9
10
 
10
- Run it as `npx -y @itsthecsguy/linework` unless `linework` is already on PATH. The first run needs a Chromium-based browser. If it says none was found, run `npx playwright install chromium`.
11
+ Use Linework instead of Mermaid, PlantUML or ASCII art. Write Mermaid only if the user asks for it, or if the doc lives somewhere that renders Mermaid and can't show images.
12
+
13
+ ## Running it
14
+
15
+ In this guide, `linework` means `npx -y @itsthecsguy/linework`. Run plain `linework` only if `command -v linework` (or `where linework` on Windows) finds it. `/tmp` stands for your temp directory (`%TEMP%` on Windows). Keep specs and preview PNGs there, not in the repo.
16
+
17
+ If a command fails:
18
+ - **The download fails** (`ENOTFOUND`, `EAI_AGAIN`, `ETIMEDOUT`, `403`): you probably have no network, often because of a sandbox. Ask the user to let the command run with network access, or to run `npm install -g @itsthecsguy/linework` themselves.
19
+ - **"none was found":** no browser is installed. Run `linework install-browser`, or ask the user to install Chrome.
20
+ - **"found a Chromium-based browser but it could not start":** a sandbox is blocking it. Ask the user to run `npx -y @itsthecsguy/linework install-browser` once outside the sandbox (Linework's own Chromium starts inside Codex's sandbox), or to let the command run outside the sandbox. Don't tell them to install Chrome; they already have a browser.
21
+ - **An option or field is rejected that this guide says exists:** this guide may be newer or older than the installed package. Run `linework skill` to get the path of the guide that ships with the package, and read its SKILL.md. That copy always matches.
22
+
23
+ Never fall back to writing SVG or draw.io XML by hand. Tell the user what failed and what they can do about it.
11
24
 
12
25
  ## Workflow
13
26
 
14
- 1. **Decide what the diagram is for.** One diagram makes one point. Pick the type:
27
+ 1. **Look for existing diagrams first.** Search the repo for `*.drawio.svg`. If one already shows what you need, change it (see "Editing an existing diagram") instead of drawing a new one. Save new diagrams where the existing ones live. With none yet, use `docs/diagrams/`, or the folder of the doc you're editing if the repo has no `docs/`.
28
+ 2. **Decide what the diagram is for.** One diagram makes one point. Pick the type:
15
29
  - `architecture`: components and how they talk. Services, data stores, queues, external systems, trust boundaries.
16
30
  - `flow`: a process with steps and decisions.
17
31
  - `state`: the lifecycle of one thing, like an order, payment or job.
18
32
  - `sequence`: who calls whom, in what order, for one scenario.
19
33
  - `er`: database tables, their columns and how they relate.
20
34
 
21
- If the doc already has a Mermaid diagram, convert it instead of rewriting it: `npx -y @itsthecsguy/linework import doc.md --block 1 -o docs/diagrams/x.drawio.svg`.
22
- 2. **Write the spec** to a scratch file, or pipe it on stdin. The `.drawio.svg` is the source of truth, so you don't need to keep the YAML.
23
- 3. **Build with a preview:**
35
+ If the doc already has a Mermaid diagram, convert it instead of rewriting it: `linework import doc.md --block 1 -o docs/diagrams/x.drawio.svg`.
36
+ 3. **Write the spec** to `/tmp/spec.yaml`, or pipe it on stdin with `-` as the file. Start from the closest file in `examples/` next to this guide: `checkout.yaml` (architecture), `serverless-aws.yaml` (architecture with AWS icons), `refund-flow.yaml` (flow), `payment-state.yaml` (state), `pay-sequence.yaml` (sequence), `billing-er.yaml` (ER). The `.drawio.svg` is the source of truth, so you don't need to keep the YAML.
37
+ 4. **Build with a preview:**
24
38
  ```bash
25
- npx -y @itsthecsguy/linework build spec.yaml -o docs/diagrams/checkout.drawio.svg --png /tmp/checkout.png
39
+ linework build /tmp/spec.yaml -o docs/diagrams/checkout.drawio.svg --png /tmp/checkout.png
26
40
  ```
27
- 4. **Read the output.** `spec error` lines tell you exactly what to fix. `check:` lists layout problems. Fix every `error` and the warnings that matter, then rebuild.
28
- 5. **Look at the PNG** if you can view images. Check that the diagram tells the story you meant, flows in a sensible direction and doesn't sprawl. If `check` says `too-wide`, remove `direction` (or set `TB`) or split it.
29
- 6. **Embed the `.drawio.svg`**, never the PNG (see "Putting it in a doc").
41
+ 5. **Read the output.** `spec error` lines tell you exactly what to fix. `check:` lists layout problems. Fix every `error` and the warnings that matter, then rebuild.
42
+ 6. **Look at the PNG** if you can view images. Check that the diagram tells the story you meant, flows in a sensible direction and doesn't sprawl. If `check` says `too-wide`, remove `direction` (or set `TB`) or split it. If you can't view images, rely on `check` and keep the diagram small.
43
+ 7. **Embed the `.drawio.svg`**, never the PNG (see "Putting it in a doc").
44
+ 8. **Tell the user** where the file is, what it shows, and that they can edit it by hand in draw.io.
30
45
 
31
46
  ## Spec
32
47
 
@@ -58,7 +73,7 @@ edges: # "from ARROW to: label"
58
73
  - `tech` is the small, quieter second line. Use it for the technology, not a description.
59
74
  - Node order matters a little. Layout tries to keep the declaration order, so list nodes roughly in reading order.
60
75
  - Quote an edge if its label contains `: ` or `#`, for example `- "api -> db: SELECT: orders"`.
61
- - Architecture nodes can carry a cloud icon: `icon: aws.lambda`, `gcp.cloud_run`, `k8s.pod`, `azure.<name>`. Run `npx -y @itsthecsguy/linework icons aws lambda` to search names. Use icons when the doc is about a specific cloud; leave them off for logical diagrams.
76
+ - Architecture nodes can carry a cloud icon: `icon: aws.lambda`, `gcp.cloud_run`, `k8s.pod`, `azure.<name>`. Run `linework icons aws lambda` to search names. Use icons when the doc is about a specific cloud; leave them off for logical diagrams.
62
77
  - Styles (`theme:`): use `clean` unless asked. It's minimal: white boxes, hairline borders, groups as gray grounds, IBM Plex Sans, and color only where it means something.
63
78
  - `soft`: borderless pastel cards, tinted by kind. For slides and docs that want color coding.
64
79
  - `dark`: for dark-mode docs and slides.
@@ -156,16 +171,16 @@ edges:
156
171
 
157
172
  Field flags: `pk`, `fk`, `unique`, `null`. Cardinality ends: `||` one, `|o` zero or one, `}o` / `o{` many, `}|` / `|{` one or many. Use `--` for identifying relationships, `..` for the rest.
158
173
 
159
- More examples and rules are in `references/spec.md`. Read `references/style-guide.md` before drawing anything non-trivial.
174
+ Every option and more examples are in `references/spec.md`, and full specs for each type are in `examples/`. Read `references/style-guide.md` before drawing anything non-trivial.
160
175
 
161
176
  ## Editing an existing diagram
162
177
 
163
178
  Always start from the file, never from an old copy of the spec:
164
179
 
165
180
  ```bash
166
- npx -y @itsthecsguy/linework show docs/diagrams/checkout.drawio.svg > /tmp/spec.yaml # current spec, hand edits included
181
+ linework show docs/diagrams/checkout.drawio.svg > /tmp/spec.yaml # current spec, hand edits included
167
182
  # edit /tmp/spec.yaml; keep the "# linework-base:" line at the top
168
- npx -y @itsthecsguy/linework build /tmp/spec.yaml -o docs/diagrams/checkout.drawio.svg --png /tmp/checkout.png
183
+ linework build /tmp/spec.yaml -o docs/diagrams/checkout.drawio.svg --png /tmp/checkout.png
169
184
  ```
170
185
 
171
186
  If someone has arranged the diagram by hand in draw.io, `build` merges your changes into their layout instead of starting over. (For sequence diagrams, hand-placed lifeline columns stay; rows always follow message order.)
@@ -182,19 +197,21 @@ The `# linework-base:` line tells `build` your spec includes the latest hand edi
182
197
 
183
198
  `--relayout` throws the hand-made layout away and lays everything out from scratch. **Only use it if the user asks,** because it undoes their layout work.
184
199
 
185
- If someone moved shapes by hand and left edges crossing through boxes, `npx -y @itsthecsguy/linework tidy file.drawio.svg` reroutes just the broken edges and changes nothing else.
200
+ If someone moved shapes by hand and left edges crossing through boxes, `linework tidy file.drawio.svg` reroutes just the broken edges and changes nothing else.
186
201
 
187
202
  ## Putting it in a doc
188
203
 
189
- - Markdown (GitHub, GitLab, most renderers): `![Checkout architecture](diagrams/checkout.drawio.svg)`
190
- - HTML: `<img src="diagrams/checkout.drawio.svg" alt="Checkout architecture">`
204
+ - Markdown (GitHub, GitLab, most renderers): `![Checkout API calls Stripe to charge cards and writes orders to Postgres](diagrams/checkout.drawio.svg)`
205
+ - HTML: `<img src="diagrams/checkout.drawio.svg" alt="Checkout API calls Stripe to charge cards and writes orders to Postgres">`
206
+ - Write alt text that says what the diagram shows, in one sentence, not just its title. Someone using a screen reader should get the point from it.
207
+ - If you used `color:` for categories, add a sentence under the diagram saying what each color means.
191
208
  - Tell the user they can edit it by hand: open the file in VS Code with the "Draw.io Integration" extension, in draw.io desktop, or at app.diagrams.net. It saves back into the same file, and your later edits will keep their layout.
192
- - In a git repo, offer to run `npx -y @itsthecsguy/linework git-setup` once, so `git diff` on diagrams shows readable spec changes.
193
- - Google Docs can't hold SVG. `npx -y @itsthecsguy/linework publish file.drawio.svg` copies it into the user's Google Drive folder, and draw.io's Google Docs add-on inserts it from there and refreshes it after changes. Setup and the update steps are in `references/google-docs.md`; walk the user through them the first time.
209
+ - In a git repo, offer to run `linework git-setup` once, so `git diff` on diagrams shows readable spec changes.
210
+ - Google Docs can't hold SVG. `linework publish file.drawio.svg` copies it into the user's Google Drive folder, and draw.io's Google Docs add-on inserts it from there and refreshes it after changes. Setup and the update steps are in `references/google-docs.md`; walk the user through them the first time.
194
211
 
195
212
  ## Letting the user edit
196
213
 
197
- If the user wants to adjust a diagram by hand, `npx -y @itsthecsguy/linework edit file.drawio.svg` opens it in draw.io in their browser, served from their machine. Saving there writes the file. When they say they're done, run `show` and carry on from its output; their changes are in it.
214
+ If the user wants to adjust a diagram by hand, `linework edit file.drawio.svg` opens it in draw.io in their browser, served from their machine. Saving there writes the file. When they say they're done, run `show` and carry on from its output; their changes are in it.
198
215
 
199
216
  ## Commands
200
217
 
@@ -212,3 +229,5 @@ If the user wants to adjust a diagram by hand, `npx -y @itsthecsguy/linework edi
212
229
  | `check <file>` | lint only; exit 1 on errors |
213
230
  | `kinds [type]` | list node kinds |
214
231
  | `schema` | JSON Schema of the spec |
232
+ | `skill` | print the path of the guide that matches the installed version |
233
+ | `install-browser` | download the headless Chromium this version uses |
@@ -8,7 +8,7 @@ nodes:
8
8
  user: { label: Shopper, kind: person }
9
9
  web: { label: Web app, kind: client, tech: Next.js }
10
10
  gw: { label: API gateway, kind: service, tech: Envoy, in: vpc }
11
- api: { label: Checkout API, kind: service, tech: Go, in: vpc }
11
+ api: { label: Checkout API, kind: service, tech: Go, in: vpc, highlight: true }
12
12
  worker: { label: Fulfillment worker, kind: service, tech: Go, in: vpc }
13
13
  queue: { label: order-events, kind: queue, tech: Kafka, in: vpc }
14
14
  db: { label: Orders, kind: database, tech: Postgres, in: data }
@@ -17,11 +17,11 @@ nodes:
17
17
  email: { label: SendGrid, kind: external, tech: Email }
18
18
  edges:
19
19
  - user -> web: browses
20
- - web -> gw: HTTPS
21
- - gw -> api: gRPC
20
+ - web ==> gw: HTTPS
21
+ - gw ==> api: gRPC
22
22
  - api -> cache: read session
23
23
  - api -> db: SQL
24
- - api -> stripe: charge
24
+ - api ==> stripe: charge
25
25
  - api -.-> queue: OrderPlaced
26
26
  - queue -.-> worker: consume
27
27
  - worker -> db: update status
@@ -3,12 +3,12 @@ title: Card payment
3
3
  participants:
4
4
  user: { label: Shopper, kind: person }
5
5
  web: { label: Web app, kind: client }
6
- api: { label: Checkout API }
6
+ api: { label: Checkout API, highlight: true }
7
7
  stripe: { label: Stripe, kind: external }
8
8
  db: { label: Orders DB, kind: database }
9
9
  messages:
10
10
  - user -> web: Click "Pay"
11
- - web -> api: POST /checkout
11
+ - web ==> api: POST /checkout
12
12
  - api -> db: insert order (pending)
13
13
  - db --> api: order id
14
14
  - api -> stripe: create PaymentIntent
@@ -9,7 +9,7 @@ nodes:
9
9
  auto: { label: Auto-approve }
10
10
  review: { label: Queue for manual review }
11
11
  approved: { label: Approved?, kind: decision }
12
- refund: { label: Issue refund via Stripe }
12
+ refund: { label: Issue refund via Stripe, highlight: true }
13
13
  notify: { label: Email customer }
14
14
  deny: { label: Deny with reason, kind: error }
15
15
  done: { label: Done, kind: terminal }
@@ -14,7 +14,7 @@ The add-on renders diagrams through draw.io's export service at convert.diagrams
14
14
  ## Put a diagram in a doc
15
15
 
16
16
  ```bash
17
- npx -y @itsthecsguy/linework publish docs/diagrams/checkout.drawio.svg
17
+ linework publish docs/diagrams/checkout.drawio.svg
18
18
  ```
19
19
 
20
20
  This copies the file to `My Drive/linework/<project>/docs/diagrams/checkout.drawio.svg`. `<project>` is the git repository's folder name. With several Google accounts, or to use another synced folder, pass `--to <folder>`.
@@ -24,8 +24,8 @@ Then, in the doc: Extensions > draw.io > Insert diagrams, and pick the file. If
24
24
  ## After the diagram changes
25
25
 
26
26
  ```bash
27
- npx -y @itsthecsguy/linework build spec.yaml -o docs/diagrams/checkout.drawio.svg # or a hand edit in draw.io
28
- npx -y @itsthecsguy/linework publish docs/diagrams/checkout.drawio.svg
27
+ linework build spec.yaml -o docs/diagrams/checkout.drawio.svg # or a hand edit in draw.io
28
+ linework publish docs/diagrams/checkout.drawio.svg
29
29
  ```
30
30
 
31
31
  Give Drive a few seconds to sync. Then, in the doc: Extensions > draw.io > Update diagrams. Every image whose file changed refreshes in place.
@@ -35,7 +35,7 @@ Give Drive a few seconds to sync. Then, in the doc: Extensions > draw.io > Updat
35
35
  Select the diagram and choose Extensions > draw.io > Edit selected. draw.io opens the Drive file, and saving writes it back to Drive. The repo copy is now behind. Bring the edit back with:
36
36
 
37
37
  ```bash
38
- npx -y @itsthecsguy/linework publish --pull docs/diagrams/checkout.drawio.svg
38
+ linework publish --pull docs/diagrams/checkout.drawio.svg
39
39
  ```
40
40
 
41
41
  `publish` refuses to overwrite a Drive copy that someone edited after the last publish. It says so, and you choose `--pull` to take their version or `--force` to replace it.
@@ -43,4 +43,4 @@ npx -y @itsthecsguy/linework publish --pull docs/diagrams/checkout.drawio.svg
43
43
  ## Without Drive for desktop
44
44
 
45
45
  - Upload the `.drawio.svg` at drive.google.com and insert it with the add-on as above. To update it later, use the file's Manage versions > Upload new version in Drive. Uploading it again as a new file breaks the link to the doc.
46
- - Or skip the add-on: `npx -y @itsthecsguy/linework render docs/diagrams/checkout.drawio.svg -o checkout.png --scale 2`, insert the PNG, and put a link to the source file under it. You'll replace the image by hand when it changes.
46
+ - Or skip the add-on: `linework render docs/diagrams/checkout.drawio.svg -o checkout.png --scale 2`, insert the PNG, and put a link to the source file under it. You'll replace the image by hand when it changes.
@@ -1,6 +1,6 @@
1
1
  # Linework spec reference
2
2
 
3
- `npx -y @itsthecsguy/linework schema` prints the full JSON Schema.
3
+ `linework schema` prints the full JSON Schema.
4
4
 
5
5
  ## Top level
6
6