archik 0.2.1 → 0.4.0
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/.claude/skills/archik/SKILL.md +207 -27
- package/dist/cli/archik.mjs +246 -240
- package/dist/ui/assets/index-CLojQhdH.css +1 -0
- package/dist/ui/assets/index-DpA4Yg8x.js +216 -0
- package/dist/ui/index.html +2 -2
- package/package.json +1 -1
- package/dist/ui/assets/index-Cb0b0uen.js +0 -216
- package/dist/ui/assets/index-DCW1nqex.css +0 -1
|
@@ -20,16 +20,71 @@ can talk about the system without re-explaining it every time.
|
|
|
20
20
|
1. **Before** answering structural questions — *"what does X do?",
|
|
21
21
|
"what depends on Y?", "where does data flow when …?"* — read
|
|
22
22
|
`architecture.archik.yaml`. Don't guess from filenames or memory.
|
|
23
|
-
2. **When** work introduces, removes, or rewires components,
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
23
|
+
2. **When** work introduces, removes, or rewires components, write
|
|
24
|
+
the proposed end-state to `architecture.archik.suggested.yaml`
|
|
25
|
+
(same schema, plus a `metadata.suggestion` block — see "Suggesting
|
|
26
|
+
changes" below). Don't edit `architecture.archik.yaml` directly;
|
|
27
|
+
the user reviews and accepts in the canvas or via
|
|
28
|
+
`archik suggest accept`.
|
|
29
|
+
3. **After** every edit to a YAML, run `archik validate`. Fix any
|
|
27
30
|
reported errors before declaring the change done.
|
|
28
31
|
|
|
29
32
|
The sections below are the detailed reference behind these three
|
|
30
33
|
rules — *when* to consult, *when* to propose, schema, taxonomy,
|
|
31
34
|
relationship vocabulary, and CLI.
|
|
32
35
|
|
|
36
|
+
## Suggesting changes (the sidecar workflow)
|
|
37
|
+
|
|
38
|
+
The `archik.yaml` is the user's source of truth. You don't get to
|
|
39
|
+
mutate it directly. Instead, write your proposed end-state to a
|
|
40
|
+
sidecar file:
|
|
41
|
+
|
|
42
|
+
```
|
|
43
|
+
architecture.archik.yaml ← truth — user owns it
|
|
44
|
+
architecture.archik.suggested.yaml ← your draft proposal
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
The sidecar is a complete, valid Archik document — same schema as the
|
|
48
|
+
main file, plus a `metadata.suggestion` block that marks it as a
|
|
49
|
+
proposal:
|
|
50
|
+
|
|
51
|
+
```yaml
|
|
52
|
+
version: "1.0"
|
|
53
|
+
name: My Architecture
|
|
54
|
+
metadata:
|
|
55
|
+
suggestion:
|
|
56
|
+
from: architecture.archik.yaml
|
|
57
|
+
at: 2026-04-26T17:00:00Z
|
|
58
|
+
note: add Stripe payment flow # optional one-liner
|
|
59
|
+
nodes:
|
|
60
|
+
# ... entire proposed end-state, not just the delta
|
|
61
|
+
edges:
|
|
62
|
+
# ...
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
Once you've written the sidecar:
|
|
66
|
+
|
|
67
|
+
* The canvas shows a **📝 Suggestion pending** banner with `Review`,
|
|
68
|
+
`Accept`, `Reject` buttons. Review opens a colour-coded SVG diff in
|
|
69
|
+
a new tab; Accept renames the sidecar over the main file; Reject
|
|
70
|
+
deletes the sidecar.
|
|
71
|
+
* From the terminal: `archik suggest show | accept | reject`.
|
|
72
|
+
|
|
73
|
+
If the user has no canvas open and asks "apply it", run
|
|
74
|
+
`archik suggest accept` for them (only after they've explicitly
|
|
75
|
+
asked).
|
|
76
|
+
|
|
77
|
+
**Key rules:**
|
|
78
|
+
|
|
79
|
+
* Write the *full proposed document*, not a patch. The diff is
|
|
80
|
+
computed by archik between the main file and the sidecar.
|
|
81
|
+
* Run `archik validate architecture.archik.suggested.yaml` after
|
|
82
|
+
writing. The schema enforces cross-references (no dangling edges,
|
|
83
|
+
no parent cycles, no duplicate ids); silent failures are not OK.
|
|
84
|
+
* If a suggestion sidecar already exists, treat it as your previous
|
|
85
|
+
proposal — extend or replace it. Don't write a new sidecar with a
|
|
86
|
+
different name.
|
|
87
|
+
|
|
33
88
|
## When to consult the YAML
|
|
34
89
|
|
|
35
90
|
Read it **before answering** any of these:
|
|
@@ -69,17 +124,30 @@ The YAML tracks **shape**, not implementation detail.
|
|
|
69
124
|
|
|
70
125
|
## Hard rules for editing
|
|
71
126
|
|
|
127
|
+
The schema enforces these — `archik validate` will reject the file
|
|
128
|
+
if you break any of them, so don't bother trying.
|
|
129
|
+
|
|
72
130
|
- **Never put coordinates** (`x`, `y`, `width`, `height`, `viewport`) in
|
|
73
131
|
the YAML. Layout is computed by ELK on every render. The schema
|
|
74
132
|
rejects unknown keys at root, node, edge, and metadata levels.
|
|
75
133
|
- **Every id matches** `^[a-z][a-z0-9-]*$` — lowercase, starts with a
|
|
76
134
|
letter, hyphens allowed.
|
|
77
|
-
- **
|
|
78
|
-
|
|
79
|
-
-
|
|
80
|
-
|
|
135
|
+
- **Node ids and edge ids are unique** within their respective lists.
|
|
136
|
+
Duplicates fail validation.
|
|
137
|
+
- **Edges reference existing nodes**. If `from` or `to` doesn't match
|
|
138
|
+
a node id, the document fails to load.
|
|
139
|
+
- **No self-loop edges** — `from === to` isn't meaningful for an
|
|
140
|
+
architecture diagram and the schema rejects it.
|
|
141
|
+
- **`parentId` references an existing node** (any kind — typically a
|
|
142
|
+
`module` or `custom` container, but any node-with-children renders
|
|
143
|
+
as a container).
|
|
144
|
+
- **No `parentId` cycles** — a → b → a, or a node with itself as parent.
|
|
145
|
+
- **Any node with children is rendered as a container** regardless of
|
|
146
|
+
kind. So you can have a `frontend` "Web App" containing `module`
|
|
147
|
+
sub-areas, or a `service` containing `adapter` children — the icon
|
|
148
|
+
and KIND tag in the header still reflect the node's own kind.
|
|
81
149
|
- **Don't rename a node id**. Remove the old node and re-add it with
|
|
82
|
-
the new id, then fix every edge that referenced it.
|
|
150
|
+
the new id, then fix every edge / parentId that referenced it.
|
|
83
151
|
- **Don't change `version`** — it's `"1.0"`.
|
|
84
152
|
|
|
85
153
|
## Schema (top-level)
|
|
@@ -163,8 +231,27 @@ Picking the right kind:
|
|
|
163
231
|
- A logical grouping container (component, module) → `module`
|
|
164
232
|
- Anything that doesn't fit and you want a custom shape → `custom`
|
|
165
233
|
|
|
166
|
-
|
|
167
|
-
|
|
234
|
+
**Distinct visual shapes** (not just an icon — the *outline* differs):
|
|
235
|
+
|
|
236
|
+
| Kind | Shape |
|
|
237
|
+
| ---- | ----- |
|
|
238
|
+
| `database` | classic UML cylinder |
|
|
239
|
+
| `cloud` | cumulus cloud silhouette |
|
|
240
|
+
| `queue` | rounded capsule (pill) |
|
|
241
|
+
| `external` | dashed-border card |
|
|
242
|
+
| `module` / `custom` (with children) | container panel with header + tinted body |
|
|
243
|
+
|
|
244
|
+
Every other kind renders as the standard rounded card — the kind icon
|
|
245
|
+
in the header and the KIND label do the visual lifting. Don't expect
|
|
246
|
+
each kind to have its own outline; the icon + KIND tag is the
|
|
247
|
+
identity.
|
|
248
|
+
|
|
249
|
+
**Containers**: any node with children (declared via other nodes'
|
|
250
|
+
`parentId`) renders as a container, regardless of kind. So
|
|
251
|
+
`frontend` "Web App" can contain `module` sub-areas, a `service`
|
|
252
|
+
can contain hexagonal `port`/`adapter` children, etc. The kind of
|
|
253
|
+
the container itself controls the icon + accent colour shown in the
|
|
254
|
+
header bar.
|
|
168
255
|
|
|
169
256
|
## Edge fields
|
|
170
257
|
|
|
@@ -179,29 +266,56 @@ Picking the right kind:
|
|
|
179
266
|
color: "#f97316" # optional, any CSS color (hex / named / var())
|
|
180
267
|
```
|
|
181
268
|
|
|
182
|
-
## Relationships (
|
|
183
|
-
|
|
184
|
-
| Category | Relationship | Visual |
|
|
185
|
-
| -------------- | ------------ |
|
|
186
|
-
| Sync
|
|
187
|
-
|
|
|
188
|
-
|
|
|
189
|
-
|
|
|
269
|
+
## Relationships (17 total)
|
|
270
|
+
|
|
271
|
+
| Category | Relationship | Visual signature |
|
|
272
|
+
| -------------- | ------------ | ---------------- |
|
|
273
|
+
| Sync wire | `http_call` | dotted, animated, filled-triangle arrow |
|
|
274
|
+
| | `grpc` | thicker dashed, animated, **double-tick chevron** arrow |
|
|
275
|
+
| | `invokes` | dotted, animated, filled-triangle arrow |
|
|
276
|
+
| | `routes_to` | solid, no animation |
|
|
277
|
+
| Bidirectional | `websocket` | dashed, **fast** animation, **arrows on both ends** |
|
|
278
|
+
| Async callback | `webhook` | long-dash dashed, animated, hollow-triangle arrow |
|
|
279
|
+
| Data access | `reads` | dotted, animated, hollow-triangle arrow |
|
|
280
|
+
| | `writes` | thicker dotted, animated, filled-triangle arrow |
|
|
281
|
+
| Messaging | `publishes` | dotted, animated, **circle** arrow head |
|
|
282
|
+
| | `subscribes` | dotted, animated, filled-triangle arrow |
|
|
283
|
+
| | `streams_to` | long-dash, **fast** animation, filled-triangle |
|
|
284
|
+
| UML structural | `implements` | dashed, **hollow-triangle** at the interface end (UML realisation) |
|
|
285
|
+
| | `extends` | solid, **hollow-triangle** at parent end (UML inheritance) |
|
|
286
|
+
| | `composes` | solid, **filled-diamond at the owner (source) end** (UML composition) |
|
|
287
|
+
| Loose deps | `depends_on` | dashed, hollow-triangle arrow |
|
|
288
|
+
| | `has_a` | solid, filled-triangle (informal composition) |
|
|
289
|
+
| | `uses` | short-dash, hollow-triangle (lightest dependency) |
|
|
190
290
|
|
|
191
291
|
Picking the right relationship:
|
|
192
292
|
|
|
193
|
-
-
|
|
194
|
-
-
|
|
195
|
-
-
|
|
293
|
+
**Wire-protocol calls** (something is going over the network *now*):
|
|
294
|
+
- Generic HTTP / REST call → `http_call`
|
|
295
|
+
- Typed RPC (protobuf, Connect, Twirp) → `grpc`
|
|
296
|
+
- Function / agent / lambda invocation → `invokes`
|
|
297
|
+
- Gateway / ingress routing → `routes_to`
|
|
298
|
+
- Long-lived bidirectional connection (chat, live trading, collab) → `websocket`
|
|
299
|
+
- Async callback the *other party* pushes to *us* (Stripe webhook, GitHub event) → `webhook`
|
|
300
|
+
|
|
301
|
+
**Data access**:
|
|
196
302
|
- DB read query → `reads`
|
|
197
303
|
- DB write / mutation → `writes`
|
|
304
|
+
|
|
305
|
+
**Messaging**:
|
|
198
306
|
- Emitting an event / message → `publishes`
|
|
199
307
|
- Consuming an event / message → `subscribes`
|
|
200
|
-
- Continuous stream of records → `streams_to`
|
|
201
|
-
|
|
202
|
-
-
|
|
203
|
-
-
|
|
204
|
-
-
|
|
308
|
+
- Continuous stream of records (Kafka, Kinesis, log shipping) → `streams_to`
|
|
309
|
+
|
|
310
|
+
**UML class-diagram structural** (drawn in the same style as a UML class diagram, so the visual matches what an engineer expects on a board):
|
|
311
|
+
- Adapter realises an abstract interface → `implements`
|
|
312
|
+
- Subclass / subtype inherits → `extends`
|
|
313
|
+
- Whole owns the part's lifecycle (component composition) → `composes`
|
|
314
|
+
|
|
315
|
+
**Looser architectural** (not UML-strict — for "X depends on Y" without claiming a specific relationship):
|
|
316
|
+
- Package / build-level dependency → `depends_on`
|
|
317
|
+
- Informal "has a" without lifecycle ownership → `has_a`
|
|
318
|
+
- Lightest weight: "X uses Y somewhere" → `uses`
|
|
205
319
|
|
|
206
320
|
## Common editing patterns
|
|
207
321
|
|
|
@@ -285,6 +399,67 @@ edges:
|
|
|
285
399
|
relationship: implements
|
|
286
400
|
```
|
|
287
401
|
|
|
402
|
+
**Modelling a real-time chat with WebSocket + a Stripe webhook**:
|
|
403
|
+
|
|
404
|
+
```yaml
|
|
405
|
+
nodes:
|
|
406
|
+
- id: web
|
|
407
|
+
kind: frontend
|
|
408
|
+
name: Web App
|
|
409
|
+
- id: api
|
|
410
|
+
kind: service
|
|
411
|
+
name: Chat API
|
|
412
|
+
- id: stripe
|
|
413
|
+
kind: external
|
|
414
|
+
name: Stripe
|
|
415
|
+
edges:
|
|
416
|
+
- id: web-api-ws
|
|
417
|
+
from: web
|
|
418
|
+
to: api
|
|
419
|
+
relationship: websocket # bidirectional, fast animation
|
|
420
|
+
label: messages
|
|
421
|
+
- id: stripe-api-webhook
|
|
422
|
+
from: stripe
|
|
423
|
+
to: api
|
|
424
|
+
relationship: webhook # async callback
|
|
425
|
+
label: payment.succeeded
|
|
426
|
+
```
|
|
427
|
+
|
|
428
|
+
**gRPC between two Go services + UML class hierarchy**:
|
|
429
|
+
|
|
430
|
+
```yaml
|
|
431
|
+
nodes:
|
|
432
|
+
- id: orders
|
|
433
|
+
kind: service
|
|
434
|
+
name: Orders
|
|
435
|
+
- id: payments
|
|
436
|
+
kind: service
|
|
437
|
+
name: Payments
|
|
438
|
+
- id: order
|
|
439
|
+
kind: interface
|
|
440
|
+
name: Order
|
|
441
|
+
- id: subscription-order
|
|
442
|
+
kind: interface
|
|
443
|
+
name: SubscriptionOrder
|
|
444
|
+
- id: cart
|
|
445
|
+
kind: custom
|
|
446
|
+
name: Cart
|
|
447
|
+
edges:
|
|
448
|
+
- id: orders-payments-grpc
|
|
449
|
+
from: orders
|
|
450
|
+
to: payments
|
|
451
|
+
relationship: grpc # double-tick chevron
|
|
452
|
+
label: ChargeRequest
|
|
453
|
+
- id: subscription-extends-order
|
|
454
|
+
from: subscription-order
|
|
455
|
+
to: order
|
|
456
|
+
relationship: extends # UML hollow triangle
|
|
457
|
+
- id: cart-composes-order
|
|
458
|
+
from: cart
|
|
459
|
+
to: order
|
|
460
|
+
relationship: composes # UML filled diamond at Cart
|
|
461
|
+
```
|
|
462
|
+
|
|
288
463
|
## CLI
|
|
289
464
|
|
|
290
465
|
These commands are available globally if archik was installed via
|
|
@@ -296,6 +471,11 @@ archik validate # schema check (run after every edit)
|
|
|
296
471
|
archik validate path/to/file.yaml
|
|
297
472
|
archik render --out diagram.svg # headless layout → SVG
|
|
298
473
|
archik render --theme light --out diagram-light.svg
|
|
474
|
+
archik diff a.yaml b.yaml # text + colour-coded SVG diff
|
|
475
|
+
archik diff a.yaml b.yaml --out diff.svg
|
|
476
|
+
archik suggest show # summary of pending sidecar (default)
|
|
477
|
+
archik suggest accept # apply the sidecar over the main file
|
|
478
|
+
archik suggest reject # discard the sidecar
|
|
299
479
|
archik watch # re-render SVG on save
|
|
300
480
|
archik check # drift: nodes vs source dirs
|
|
301
481
|
archik dev # open the live editor in the browser (foreground)
|