archik 0.1.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.
@@ -0,0 +1,341 @@
1
+ ---
2
+ name: archik
3
+ description: Use whenever architecture.archik.yaml exists in the project, or the user asks about the system's architecture, services, dependencies, or data flow. The YAML is the shared map of the project between the user and Claude — read it before answering structural questions, and propose updates when work introduces or changes nodes/edges. Also covers the archik CLI for validation and rendering.
4
+ ---
5
+
6
+ # Archik — the project's shared map
7
+
8
+ `architecture.archik.yaml` at the project root is **the user's source of
9
+ truth for what the system looks like**. It lists every meaningful node
10
+ (services, databases, queues, frontends, external APIs, …) and the
11
+ edges between them. The canvas in the browser is a stateless projection
12
+ of this file — when the user says "the orders service" or "the events
13
+ queue", they mean the entity with that `id` in the YAML.
14
+
15
+ Treat this file as a shared vocabulary. It exists so the user and you
16
+ can talk about the system without re-explaining it every time.
17
+
18
+ ## Protocol
19
+
20
+ 1. **Before** answering structural questions — *"what does X do?",
21
+ "what depends on Y?", "where does data flow when …?"* — read
22
+ `architecture.archik.yaml`. Don't guess from filenames or memory.
23
+ 2. **When** work introduces, removes, or rewires components, propose
24
+ an update to the YAML alongside the implementation. The user owns
25
+ the file — suggest, don't silently apply.
26
+ 3. **After** every edit to the YAML, run `archik validate`. Fix any
27
+ reported errors before declaring the change done.
28
+
29
+ The sections below are the detailed reference behind these three
30
+ rules — *when* to consult, *when* to propose, schema, taxonomy,
31
+ relationship vocabulary, and CLI.
32
+
33
+ ## When to consult the YAML
34
+
35
+ Read it **before answering** any of these:
36
+
37
+ - "What does X do?" / "What's the responsibility of X?"
38
+ - "What writes to / reads from / publishes to Y?"
39
+ - "Where does data flow when …?"
40
+ - "What services exist?" / "What's in the architecture?"
41
+ - "What depends on Z?" / "What would break if I remove Z?"
42
+ - "Is there a queue / cache / gateway already?"
43
+
44
+ Don't guess. The YAML has the answer or it doesn't — if it doesn't, say
45
+ so and offer to add it.
46
+
47
+ ## When to propose updates to the YAML
48
+
49
+ Proactively suggest edits (don't silently apply them — the user owns
50
+ this file) when the work you're doing changes the structure:
51
+
52
+ - Adding a new service, function, worker, frontend, queue, DB, etc.
53
+ - Introducing a new dependency between existing components.
54
+ - Adding a new external API integration.
55
+ - Removing or renaming a component.
56
+ - Splitting one component into several, or merging several into one.
57
+
58
+ Frame it as: *"This adds a `payments-worker` that reads from the
59
+ `order-events` queue and writes to `payments-db`. Want me to update
60
+ `architecture.archik.yaml` to capture that?"*
61
+
62
+ ## When to defer
63
+
64
+ - Pure refactors that don't change the component graph → leave it alone.
65
+ - Local file moves / renames → leave it alone.
66
+ - Bug fixes inside an existing node → leave it alone.
67
+
68
+ The YAML tracks **shape**, not implementation detail.
69
+
70
+ ## Hard rules for editing
71
+
72
+ - **Never put coordinates** (`x`, `y`, `width`, `height`, `viewport`) in
73
+ the YAML. Layout is computed by ELK on every render. The schema
74
+ rejects unknown keys at root, node, edge, and metadata levels.
75
+ - **Every id matches** `^[a-z][a-z0-9-]*$` — lowercase, starts with a
76
+ letter, hyphens allowed.
77
+ - **Edges reference existing nodes**. If `from` or `to` doesn't match a
78
+ node id, the document fails to load.
79
+ - **`parentId` references existing nodes** (typically `module` or
80
+ `custom` containers).
81
+ - **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.
83
+ - **Don't change `version`** — it's `"1.0"`.
84
+
85
+ ## Schema (top-level)
86
+
87
+ ```yaml
88
+ version: "1.0" # literal — must be "1.0"
89
+ name: My Architecture # required
90
+ description: ... # optional
91
+ nodes: [ ... ] # required, may be empty
92
+ edges: [ ... ] # required, may be empty
93
+ metadata: # optional
94
+ createdAt: "..."
95
+ updatedAt: "..."
96
+ ```
97
+
98
+ ## Node fields
99
+
100
+ ```yaml
101
+ - id: orders # required, kebab-case
102
+ kind: service # required, see taxonomy below
103
+ name: Orders # required, human-readable
104
+ description: ... # optional, free text
105
+ stack: Go + Postgres # optional, technology label shown under name
106
+ responsibilities: # optional, string list
107
+ - place orders
108
+ - track shipments
109
+ interfaces: # optional, list of contract specs
110
+ - name: POST /orders
111
+ protocol: http
112
+ description: ... # optional
113
+ notes: # optional, list of free-text notes
114
+ - "Migrated from monolith in 2024."
115
+ parentId: platform # optional, must reference a real node
116
+ metadata: # optional, free record
117
+ team: fulfillment
118
+ ```
119
+
120
+ ## Node kinds (26 total, grouped by purpose)
121
+
122
+ | Group | Kinds |
123
+ | ----------- | --------------------------------- |
124
+ | Compute | `service`, `function`, `worker`, `agent` |
125
+ | Data | `database`, `cache`, `vectordb`, `storage` |
126
+ | Messaging | `queue`, `topic`, `stream` |
127
+ | Networking | `gateway`, `cdn` |
128
+ | Hexagonal | `interface`, `adapter`, `port` |
129
+ | AI / ML | `llm`, `prompt`, `tool` |
130
+ | Identity | `auth` |
131
+ | Observability | `observability` |
132
+ | Cloud | `cloud` |
133
+ | UI | `frontend` |
134
+ | External | `external` |
135
+ | Structural | `module`, `custom` |
136
+
137
+ Picking the right kind:
138
+
139
+ - A long-running HTTP service → `service`
140
+ - A serverless function / lambda → `function`
141
+ - A background job consumer → `worker`
142
+ - An autonomous AI agent driving tools → `agent`
143
+ - Postgres / DynamoDB / etc → `database`
144
+ - Redis / Memcached → `cache`
145
+ - Pinecone / pgvector / Weaviate → `vectordb`
146
+ - S3 / GCS / blob → `storage`
147
+ - SQS / RabbitMQ work queue → `queue`
148
+ - SNS / Kafka pub/sub topic → `topic`
149
+ - Kafka / Kinesis stream-of-events → `stream`
150
+ - API gateway, ingress, edge proxy → `gateway`
151
+ - CloudFront / Fastly → `cdn`
152
+ - An abstract contract → `interface`
153
+ - A concrete impl of an interface → `adapter`
154
+ - A hexagonal-architecture port → `port`
155
+ - An LLM API (OpenAI, Anthropic) → `llm`
156
+ - A reusable prompt template → `prompt`
157
+ - An LLM-callable tool → `tool`
158
+ - Auth0 / Clerk / IDP → `auth`
159
+ - Datadog / Grafana / OTEL collector → `observability`
160
+ - A managed cloud service that doesn't fit → `cloud`
161
+ - Browser / mobile / CLI → `frontend`
162
+ - Third-party API you don't run → `external`
163
+ - A logical grouping container (component, module) → `module`
164
+ - Anything that doesn't fit and you want a custom shape → `custom`
165
+
166
+ `module` and `custom` render as containers when they have children — set
167
+ `parentId` on the children to nest them inside.
168
+
169
+ ## Edge fields
170
+
171
+ ```yaml
172
+ - id: api-db # required, kebab-case
173
+ from: api # required, must be a node id
174
+ to: db # required, must be a node id
175
+ relationship: writes # required, see vocabulary below
176
+ label: "create order" # optional, shows on the canvas
177
+ description: ... # optional
178
+ protocol: http # optional
179
+ color: "#f97316" # optional, any CSS color (hex / named / var())
180
+ ```
181
+
182
+ ## Relationships (12 total)
183
+
184
+ | Category | Relationship | Visual |
185
+ | -------------- | ------------ | ------ |
186
+ | Sync calls | `http_call`, `invokes`, `routes_to` | dotted, animated |
187
+ | Data access | `reads`, `writes` | dotted, animated |
188
+ | Messaging | `publishes`, `subscribes`, `streams_to` | dotted, animated |
189
+ | Architectural | `implements`, `depends_on`, `has_a`, `uses` | static + muted |
190
+
191
+ Picking the right relationship:
192
+
193
+ - Service-to-service HTTP / RPC call → `http_call`
194
+ - Calling a function or agent → `invokes`
195
+ - Gateway routing requests → `routes_to`
196
+ - DB read query → `reads`
197
+ - DB write / mutation → `writes`
198
+ - Emitting an event / message → `publishes`
199
+ - Consuming an event / message → `subscribes`
200
+ - Continuous stream of records → `streams_to`
201
+ - Adapter implements an interface → `implements`
202
+ - A depends on B at the package / build level → `depends_on`
203
+ - Composition / ownership ("has a") → `has_a`
204
+ - Lighter-weight dependency → `uses`
205
+
206
+ ## Common editing patterns
207
+
208
+ **Adding a service that writes to a database**:
209
+
210
+ ```yaml
211
+ nodes:
212
+ - id: payments
213
+ kind: service
214
+ name: Payments
215
+ stack: Go
216
+ - id: payments-db
217
+ kind: database
218
+ name: Payments DB
219
+ stack: Postgres 16
220
+ edges:
221
+ - id: payments-writes-db
222
+ from: payments
223
+ to: payments-db
224
+ relationship: writes
225
+ ```
226
+
227
+ **Adding an LLM agent with tools**:
228
+
229
+ ```yaml
230
+ nodes:
231
+ - id: support-agent
232
+ kind: agent
233
+ name: Support Agent
234
+ description: Handles tier-1 customer questions.
235
+ - id: openai
236
+ kind: llm
237
+ name: GPT-4o
238
+ - id: lookup-orders
239
+ kind: tool
240
+ name: Lookup orders
241
+ edges:
242
+ - id: agent-llm
243
+ from: support-agent
244
+ to: openai
245
+ relationship: invokes
246
+ - id: agent-uses-tool
247
+ from: support-agent
248
+ to: lookup-orders
249
+ relationship: uses
250
+ ```
251
+
252
+ **Grouping nodes inside a module**:
253
+
254
+ ```yaml
255
+ nodes:
256
+ - id: orders-module
257
+ kind: module
258
+ name: Orders
259
+ - id: orders-api
260
+ kind: service
261
+ name: Orders API
262
+ parentId: orders-module
263
+ - id: orders-db
264
+ kind: database
265
+ name: Orders DB
266
+ parentId: orders-module
267
+ ```
268
+
269
+ ELK will nest them visually inside the module's container.
270
+
271
+ **Adding a hexagonal port + adapter**:
272
+
273
+ ```yaml
274
+ nodes:
275
+ - id: payment-port
276
+ kind: port
277
+ name: Payment Port
278
+ - id: stripe-adapter
279
+ kind: adapter
280
+ name: Stripe Adapter
281
+ edges:
282
+ - id: stripe-implements-port
283
+ from: stripe-adapter
284
+ to: payment-port
285
+ relationship: implements
286
+ ```
287
+
288
+ ## CLI
289
+
290
+ These commands are available globally if archik was installed via
291
+ `npm link`. Each defaults to `architecture.archik.yaml` in the current
292
+ directory unless given a positional path.
293
+
294
+ ```
295
+ archik validate # schema check (run after every edit)
296
+ archik validate path/to/file.yaml
297
+ archik render --out diagram.svg # headless layout → SVG
298
+ archik render --theme light --out diagram-light.svg
299
+ archik watch # re-render SVG on save
300
+ archik check # drift: nodes vs source dirs
301
+ archik dev # open the live editor in the browser (foreground)
302
+ archik start # same as dev, detached — returns the prompt
303
+ archik stop # stop the background server
304
+ archik status # list running archik instances
305
+ archik init # scaffold a starter file
306
+ archik skill # install/refresh this skill in cwd
307
+ ```
308
+
309
+ If `archik` isn't on PATH (the user hasn't run `npm link` yet), fall
310
+ back to the in-repo form: `npm run archik -- <command>` from the
311
+ archik checkout.
312
+
313
+ ## Verification workflow
314
+
315
+ After **every** edit you make to `architecture.archik.yaml`:
316
+
317
+ 1. Run `archik validate` — fix any reported errors before declaring
318
+ the change done. Schema errors include the path of the offending
319
+ field so you can fix them precisely.
320
+ 2. If the project has an `archik dev` server running, the file watcher
321
+ broadcasts the change automatically — no restart needed.
322
+ 3. If the project commits a rendered SVG (e.g. `docs/architecture.svg`),
323
+ regenerate it with `archik render --out docs/architecture.svg` so
324
+ the committed picture matches the YAML.
325
+ 4. For nodes whose `kind` implies code (`service`, `function`, `worker`,
326
+ `agent`, `frontend`, `gateway`, `tool`, `module`), consider
327
+ `archik check` to flag nodes that don't have a matching source
328
+ folder under `src/`, `services/`, `packages/`, or `apps/`.
329
+
330
+ ## Things to avoid
331
+
332
+ - Don't invent kinds or relationships outside the lists above — the
333
+ Zod schema rejects them.
334
+ - Don't add visual properties (colors, sizes, positions) to nodes.
335
+ Only edges have `color`. Everything else comes from the renderer.
336
+ - Don't add empty `notes` / `responsibilities` / `interfaces` lists —
337
+ either include real entries or omit the field entirely.
338
+ - Don't blow away `description`, `responsibilities`, or `notes` the
339
+ user wrote unless they ask you to. They're encoded context.
340
+ - Don't bulk-restructure the file as a side effect of a small edit.
341
+ Make the minimal change that captures what changed.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Bashar
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,106 @@
1
+ # Archik
2
+
3
+ A JSON-native architecture diagram tool. The YAML file is the source of
4
+ truth; the canvas is a stateless projection of it. Both humans and LLMs
5
+ edit the same file. Layout is computed by ELK; coordinates never appear
6
+ in the YAML.
7
+
8
+ ## Install once, use in every project
9
+
10
+ Inside this repo:
11
+
12
+ ```bash
13
+ npm install
14
+ npm link # exposes the `archik` binary on your PATH
15
+ ```
16
+
17
+ `npm link` creates a symlink from your global node binaries to
18
+ `bin/archik.js` in this directory. The bin script resolves through the
19
+ symlink (via `realpath`), spawns `tsx` against `src/cli/index.ts`, and
20
+ runs the CLI without a separate build step.
21
+
22
+ If you ever want to remove it:
23
+
24
+ ```bash
25
+ npm unlink -g archik
26
+ ```
27
+
28
+ ## Per-project workflow
29
+
30
+ The YAML lives in your target project, not here. From any project
31
+ directory:
32
+
33
+ ```bash
34
+ cd ~/projects/my-app
35
+ archik init # only the first time — scaffolds architecture.archik.yaml
36
+ archik dev # opens the live canvas in your browser
37
+ ```
38
+
39
+ `archik dev` starts the Vite dev server from Archik's install dir, but
40
+ points it at the current working directory's `architecture.archik.yaml`
41
+ via the `ARCHIK_DOC_PATH` env var. The browser canvas loads, the file
42
+ watcher sees your edits, the inspector saves back to your project's
43
+ file. Nothing about Archik lives inside your project.
44
+
45
+ ## All commands
46
+
47
+ ```
48
+ archik init Scaffold a starter architecture.archik.yaml
49
+ archik dev [path] Open the canvas in your browser (foreground)
50
+ --port <n> dev server port
51
+ --host <addr> bind to host
52
+ --no-open don't auto-open the browser
53
+ archik start [path] Same as dev, but detached — prompt returns immediately
54
+ --port <n> dev server port
55
+ --host <addr> bind to host
56
+ archik stop [path] Stop the background server started with `archik start`
57
+ archik status List running archik instances (across all projects)
58
+ archik validate [path] Validate a document against the schema
59
+ archik render [path] Render to a self-contained SVG file
60
+ --out <file> output path (default: diagram.svg)
61
+ --theme <name> "dark" (default) or "light"
62
+ archik watch [path] Re-render to SVG on file changes
63
+ archik check [path] Drift detection — flag nodes without source dirs
64
+ ```
65
+
66
+ Use `archik dev` for an interactive session you'll Ctrl+C to end, and
67
+ `archik start` / `archik stop` when you want the canvas running in the
68
+ background while you keep working in the same terminal. State is kept in
69
+ `$TMPDIR/archik-cli/` keyed by the YAML path, so you can run several
70
+ projects' canvases at once.
71
+
72
+ Default path is `architecture.archik.yaml` in the current directory.
73
+
74
+ ## CI usage
75
+
76
+ ```bash
77
+ # Fail the build if the diagram has schema errors:
78
+ archik validate
79
+
80
+ # Generate an SVG of your architecture for the docs:
81
+ archik render --theme light --out docs/architecture.svg
82
+
83
+ # Compare nodes to source dirs and warn about drift:
84
+ archik check
85
+ ```
86
+
87
+ ## Directory layout (this repo)
88
+
89
+ ```
90
+ src/
91
+ domain/ Pure schema + commands (no React, no ELK)
92
+ layout/ ELK adapter behind a LayoutEngine interface
93
+ render/ Pure SVG renderer (DiagramSvg, per-kind shapes, edges)
94
+ io/ YAML/JSON, exporters, file adapter, live-reload
95
+ ui/ React app — toolbar, inspectors, modals, popovers
96
+ cli/ The `archik` binary you just installed
97
+ vite/ Vite plugin that watches + serves the YAML over HTTP/WS
98
+ .claude/skills/ archik.md — schema + patterns for AI editors
99
+ ```
100
+
101
+ ## For AI editors
102
+
103
+ `.claude/skills/archik.md` documents the schema, all 26 node kinds, all
104
+ 12 relationships, common editing patterns, and the verification
105
+ workflow. Claude Code in this repo (or any project that copies the
106
+ skill) gets the right vocabulary automatically.
package/bin/archik.js ADDED
@@ -0,0 +1,58 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Global entry point. Resolves the package root through symlinks
4
+ * (npm link / pnpm link), then dispatches to one of two backends:
5
+ *
6
+ * * Production install (`npm install archik`): runs the pre-built
7
+ * ESM bundle at `dist/cli/archik.mjs` directly with node — no
8
+ * TypeScript, no tsx, no source files.
9
+ * * In-repo development (this checkout, before `npm run build`):
10
+ * falls back to spawning `tsx` against `src/cli/index.ts`.
11
+ *
12
+ * Either way, ARCHIK_PKG_ROOT is set so the CLI doesn't have to guess
13
+ * where its install lives.
14
+ */
15
+ import { spawnSync } from "node:child_process";
16
+ import { dirname, resolve } from "node:path";
17
+ import { fileURLToPath } from "node:url";
18
+ import { existsSync, realpathSync } from "node:fs";
19
+
20
+ const here = dirname(realpathSync(fileURLToPath(import.meta.url)));
21
+ const pkgRoot = resolve(here, "..");
22
+ const args = process.argv.slice(2);
23
+ const env = { ...process.env, ARCHIK_PKG_ROOT: pkgRoot };
24
+
25
+ const distEntry = resolve(pkgRoot, "dist", "cli", "archik.mjs");
26
+
27
+ let result;
28
+ if (existsSync(distEntry)) {
29
+ result = spawnSync(process.execPath, [distEntry, ...args], {
30
+ stdio: "inherit",
31
+ env,
32
+ });
33
+ } else {
34
+ const tsxBin = resolve(
35
+ pkgRoot,
36
+ "node_modules",
37
+ ".bin",
38
+ process.platform === "win32" ? "tsx.cmd" : "tsx",
39
+ );
40
+ if (!existsSync(tsxBin)) {
41
+ console.error(
42
+ "archik: no built bundle and no tsx fallback available.\n" +
43
+ ` Looked for: ${distEntry}\n` +
44
+ ` and: ${tsxBin}\n` +
45
+ " Run `npm install` and `npm run build` from the archik checkout.",
46
+ );
47
+ process.exit(1);
48
+ }
49
+ const cliEntry = resolve(pkgRoot, "src", "cli", "index.ts");
50
+ const tsconfig = resolve(pkgRoot, "tsconfig.app.json");
51
+ result = spawnSync(
52
+ tsxBin,
53
+ ["--tsconfig", tsconfig, cliEntry, ...args],
54
+ { stdio: "inherit", env },
55
+ );
56
+ }
57
+
58
+ process.exit(result.status ?? 1);