archik 0.12.37 → 0.12.39

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.
@@ -0,0 +1,17 @@
1
+ {
2
+ "name": "archik",
3
+ "owner": {
4
+ "name": "Bashar",
5
+ "email": "welcomebachar@gmail.com"
6
+ },
7
+ "plugins": [
8
+ {
9
+ "name": "archik",
10
+ "source": ".",
11
+ "description": "Plain-YAML architecture diagrams + Jacobson use cases / actors / sequence diagrams / alphas, all CLI-mediated and validated. The skill enforces CLI-only access; the slash commands wrap the loop.",
12
+ "homepage": "https://github.com/bacharSalleh/archik#readme",
13
+ "license": "MIT",
14
+ "keywords": ["architecture", "diagram", "yaml", "jacobson", "ecb"]
15
+ }
16
+ ]
17
+ }
@@ -0,0 +1,21 @@
1
+ {
2
+ "name": "archik",
3
+ "description": "The shared vocabulary between you and Claude Code, at the engineering level. Plain-YAML architecture diagrams + Jacobson use cases / actors / sequence diagrams / alphas, all CLI-mediated and validated.",
4
+ "author": {
5
+ "name": "Bashar",
6
+ "email": "welcomebachar@gmail.com"
7
+ },
8
+ "homepage": "https://github.com/bacharSalleh/archik#readme",
9
+ "repository": "https://github.com/bacharSalleh/archik",
10
+ "license": "MIT",
11
+ "keywords": [
12
+ "architecture",
13
+ "diagram",
14
+ "yaml",
15
+ "jacobson",
16
+ "use-case",
17
+ "ecb",
18
+ "essence",
19
+ "documentation"
20
+ ]
21
+ }
package/README.md CHANGED
@@ -5,7 +5,8 @@
5
5
  <h1 align="center">archik</h1>
6
6
 
7
7
  <p align="center">
8
- <em>The shared vocabulary between you and Claude Code, at the engineering level.</em>
8
+ <em>Architecture-as-code your AI editor actually reads —<br/>
9
+ with use cases, sequence diagrams, and tests wired end-to-end.</em>
9
10
  </p>
10
11
 
11
12
  [![npm version](https://badge.fury.io/js/archik.svg)](https://www.npmjs.com/package/archik)
@@ -20,26 +21,30 @@
20
21
  <img src="https://cdn.jsdelivr.net/npm/archik/docs/hero.svg?v=2" alt="Sample Archik diagram of an LLM-assisted support system" width="780">
21
22
  </p>
22
23
 
23
- archik gives your project — and the AI editing it — *one file* that
24
- describes what the system actually looks like. Services, databases,
25
- queues, agents, LLMs, the edges between them. Plain YAML, schema-
26
- validated, no coordinates, no proprietary format.
24
+ ## The problems this fixes
27
25
 
28
- Open it in your browser for a live canvas. Render it in CI for a
29
- self-contained SVG. The [Claude Code skill and `/archik:*` slash
30
- commands](#for-claude-code--other-llms) install automatically with
31
- `archik init`, so the model edits the same file you do — *the
32
- diagram and the codebase stop drifting because Claude treats the
33
- diagram as the spec*.
26
+ If you've ever:
34
27
 
35
- If you've ever asked an AI agent "where would I add X?" and watched
36
- it guess from filenames, archik is the fix: the YAML answers the
37
- question, and Claude is required to read it before doing structural
38
- work.
28
+ - Asked an AI agent **"where would I add X?"** and watched it guess from filenames
29
+ - Shipped a feature and realised **the architecture doc hasn't been right since 2023**
30
+ - Tried to answer **"are we done?"** and gotten back vibes instead of evidence
31
+ - Watched a diagram drift from the code because **someone dragged a box and forgot to write it down**
39
32
 
40
- ## Quickstart
33
+ …then you know the gap. archik closes it with one YAML file as the spec, a CLI that's the only way to edit it, and a validator that catches every drift before merge.
34
+
35
+ ## What you get
36
+
37
+ | Layer | File | What it captures |
38
+ | -------------------- | ----------------------------------- | ------------------------------------------------------------------------- |
39
+ | **Structure** | `.archik/main.archik.yaml` | Services, databases, queues, agents, LLMs, the edges between them |
40
+ | **Actors** | `*.archik.actors.yaml` | Who initiates use cases (humans, external systems, schedulers) |
41
+ | **Requirements** | `.archik/usecases/*.archik.uc.yaml` | What each actor wants — flows + slices that name **test paths** |
42
+ | **Behaviour** | `*.archik.seq.yaml` | UML-subset sequence diagrams, ECB-checked when bound to a slice |
43
+ | **Progress** | `*.archik.alphas.yaml` | Essence/SEMAT alphas with **mechanically-verified** state transitions |
44
+
45
+ Every link between layers is a YAML cross-reference. The validator rejects breaks at every step — slice with missing test files, seq diagram without a `realizes` block, node whose `sourcePath` no longer resolves on disk, participant node missing a `seqFiles` backref. Orphans are caught at lint time, not in code review.
41
46
 
42
- Two terminal commands, then talk to Claude:
47
+ ## Quickstart
43
48
 
44
49
  ```bash
45
50
  npx archik@latest init # scaffolds .archik/main.archik.yaml +
@@ -47,17 +52,16 @@ npx archik@latest init # scaffolds .archik/main.archik.yaml +
47
52
  npx archik@latest start # opens the live canvas at http://localhost:5173
48
53
  ```
49
54
 
50
- Then in Claude Code, type:
55
+ Then in Claude Code:
51
56
 
52
57
  ```
53
- /archik:spawn # mirror your real source tree as the first diagram
54
- /archik:evolve # propose a cleaner bounded-context refactor
55
- /archik:suggest <feature> # propose changes for a specific feature
58
+ /archik:spawn # mirror your real source tree as the first diagram
59
+ /archik:suggest <feature> # propose changes for a specific feature
60
+ /archik:usecase <name> # author a use case with slices + tests
61
+ /archik:trace # "am I done?" — the coverage matrix
56
62
  ```
57
63
 
58
- Each `/archik:*` command stages a suggestion sidecar — **Review** in the canvas, then **Accept** or **Reject**. No manual YAML editing on either side: you click in the browser, Claude drives through the CLI.
59
-
60
- Done with the canvas? `npx archik stop`.
64
+ `/archik:suggest` and `/archik:usecase` stage reviewable artifacts — diff overlay on the canvas, accept or reject. **Claude never edits YAML by hand**; the skill enforces CLI-only access.
61
65
 
62
66
  <p align="center">
63
67
  <video src="https://github.com/bacharSalleh/archik/raw/main/docs/record.mp4" poster="https://cdn.jsdelivr.net/gh/bacharSalleh/archik@main/docs/archik.gif" width="780" controls muted autoplay loop playsinline>
@@ -65,6 +69,23 @@ Done with the canvas? `npx archik stop`.
65
69
  </video>
66
70
  </p>
67
71
 
72
+ ## Two install paths, same outcome
73
+
74
+ **npm** — the canonical install, includes the CLI and the canvas:
75
+
76
+ ```bash
77
+ npx archik@latest init
78
+ ```
79
+
80
+ **Claude Code plugin** — for the marketplace flow:
81
+
82
+ ```
83
+ /plugin marketplace add bacharSalleh/archik
84
+ /plugin install archik@archik
85
+ ```
86
+
87
+ Either path lands the same skill + the same 11 slash commands. The plugin still uses the `archik` npm binary for the actual work, so you need Node available either way. See [Manual install](#manual-install) for adding the integration to projects that don't use `archik init`.
88
+
68
89
  ## What you write
69
90
 
70
91
  ```yaml
@@ -74,14 +95,19 @@ nodes:
74
95
  - id: api
75
96
  kind: service
76
97
  name: Support API
77
- stack: Go + Postgres
98
+ sourcePath: src/api
99
+ description: REST API serving the customer support frontend.
100
+ stereotype: boundary
78
101
  - id: agent
79
102
  kind: agent
80
103
  name: Support Agent
81
- description: Drafts replies, escalates risky ones.
104
+ sourcePath: src/agent
105
+ description: Drafts replies, escalates risky ones to a human.
106
+ stereotype: control
82
107
  - id: claude
83
108
  kind: llm
84
109
  name: Claude
110
+ description: LLM backend for draft generation.
85
111
  edges:
86
112
  - id: api-agent
87
113
  from: api
@@ -94,99 +120,91 @@ edges:
94
120
  label: draft reply
95
121
  ```
96
122
 
97
- No `x` / `y` / `width` — layout is computed by [ELK](https://eclipse.dev/elk/) on every render. The schema rejects coordinates so diffs stay meaningful.
123
+ No `x`/`y`/`width` — layout is computed by [ELK](https://eclipse.dev/elk/) on every render. The schema rejects coordinates so diffs stay meaningful and diagrams stop drifting because someone moved a box.
98
124
 
99
- ## What it gives you
125
+ ## The killer feature: the Jacobson chain
100
126
 
101
- - **Live canvas** — `archik dev` (foreground) or `archik start` / `stop` (detached, multi-project).
102
- - **27 node kinds** across compute, data, messaging, networking, hexagonal, AI/ML, identity, observability, cloud, UI, and external.
103
- - **12 relationships** with distinct visual styling — `http_call`, `invokes`, `reads`, `writes`, `publishes`, `subscribes`, `streams_to`, `routes_to`, `implements`, `depends_on`, `has_a`, `uses`.
104
- - **Drag-to-connect, multi-select, undo/redo, compact view, themed (dark / light), notes per node, color overrides on edges.**
105
- - **CI-ready CLI** — `validate`, `render` (headless SVG), `watch`, `drift` (source-tree gaps), `trace` (coverage matrix with `--fail-on partial|none`).
106
- - **AI skill + slash commands** — `archik init` installs both automatically. Eleven `/archik:*` commands cover the structural surface (`spawn`, `evolve`, `suggest`, `describe`, `dev`, `accept`, `reject`) plus the requirements layer (`actor`, `usecase`, `trace`, `alpha`).
127
+ The diagram is the start. The thing that actually answers *"are we done?"* is the chain that runs from a stakeholder request all the way down to a passing test:
107
128
 
108
- ## Beyond the diagram — use cases, traceability, alphas
129
+ ```
130
+ Actor → Use case → Slice → Tests on disk → Seq diagram → Participant nodes → sourcePath on disk
131
+ ```
109
132
 
110
- The structural diagram is the start. Above it sits a thin requirements
111
- layer that closes the Jacobson chain — *who acts → what they want →
112
- how the system behaves at runtime → which structural nodes participate
113
- → which tests prove it*. Every link is a YAML cross-reference and the
114
- validator rejects breaks at every step.
133
+ Every arrow is a YAML cross-reference. `npx archik trace` walks the chain and prints a coverage matrix:
115
134
 
116
- | Artifact | File | What it captures |
117
- | ------------------------------ | ----------------------------------- | ------------------------------------------------------------- |
118
- | **Actors** | `*.archik.actors.yaml` | Who initiates use cases — humans, external systems, schedulers |
119
- | **Use cases + slices** | `.archik/usecases/*.archik.uc.yaml` | What each actor wants, with slim slices that name test paths |
120
- | **Sequence diagrams** | `*.archik.seq.yaml` | How a slice plays out at runtime (ECB-checked when bound to a slice via `realizes`) |
121
- | **Alphas (Essence / SEMAT)** | `*.archik.alphas.yaml` | Project-wide progress dials with mechanically-verified states |
135
+ ```
136
+ $ npx archik trace
122
137
 
123
- `npx archik trace` prints the coverage matrix (use case × slice × test
124
- × seq × ECB) so "are we done?" stops being an opinion. The dev canvas
125
- surfaces the same information visually: the **Use cases** toolbar
126
- button shows live trace status (`✓ all traced` / `◐ N to finish` /
127
- `○ N untraced`), and `/__archik/usecases` is a dedicated page with
128
- master/detail rail, slice cards with clickable test paths, and direct
129
- links to each realising sequence diagram.
138
+ USE CASE / SLICE TST RZ ECB FILE
139
+ ~ drift/clean 1t — — .archik/usecases/drift.archik.uc.yaml
140
+ ~ drift/missing-source 1t — — .archik/usecases/drift.archik.uc.yaml
141
+ ~ render/arch-svg 1t — — .archik/usecases/render.archik.uc.yaml
142
+ ~ suggest-accept/happy 1t ✓ 2/4 .archik/usecases/suggest-accept.archik.uc.yaml
143
+ ~ suggest-accept/rejected 1t — — .archik/usecases/suggest-accept.archik.uc.yaml
144
+ ~ validate/clean 1t — — .archik/usecases/validate.archik.uc.yaml
130
145
 
131
- The `validate` command enforces the integrity triangle: if a slice
132
- points at a seq file, the seq must point back; if a seq diagram
133
- realises a slice, every participant node must list that seq in its
134
- `seqFiles` array. Orphans get caught at lint time, not in code review.
146
+ totals: 9 slices across 4 use cases — 0 full, 9 partial, 0 untraced
147
+ ```
135
148
 
136
- ## For Claude Code & other LLMs
149
+ Same data lives on screen — the **Use cases** toolbar button shows live status (`✓ all traced` / `◐ N to finish` / `○ N untraced`), and `/__archik/usecases` is a dedicated page with master/detail rail, slice cards with test paths, and direct links to each realising sequence diagram.
137
150
 
138
- The whole reason archik uses YAML instead of a binary format: **the file is the shared map between you and the model**. `npx archik@latest init` drops both the Claude skill and the seven slash commands into your project — no separate setup.
151
+ In CI:
139
152
 
140
- The skill enforces a hard rule: **Claude talks to archik only through the `npx archik` CLI** — never `Read`, `Write`, or `Edit` on a YAML directly. Queries go through `npx archik q`, suggestions through `npx archik suggest set`, lifecycle through `npx archik suggest accept | reject`. You own the file; the CLI is the contract.
153
+ ```bash
154
+ npx archik trace --fail-on partial # exit 1 if anything's not fully traced
155
+ ```
141
156
 
142
- ### The slash commands
157
+ ## In your workflow
143
158
 
144
- **Structural diagram (the original surface):**
159
+ **Adding a feature.** Type `/archik:suggest add Stripe webhook handler`. Claude grounds in the current diagram, asks 1–3 clarifying questions, and stages a sidecar with the proposed shape. You review the green/red diff overlay on the canvas. Accept and the YAML is updated atomically; the next step is the build plan.
145
160
 
146
- | Command | What it does |
147
- | --------------------------- | ----------------------------------------------------------- |
148
- | `/archik:spawn` | Bootstrap a diagram by mirroring your real source tree |
149
- | `/archik:evolve` | Propose a cleaner bounded-context refactor |
150
- | `/archik:suggest <feature>` | Propose changes for a specific feature |
151
- | `/archik:describe <id>` | Explain a node and its connections |
152
- | `/archik:dev` | Open the live canvas |
153
- | `/archik:accept` | Apply the pending suggestion |
154
- | `/archik:reject` | Discard the pending suggestion |
161
+ **Tracking the work.** `/archik:usecase <name>` writes a `*.archik.uc.yaml` with flows, slices, and test paths. Each active slice's test files must exist on disk — the validator rejects empty promises. As code lands, slices flip from "tests-only" to "fully traced" once their realisation seq exists.
155
162
 
156
- **Requirements + traceability (the Jacobson layer — see below):**
163
+ **Closing the milestone.** `/archik:trace` surfaces what's left. `/archik:alpha promote requirements addressed` runs the criteria check before advancing — over-claiming is a hard error. `npx archik drift` catches sourcePath gaps from the source tree side.
157
164
 
158
- | Command | What it does |
159
- | ------------------------------------ | --------------------------------------------------------------------------- |
160
- | `/archik:actor <id>` | Add or update an actor in the actor index |
161
- | `/archik:usecase <name>` | Author a use case (actors + flows + slices + tests) |
162
- | `/archik:trace` | Show the use case × slice × test × seq × ECB coverage matrix |
163
- | `/archik:alpha [show \| promote …]` | Read the project's alpha state, or promote one with a criteria check |
165
+ ## How it differs
164
166
 
165
- A typical first-day flow:
167
+ | | archik | Mermaid / PlantUML | Structurizr | ADRs |
168
+ | --------------------- | --------------------- | ------------------ | ---------------- | ------------------ |
169
+ | Diagram source format | Plain YAML | Custom DSL | Structurizr DSL | Markdown prose |
170
+ | Layout | Auto (ELK), no coords | Auto | Auto | N/A |
171
+ | Live canvas | Yes (browser) | Some renderers | Yes | No |
172
+ | Headless render to CI | Yes (SVG) | Yes | Yes | No |
173
+ | AI-editor integration | **First-class** | None | None | None |
174
+ | Use cases / slices | **Yes** | No | No | Sometimes informal |
175
+ | Sequence diagrams | **Yes (UML subset)** | Yes | No | No |
176
+ | Test ↔ requirement traceability | **Mechanical** | No | No | No |
177
+ | Drift detection | **Yes (`drift`)** | No | No | No |
178
+ | Validator | **Schema + cross-file + ECB rules** | Syntax only | Syntax only | None |
166
179
 
167
- ```
168
- /archik:spawn # mirror what's there now
169
- # → review on the canvas, accept
170
- /archik:evolve # propose a cleaner shape
171
- # → discuss with Claude, accept (or iterate)
172
- /archik:suggest add Stripe webhook handler
173
- # → small, targeted change
174
- ```
180
+ If all you need is a one-off rendered diagram, Mermaid is faster. If you need the diagram to **stay accurate across an LLM-assisted refactor** and **prove the system does what the requirements say**, that's archik.
175
181
 
176
- Each command stages a sidecar via `npx archik suggest set`. The canvas shows a green/red/amber diff overlay; you click Accept or Reject — or `/archik:accept` / `/archik:reject` from the terminal. Same outcome either way.
182
+ ## All slash commands
177
183
 
178
- ### Manual install (existing projects without `archik init`)
184
+ **Structural diagram** (the original surface):
179
185
 
180
- If you already have an archik file and just want to add the Claude integration:
186
+ | Command | What it does |
187
+ | --------------------------- | ------------------------------------------------------ |
188
+ | `/archik:spawn` | Bootstrap a diagram by mirroring your real source tree |
189
+ | `/archik:evolve` | Propose a cleaner bounded-context refactor |
190
+ | `/archik:suggest <feature>` | Propose changes for a specific feature |
191
+ | `/archik:describe <id>` | Explain a node and its connections |
192
+ | `/archik:dev` | Open the live canvas |
193
+ | `/archik:accept` | Apply the pending suggestion |
194
+ | `/archik:reject` | Discard the pending suggestion |
181
195
 
182
- ```bash
183
- npx archik@latest skill --user # install skill into ~/.claude/skills (all projects)
184
- npx archik@latest commands --user # install /archik:* into ~/.claude/commands (all projects)
185
- ```
196
+ **Requirements + traceability** (the Jacobson layer):
186
197
 
187
- Drop the `--user` flag to scope to the current project only.
198
+ | Command | What it does |
199
+ | ------------------------------------ | ----------------------------------------------------------- |
200
+ | `/archik:actor <id>` | Add or update an actor in the actor index |
201
+ | `/archik:usecase <name>` | Author a use case (actors + flows + slices + tests) |
202
+ | `/archik:trace` | Show the coverage matrix + the next concrete action |
203
+ | `/archik:alpha [show \| promote …]` | Read or move project alphas with a machine-checked criteria |
188
204
 
189
- ## Commands
205
+ The skill enforces a hard rule: **Claude talks to archik only through `npx archik`** — never `Read`, `Write`, or `Edit` on a YAML file directly. Queries through `npx archik q`, suggestions through `npx archik suggest set`, lifecycle through `npx archik suggest accept | reject`. You own the file; the CLI is the contract.
206
+
207
+ ## CLI reference
190
208
 
191
209
  ```
192
210
  archik init [path] Scaffold a starter .archik/main.archik.yaml
@@ -207,12 +225,16 @@ archik validate [path] Validate against the schema (CI-friendly, exit code 1 o
207
225
  archik render [path] Render to a self-contained SVG file
208
226
  --out <file> output path (default: diagram.svg)
209
227
  --theme <name> "dark" (default) or "light"
228
+ --seq <path> render a sequence diagram instead of the structural one
210
229
  archik watch [path] Re-render to SVG on every file change (Ctrl+C to stop)
211
230
 
212
231
  archik trace [path] Use case × slice × test × seq × ECB coverage matrix
213
232
  --json structured rows + summary
214
233
  --fail-on <level> exit 1 on partial | none (CI gate)
215
234
  --use-case <id> filter to one use case
235
+ --actor <id> filter to use cases involving an actor
236
+ --status <s> filter slices by status (active|proposed|deprecated)
237
+ --coverage <l> filter rows by level (full|partial|none)
216
238
  archik drift [path] Surface gaps where a node's sourcePath or a slice's
217
239
  tests path no longer resolves on disk
218
240
 
@@ -222,12 +244,6 @@ archik alpha [sub] Project-wide alpha state (Essence / SEMAT)
222
244
  --note '<text>' captures the rationale
223
245
  demote <a> <s> walk back to an earlier state on the ladder
224
246
 
225
- archik upgrade Pull the latest archik via the project's package manager
226
- (auto-detects npm / pnpm / yarn / bun from the lockfile)
227
- then refreshes SKILL.md + slash commands from the new binary
228
- --skip-install just refresh artifacts; don't reinstall
229
- --user install to ~/.claude (global skill)
230
-
231
247
  archik suggest [sub] Manage Claude's pending architecture suggestion
232
248
  show summarise the pending sidecar (default; --json supported)
233
249
  set <draft> validate a draft YAML and stage it as the sidecar
@@ -238,49 +254,98 @@ archik suggest [sub] Manage Claude's pending architecture suggestion
238
254
  accept apply the sidecar over the main file
239
255
  reject discard the sidecar
240
256
 
257
+ archik q [sub] Query the diagram (--json supported on every subcommand)
258
+ describe <id> one node, full detail
259
+ deps <id> what does this node depend on?
260
+ dependents <id> what depends on this node?
261
+ impact <id> who breaks if this is removed?
262
+ list all nodes (with --kind / --parent / --status / --search filters)
263
+ edges all edges (with --from / --to / --rel filters)
264
+ stats node + edge counts by kind/relationship
265
+ usecases use case index (--actor filters)
266
+ describe-usecase <id> one use case, full detail
267
+ actors actor index
268
+ sequences sequence diagram index (--node filters)
269
+
270
+ archik upgrade Pull the latest archik via the project's package manager
271
+ (auto-detects npm / pnpm / yarn / bun from the lockfile)
272
+ then refreshes SKILL.md + slash commands from the new binary
273
+ --skip-install just refresh artifacts; don't reinstall
274
+
241
275
  archik skill Install the Claude skill for AI editing
242
276
  --user install into ~/.claude/skills (all projects)
243
277
  --force overwrite an existing skill
244
278
  archik commands Install the /archik:* slash commands for Claude Code
245
279
  --user install into ~/.claude/commands (all projects)
246
280
  --force overwrite existing commands
281
+ archik schema [variant] Print the document schema as a reference (--json supported)
282
+ (no arg) architecture document
283
+ seq sequence diagram
284
+ uc use case
285
+ actors actors file
247
286
  ```
248
287
 
249
288
  Without a `[path]` argument, archik resolves the file in this order:
250
289
 
251
- 1. `.archik/main.archik.yaml` (preferred new convention — keeps the project root tidy)
290
+ 1. `.archik/main.archik.yaml` (preferred — keeps the project root tidy)
252
291
  2. `architecture.archik.yaml` (legacy root location — still fully supported)
253
292
 
254
- If both exist the command errors out and asks you to pick one. New projects get the `.archik/` layout from `archik init`; existing projects keep working without any migration.
293
+ If both exist the command errors out and asks you to pick one.
255
294
 
256
- Single instance per file is enforced via a lock file in `$TMPDIR/archik-cli/`, so parallel `dev` and `start` against the same YAML are rejected with a friendly error.
295
+ ## Manual install
257
296
 
258
- ## Use it in CI
297
+ If you already have an archik file and just want to add the Claude integration to it:
298
+
299
+ **Via the npm CLI:**
259
300
 
260
301
  ```bash
261
- # Fail the build on schema errors
262
- archik validate
302
+ npx archik@latest skill --user # install skill into ~/.claude/skills (all projects)
303
+ npx archik@latest commands --user # install /archik:* into ~/.claude/commands (all projects)
304
+ ```
305
+
306
+ Drop the `--user` flag to scope to the current project only.
263
307
 
264
- # Generate a committable SVG of your architecture for the docs site
265
- archik render --theme light --out docs/architecture.svg
308
+ **Via Claude Code's plugin marketplace:**
309
+
310
+ ```
311
+ /plugin marketplace add bacharSalleh/archik
312
+ /plugin install archik@archik
266
313
  ```
267
314
 
268
- ## Schema
315
+ Either path leaves the same skill + the same 11 slash commands in the same target directories.
316
+
317
+ ## When to use it (and when not to)
269
318
 
270
- The full schema reference (every node kind, every relationship, common patterns, hard rules) lives in the AI skill. After installing it locally:
319
+ **Use archik when**
320
+
321
+ - Your project has more than ~5 components and you want the diagram to stay accurate
322
+ - You're using Claude Code (or any AI agent) to author code, and you want the agent to reason about structure instead of guess from filenames
323
+ - You're shipping in milestones and want "are we done?" to be mechanically answerable
324
+ - You have CI and want a gate that fails on architectural drift
325
+
326
+ **Skip it when**
327
+
328
+ - It's a one-file script or a throwaway prototype
329
+ - The architecture diagram is for a slide deck (use Mermaid)
330
+ - You don't have a build step or CI
331
+
332
+ The full schema reference (every node kind, every relationship, common patterns, hard rules) lives in [`skills/archik/SKILL.md`](skills/archik/SKILL.md) — installed automatically by `archik init` so Claude reads it before doing structural work.
333
+
334
+ ## Use it in CI
271
335
 
272
336
  ```bash
273
- archik skill --user
274
- $EDITOR ~/.claude/skills/archik/SKILL.md
337
+ archik validate # schema + cross-file integrity
338
+ archik drift # source-tree gaps
339
+ archik trace --fail-on partial # block merge on incomplete traceability
340
+ archik render --theme light --out docs/architecture.svg # commit a static SVG
275
341
  ```
276
342
 
277
- Or read it directly in this repo: [`.claude/skills/archik/SKILL.md`](.claude/skills/archik/SKILL.md).
278
-
279
343
  ## Design notes
280
344
 
281
- - The YAML is the only persistent truth. The canvas is a stateless projection that reloads on every file change (live-reload via SSE).
282
- - Layout is non-negotiable: ELK lays out every render. Putting an `x` / `y` / `width` field at any level fails schema validation. No more "the diagram drifted because someone dragged a box."
283
- - The published npm package ships only the bundled binary — no source files, no build tooling. Zero runtime dependencies.
345
+ - **The YAML is the only persistent truth.** The canvas is a stateless projection that reloads on every file change (live-reload via SSE).
346
+ - **Layout is non-negotiable.** ELK lays out every render. Putting an `x`/`y`/`width` field at any level fails schema validation. No more "the diagram drifted because someone dragged a box."
347
+ - **Single instance per file** is enforced via a lock file in `$TMPDIR/archik-cli/`, so parallel `dev`/`start` against the same YAML are rejected with a friendly error.
348
+ - **The published npm package** ships only the bundled binary, the canvas assets, the skill, and the 11 slash commands. Zero runtime dependencies.
284
349
 
285
350
  ## License
286
351
 
@@ -371,7 +371,7 @@ Consider installing the package or pass your own 'workerFactory' to ELK's constr
371
371
  React keys must be passed directly to JSX without using spread:
372
372
  let props = %s;
373
373
  <%s key={someKey} {...props} />`,Yo,Wr,Oa,Wr),_a[Wr+Yo]=!0)}if(Wr=null,yi!==void 0&&(d(yi),Wr=""+yi),v(Zn)&&(d(Zn.key),Wr=""+Zn.key),"key"in Zn){yi={};for(var Wl in Zn)Wl!=="key"&&(yi[Wl]=Zn[Wl])}else yi=Zn;return Wr&&k(yi,typeof nn=="function"?nn.displayName||nn.name||"Unknown":nn),P(nn,Wr,yi,f(),Hs,Lo)}function B(nn){G(nn)?nn._store&&(nn._store.validated=1):typeof nn=="object"&&nn!==null&&nn.$$typeof===jn&&(nn._payload.status==="fulfilled"?G(nn._payload.value)&&nn._payload.value._store&&(nn._payload.value._store.validated=1):nn._store&&(nn._store.validated=1))}function G(nn){return typeof nn=="object"&&nn!==null&&nn.$$typeof===de}var K=y3(),de=Symbol.for("react.transitional.element"),ce=Symbol.for("react.portal"),we=Symbol.for("react.fragment"),De=Symbol.for("react.strict_mode"),at=Symbol.for("react.profiler"),kt=Symbol.for("react.consumer"),_e=Symbol.for("react.context"),ht=Symbol.for("react.forward_ref"),Te=Symbol.for("react.suspense"),Wt=Symbol.for("react.suspense_list"),tn=Symbol.for("react.memo"),jn=Symbol.for("react.lazy"),rr=Symbol.for("react.activity"),_r=Symbol.for("react.client.reference"),fn=K.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE,ii=Object.prototype.hasOwnProperty,Si=Array.isArray,No=console.createTask?console.createTask:function(){return null};K={react_stack_bottom_frame:function(nn){return nn()}};var bs,Ki={},se=K.react_stack_bottom_frame.bind(K,b)(),Bs=No(g(b)),_a={};DDe.Fragment=we,DDe.jsx=function(nn,Zn,yi){var Yo=1e4>fn.recentlyCreatedOwnerStacks++;return j(nn,Zn,yi,!1,Yo?Error("react-stack-top-frame"):se,Yo?No(g(nn)):Bs)},DDe.jsxs=function(nn,Zn,yi){var Yo=1e4>fn.recentlyCreatedOwnerStacks++;return j(nn,Zn,yi,!0,Yo?Error("react-stack-top-frame"):se,Yo?No(g(nn)):Bs)}})()});var sc=mr((uri,Dft)=>{"use strict";process.env.NODE_ENV==="production"?Dft.exports=tan():Dft.exports=nan()});import{readFileSync as s8r}from"node:fs";import u8r from"node:path";import{access as RRn,mkdir as DRn,readFile as ORn,writeFile as EKt}from"node:fs/promises";import pct from"node:path";var kRn=process.env.FORCE_COLOR==="0"?!1:process.env.FORCE_COLOR!==void 0?!0:process.env.NO_COLOR!==void 0?!1:!!process.stdout.isTTY,Hx=(o,c)=>d=>kRn?`\x1B[${o}m${d}\x1B[${c}m`:d,Mr=Hx("1","22"),tr=Hx("2","22"),MRn=Hx("31","39"),act=Hx("32","39"),Uf=Hx("33","39"),eKr=Hx("34","39"),mKt=Hx("35","39"),ys=Hx("36","39"),V1=Hx("90","39"),Hl=()=>Mr(act("\u2713")),Yr=()=>Mr(MRn("\u2717")),k9=()=>ys("\u25B8");function vKt(o){let c={_:[]};for(let d=0;d<o.length;d++){let g=o[d];if(g.startsWith("--")){let f=g.indexOf("=");if(f!==-1)c[g.slice(2,f)]=g.slice(f+1);else{let b=o[d+1];b===void 0||b.startsWith("--")?c[g.slice(2)]="true":(c[g.slice(2)]=b,d++)}}else c._.push(g)}return c}function Zr(o,c){let d=o[c];return Array.isArray(d)?d[0]:d}import{existsSync as SRn,mkdirSync as _Rn}from"node:fs";import{readFile as CRn,rename as IRn,unlink as LRn,writeFile as ERn}from"node:fs/promises";import MKt from"node:path";import{access as xRn}from"node:fs/promises";import $x from"node:path";var sct=".archik/main.archik.yaml",uct="architecture.archik.yaml";async function lct(o){try{return await xRn(o),!0}catch{return!1}}async function Lu(o,c=process.cwd()){if(o!==void 0&&o!=="")return $x.resolve(c,o);let d=$x.resolve(c,uct),g=$x.resolve(c,sct),[f,b]=await Promise.all([lct(d),lct(g)]);if(f&&b)throw new Error(`Found both ${uct} and ${sct}. Pick one \u2014 keep the file under .archik/ (preferred) and delete the root copy, or vice versa.`);return f?d:g}async function kKt(o,c=process.cwd()){if(o!==void 0&&o!=="")return $x.resolve(c,o);let d=$x.resolve(c,uct);return await lct(d)?d:$x.resolve(c,sct)}function W1(o){let c=$x.dirname(o);return $x.basename(c)===".archik"?$x.dirname(c):c}var hct="runtime.json";function zU(o){return MKt.join(W1(o),".archik",hct)}async function kfe(o,c){let d=zU(o),g=MKt.dirname(d);SRn(g)||_Rn(g,{recursive:!0});let f=`${d}.tmp`;await ERn(f,JSON.stringify(c,null,2)+`
374
- `,"utf-8"),await IRn(f,d)}async function xKt(o){let c=zU(o);try{let d=await CRn(c,"utf-8"),g=JSON.parse(d);return typeof g.pid!="number"||typeof g.port!="number"||typeof g.host!="string"||typeof g.url!="string"||typeof g.startedAt!="string"?null:g}catch{return null}}function SKt(o){let c=o.urls?.local?.[0];if(c===void 0)return null;let d;try{d=new URL(c)}catch{return null}if(d.port==="")return null;let g=Number.parseInt(d.port,10);return Number.isFinite(g)?{pid:o.pid,port:g,host:d.hostname,url:c,startedAt:o.startedAt}:null}async function GI(o){let c=zU(o);try{await LRn(c)}catch{}}import{copyFile as _Kt,mkdir as CKt,readdir as NRn,stat as dct}from"node:fs/promises";import h3 from"node:path";import IKt from"node:os";import{existsSync as TRn,realpathSync as ARn}from"node:fs";import Mfe from"node:path";import{fileURLToPath as PRn}from"node:url";function U5(){let o=process.env.ARCHIK_PKG_ROOT;if(o)return Mfe.resolve(o);let c=Mfe.dirname(ARn(PRn(import.meta.url))),d=c;for(let g=0;g<10;g++){if(TRn(Mfe.join(d,"package.json")))return d;let f=Mfe.dirname(d);if(f===d)break;d=f}throw new Error(`archik: could not locate package root (start: ${c})`)}async function fct(o){let c=h3.join(U5(),".claude","skills","archik","SKILL.md");try{await dct(c)}catch{return{ok:!1,reason:"missing-source",source:c}}let d=o.scope==="user"?h3.join(IKt.homedir(),".claude","skills"):h3.resolve(".claude","skills"),g=h3.join(d,"archik"),f=h3.join(g,"SKILL.md");if(!o.force)try{return await dct(f),{ok:!1,reason:"exists",target:f}}catch{}return await CKt(g,{recursive:!0}),await _Kt(c,f),{ok:!0,target:f,scope:o.scope}}async function xfe(o){let c=h3.join(U5(),".claude","commands","archik"),d;try{d=(await NRn(c)).filter(v=>v.endsWith(".md"))}catch{return{ok:!1,reason:"missing-source",source:c}}if(d.length===0)return{ok:!1,reason:"missing-source",source:c};let g=o.scope==="user"?h3.join(IKt.homedir(),".claude","commands"):h3.resolve(".claude","commands"),f=h3.join(g,"archik");if(!o.force){let v=[];for(let k of d)try{await dct(h3.join(f,k)),v.push(k)}catch{}if(v.length>0)return{ok:!1,reason:"exists",existing:v,targetDir:f}}await CKt(f,{recursive:!0});let b=[];for(let v of d)await _Kt(h3.join(c,v),h3.join(f,v)),b.push(v);return{ok:!0,targetDir:f,copied:b,scope:o.scope}}async function LKt(o){let c=Zr(o,"user")==="true"?"user":"project",d=Zr(o,"force")==="true",g=await fct({scope:c,force:d});if(!g.ok)return g.reason==="missing-source"?console.error(`\u2717 Source skill not found at ${g.source}`):console.error(`\u2717 ${g.target} already exists. Pass --force to overwrite.`),1;let f=g.scope==="user"?"user-wide":"this project";return console.log(`\u2713 Installed archik skill (${f}) \u2192 ${g.target}`),0}var FRn=`version: "1.0"
374
+ `,"utf-8"),await IRn(f,d)}async function xKt(o){let c=zU(o);try{let d=await CRn(c,"utf-8"),g=JSON.parse(d);return typeof g.pid!="number"||typeof g.port!="number"||typeof g.host!="string"||typeof g.url!="string"||typeof g.startedAt!="string"?null:g}catch{return null}}function SKt(o){let c=o.urls?.local?.[0];if(c===void 0)return null;let d;try{d=new URL(c)}catch{return null}if(d.port==="")return null;let g=Number.parseInt(d.port,10);return Number.isFinite(g)?{pid:o.pid,port:g,host:d.hostname,url:c,startedAt:o.startedAt}:null}async function GI(o){let c=zU(o);try{await LRn(c)}catch{}}import{copyFile as _Kt,mkdir as CKt,readdir as NRn,stat as dct}from"node:fs/promises";import h3 from"node:path";import IKt from"node:os";import{existsSync as TRn,realpathSync as ARn}from"node:fs";import Mfe from"node:path";import{fileURLToPath as PRn}from"node:url";function U5(){let o=process.env.ARCHIK_PKG_ROOT;if(o)return Mfe.resolve(o);let c=Mfe.dirname(ARn(PRn(import.meta.url))),d=c;for(let g=0;g<10;g++){if(TRn(Mfe.join(d,"package.json")))return d;let f=Mfe.dirname(d);if(f===d)break;d=f}throw new Error(`archik: could not locate package root (start: ${c})`)}async function fct(o){let c=h3.join(U5(),"skills","archik","SKILL.md");try{await dct(c)}catch{return{ok:!1,reason:"missing-source",source:c}}let d=o.scope==="user"?h3.join(IKt.homedir(),".claude","skills"):h3.resolve(".claude","skills"),g=h3.join(d,"archik"),f=h3.join(g,"SKILL.md");if(!o.force)try{return await dct(f),{ok:!1,reason:"exists",target:f}}catch{}return await CKt(g,{recursive:!0}),await _Kt(c,f),{ok:!0,target:f,scope:o.scope}}async function xfe(o){let c=h3.join(U5(),"commands"),d;try{d=(await NRn(c)).filter(v=>v.endsWith(".md"))}catch{return{ok:!1,reason:"missing-source",source:c}}if(d.length===0)return{ok:!1,reason:"missing-source",source:c};let g=o.scope==="user"?h3.join(IKt.homedir(),".claude","commands"):h3.resolve(".claude","commands"),f=h3.join(g,"archik");if(!o.force){let v=[];for(let k of d)try{await dct(h3.join(f,k)),v.push(k)}catch{}if(v.length>0)return{ok:!1,reason:"exists",existing:v,targetDir:f}}await CKt(f,{recursive:!0});let b=[];for(let v of d)await _Kt(h3.join(c,v),h3.join(f,v)),b.push(v);return{ok:!0,targetDir:f,copied:b,scope:o.scope}}async function LKt(o){let c=Zr(o,"user")==="true"?"user":"project",d=Zr(o,"force")==="true",g=await fct({scope:c,force:d});if(!g.ok)return g.reason==="missing-source"?console.error(`\u2717 Source skill not found at ${g.source}`):console.error(`\u2717 ${g.target} already exists. Pass --force to overwrite.`),1;let f=g.scope==="user"?"user-wide":"this project";return console.log(`\u2713 Installed archik skill (${f}) \u2192 ${g.target}`),0}var FRn=`version: "1.0"
375
375
  name: My Architecture
376
376
  description: Initial scaffold \u2014 edit this file to grow your diagram.
377
377
  nodes:
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "archik",
3
- "version": "0.12.37",
3
+ "version": "0.12.39",
4
4
  "description": "The shared vocabulary between you and Claude Code, at the engineering level. Plain-YAML architecture diagrams with a live browser canvas, headless SVG render in CI, and an installable Claude skill so the model treats the diagram as the spec.",
5
5
  "keywords": [
6
6
  "architecture",
@@ -33,8 +33,9 @@
33
33
  "docs/hero.svg",
34
34
  "docs/logo.svg",
35
35
  "docs/wordmark.svg",
36
- ".claude/skills/archik",
37
- ".claude/commands/archik",
36
+ "skills",
37
+ "commands",
38
+ ".claude-plugin",
38
39
  "README.md",
39
40
  "LICENSE"
40
41
  ],
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes