@zerwiz/ymir 0.1.1 → 0.1.3

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.
Files changed (2) hide show
  1. package/README.md +558 -51
  2. package/package.json +1 -1
package/README.md CHANGED
@@ -1,87 +1,594 @@
1
1
  # @zerwiz/ymir
2
2
 
3
- > **The front door to Ymir** — a local, self-hosted, multi-agent AI runtime.
4
- > One command to stand it up on your own machine.
3
+
4
+ ---
5
+
6
+ <p align="center">
7
+ <strong>created by zerwiz</strong> · <a href="https://zerwiz.org">https://zerwiz.org</a> · whynotproductions<br>
8
+ <em>a hobby project, made for the love of the craft. use it, fork it, enjoy it.</em>
9
+ </p>
10
+
11
+ ---
12
+
13
+ > **The front door to Ymir** — a single-operator, self-hosted, multi-agent AI runtime.
14
+ > One command stands it up on your own machine. No hosting, no accounts.
5
15
 
6
16
  ```bash
7
- # curl
17
+ # 1 · curl — fetch the bootstrap and run it
8
18
  curl -fsSL https://raw.githubusercontent.com/zerwiz/ymir-release/main/install.sh | bash
9
19
 
10
- # npm
11
- npx @zerwiz/ymir
20
+ # 2 · npx — no install, run once
21
+ npx @zerwiz/ymir # add --check (report only) or --yes (unattended)
22
+
23
+ # 3 · npm global — install the command, then run it
24
+ npm i -g @zerwiz/ymir
25
+ ymir
26
+
27
+ # 4 · clone the distro and run its installer directly
28
+ git clone https://github.com/zerwiz/ymir.git ~/.ymir
29
+ bash ~/.ymir/bin/ymir-install.sh
12
30
  ```
13
31
 
14
- Both do the same thing: fetch the Ymir distro, then run its installer which
15
- provisions, self-heals, and **validates** what it claims is running.
32
+ > All four run the **same installer**. It is idempotent run it again and it heals
33
+ > forward. `--check` shows the plan without writing anything.
34
+
35
+ This npm package is only the **bootstrap** (install.sh + a thin `ymir` bin): it
36
+ fetches the Ymir distro and runs its installer, which provisions, self-heals and
37
+ **validates** what it claims is running. It carries no secrets.
38
+
39
+ > **Alpha** — the forge is hot and the anvil works, but expect rough edges, and do
40
+ > not expose it as a public service yet.
41
+
42
+ ---
43
+
44
+ # YMIR — The Single-Tenant Agent Operating System
45
+
46
+ > **One operator. One repo. A whole business, run by a Norse-named agent fleet.**
47
+
48
+ ![Ymir — the single-tenant agent OS](assets/ymir-banner-03.png)
49
+
50
+ Ymir is a lean, single-operator agentic OS. You are the **Allfather**; **Brokk** is
51
+ your primary agent; **Eindri** are the isolated workers it dispatches. Everything —
52
+ development, marketing, business strategy, life — runs from one repository, with an
53
+ audit ledger, a memory well, one tenant and its workspaces, and a control plane you actually look at.
54
+
55
+ ---
56
+
57
+ ## The Allfather's Chain
58
+
59
+ The Allfather holds the only chain. If the Allfather does not draw it, Ymir walks
60
+ the machine as the Allfather walks it — no gate between the agent and the tools,
61
+ no second master but the Allfather's own hand.
16
62
 
17
63
  ---
18
64
 
19
- ## What is Ymir?
65
+ ## The Lore (short version)
20
66
 
21
- A **brutal multi-agent AI runtime** where autonomous smiths forge code inside
22
- sealed sandboxes and persistent vector-memory wells. It is one program, carved
23
- into realms: a fleet of named agents, isolated git worktrees, an append-only
24
- audit ledger, and an anti-hallucination gate — all on hardware you own.
67
+ Ymir is not a theme the myths are **load-bearing allegory**. Every subsystem is
68
+ named for the figure whose role matches the machine's job:
25
69
 
26
- Norse myth is **structural allegory**, not decoration. Every name explains a job:
70
+ The platform is the primordial giant **Ymir**, from whose body the worlds were
71
+ carved. The smiths are **Brokk** (the bellows-smith, your primary agent) and
72
+ **Eindri** (the workers who out-forged the gods). Memory is **Mimirsbrunn**, the
73
+ well at the root of **Yggdrasil**, and **Kaia** is the oracle who speaks from it.
74
+ Every significant action is carved into **Runes**, an append-only ledger. Work
75
+ passes the **seven gates** and is built on **borrowed anvils** — validated open
76
+ source first, always. The full tale: [`docs/lore.md`](docs/lore.md).
27
77
 
28
- | Name | What it is |
78
+ | Component | Role |
29
79
  |---|---|
30
- | **Ymir** | the substrate one program, one machine, all realms carved from it |
31
- | **Brokk** | the primary agent — the bellows that drives the forge |
32
- | **Eindri** | isolated worker agents smiths in sealed sandboxes |
33
- | **Utgard** | the sandbox untrusted code runs there, never in the halls |
34
- | **Yggdrasil** | git worktrees — parallel branches, zero collision |
35
- | **Mimirsbrunn** | the memory wellvector + full-text + local embeddings |
36
- | **Ratatoskr** | the message bus — the agent-to-agent backbone (A2A 1.0) |
37
- | **Runes** | the append-only audit ledger a rune once carved is never un-carved |
38
- | **Hlidskjalf** | the control plane — the high seat that sees every realm |
39
- | **Sessrúmnir** | the seat-hall — where you converse with the fleet |
40
-
41
- ## Install
80
+ | **Ymir** | the platform / host daemon |
81
+ | **Brokk** | the primary autonomous agent |
82
+ | **Eindri** | isolated workersSindri, Bragi, Huginn, Mímir, Forseti, Snotra, Kvasir |
83
+ | **Mimirsbrunn** | the memory well (engram) + Kaia's bridge |
84
+ | **Yggdrasil** | git worktrees — zero-collision parallelism |
85
+ | **Utgard** | ephemeral Docker sandboxesthe execution barrier |
86
+ | **Runes** | the append-only audit ledger |
87
+ | **Hlidskjalf** | the control plane / observability |
88
+
89
+ ---
90
+
91
+ ## What it is
92
+
93
+ - **A distro, not an app.** Launch a supported harness in the repo and you take the
94
+ high seat: context is injected before your first turn, the model bridge is raised,
95
+ the scheduled jobs start.
96
+ - **Isolation by default.** Complex work runs in **Yggdrasil** worktrees sealed by
97
+ **Utgard** sandboxes; a failed run never touches main.
98
+ - **Audit everything.** **Runes** is an append-only, checksum-chained ledger.
99
+ - **Memory that grounds.** **Mimirsbrunn** (engram) is drunk from before dispatch and
100
+ watered after; a dry well never blocks.
101
+ - **Humans in the loop.** **Mjollnir** opens PRs; nothing force-merges.
102
+ - **Open source first.** Ymir owns only three things — the UI, the runtime, and
103
+ A2A collaboration. Everything else wears a Norse name over a validated engine.
104
+
105
+ ---
106
+
107
+ ## Host platforms — three first-class identities
108
+
109
+ Ymir is not portable-in-theory; it is **native** to the machine it runs on. Three
110
+ platforms are first-class, and each one is detected, used, and learned rather than
111
+ merely tolerated.
112
+
113
+ | Identity | What it means | Where it lives |
114
+ |---|---|---|
115
+ | **Omarchy-native** | The host desktop is Omarchy (Arch + Hyprland). Ymir reads monitors/scale, lets Hyprland own window placement, mitigates the amdgpu GPU crash, and **learns the user's setup** — packages, configs, Omarchy version — re-learning after every `omarchy update` via a `post-update` hook. | `bin/omarchy-sense.sh`, `bin/omarchy-hook-install.sh`, skill `ymir` |
116
+ | **herdr-first (Þjazi)** | Agent panes need a terminal backend. **herdr** is preferred (Þjazi protocol **14+**; presentation spaces at **0.8.0+**), **tmux** is the accepted reference backend. A missing backend is reported, never silently degraded. | `bin/herdr-ensure.sh`, skill `ymir` |
117
+ | **pi-native** | The [pi](https://pi.dev) coding harness is a first-class surface: extensions, skills, prompt templates, themes, custom providers, and **pi packages** (npm/git) are all live. This is where Ymir gains reach — a new capability can be a pi extension or a packaged bundle, not just a shell script. | `.pi/extensions/`, `.pi/settings.json`, `.pi/mcp.json` |
118
+
119
+ **Why this matters.** The freedom runs both ways: because Ymir is pi-native it can
120
+ ship **pi packages** — bundling extensions, skills, prompt templates, and themes
121
+ for others to `pi install` — and because it is Omarchy-native it can help an
122
+ Omarchy user set up and tune the whole machine, not just the repo.
123
+
124
+ On a non-Omarchy host the Omarchy steps are a clean `SKIP`; Ymir still runs. On a
125
+ host without herdr, tmux carries the panes. On a harness that is not pi, the
126
+ runtime adapts through the harness adapters (see `hamr`).
127
+
128
+ ### Omarchy-native
129
+
130
+ Ymir treats the host desktop as part of itself. It **detects** Omarchy
131
+ (`/usr/share/omarchy`), **reads** the real layout (`hyprctl monitors -j` — physical
132
+ size *and* scale, because a 1920×1200 panel at scale 1.5 is a 1280×800 logical
133
+ desktop, and mixing the two is the classic placement bug), and **lets Hyprland own
134
+ placement** rather than fighting the compositor.
135
+
136
+ - **Desktop placement.** On Omarchy the numbered **desktops** (`1 2 3 4 5 …`) are
137
+ the operator's "screens". `bin/desktop-place.sh` gives each Ymir app its **own
138
+ desktop, preferring an empty one**, via Omarchy's own rule idiom
139
+ (`o.window({ class = "^ymir-hlidskjalf$" }, { workspace = "2" })`), and never
140
+ edits `/usr/share/omarchy/`.
141
+ - **It learns the machine.** `bin/omarchy-sense.sh` records a comparable snapshot
142
+ (Omarchy version, explicit packages, config files, monitors, scale) and **diffs**
143
+ it, so Ymir can advise on *this* setup. `bin/omarchy-hook-install.sh` installs a
144
+ `post-update.d` hook, so **every `omarchy update` re-teaches it**.
145
+ - **It survives the hardware.** On a small-VRAM iGPU the Wayland GPU process can
146
+ die with `amdgpu: Not enough memory for command submission` (SIGSEGV, not an OOM);
147
+ `YMIR_DESKTOP_DISABLE_GPU=1` runs the dashboards on software rendering.
148
+
149
+ Full reference: the `ymir` skill. Omarchy's own skill is authoritative for
150
+ Omarchy itself; ours adds the Ymir integration.
151
+
152
+ ### herdr-first (Þjazi)
153
+
154
+ Every Eindri worker lives in a terminal pane, so the backend matters. Ymir prefers
155
+ **herdr** and accepts **tmux** — and never degrades silently.
42
156
 
43
157
  ```
44
- Requirements: git · curl · node ≥ 18 (for the npm route) · bun/docker (the
45
- installer provisions what it can, and reports honestly what it cannot)
158
+ backend_priority[3]{rank,backend,note}:
159
+ "1","herdr","preferred; protocol 14+ for panes, 0.8.0+ for presentation spaces"
160
+ "2","tmux","verified reference backend"
161
+ "3","none","spawn is refused with a plain reason"
46
162
  ```
47
163
 
164
+ `bin/herdr-ensure.sh` verifies the *version* (not just presence) and installs via
165
+ the pinned, SHA-256-verified installer when herdr is absent. Selection order:
166
+ `config/backend` → `BROKK_BACKEND` → `HERDR_ENV=1` → else tmux. Full reference:
167
+ the `ymir` skill.
168
+
169
+ ### pi-native
170
+
171
+ [pi](https://pi.dev) is the harness Ymir runs in, and Ymir uses that fully rather
172
+ than treating it as a shell to be wrapped:
173
+
174
+ - **Extensions** — `.pi/extensions/` carries live behaviour (the watcher arm, the
175
+ turn-end guard, the Ró presentation preference, the agent-state surface).
176
+ - **Packages** — `pi install npm:<pkg>` / `git:<repo>` bundles extensions, skills,
177
+ prompt templates, and themes. Ymir can **ship its own**, so a Ymir capability can
178
+ be distributed and installed like any pi package, not only as a shell script.
179
+ - **Model providers** — pi resolves models from `~/.pi/agent/models.json`, whose
180
+ shape is `{"providers": {...}}`. Local servers (LM Studio, Ollama, vLLM) and the
181
+ Bifrost bridge are configured the same way, so the fleet runs on local or cloud
182
+ models by the operator's choice.
183
+
184
+ This is the freedom you gain from being pi-native: a new capability has three
185
+ possible homes — a shell script, a skill, or a **pi package** — and the last one is
186
+ installable by anyone running pi.
187
+
188
+ ---
189
+
190
+ ## System Map
191
+
192
+ | Subsystem | Norse Name | Role |
193
+ |---|---|---|
194
+ | Platform root | **Ymir** | master daemon / host OS |
195
+ | Primary agent | **Brokk** | the autonomous operator's hand |
196
+ | Sub-agent workers | **Eindri** | isolated sandboxed workers |
197
+ | Git worktrees | **Yggdrasil** | zero-collision parallel edits |
198
+ | Docker sandbox | **Utgard** | ephemeral execution barrier |
199
+ | Gateway | **Bifrost** | reverse proxy / HTTP routing |
200
+ | Model bridge | **Bifrost bridge** | local OpenAI-compatible endpoint for the fleet |
201
+ | OAuth guard | **Heimdall** | GitHub OAuth / JWT |
202
+ | Tunnel | **Gjallarhorn** | Cloudflare outbound tunnel |
203
+ | Dashboard | **Hlidskjalf** | observability & control plane |
204
+ | File browser | **Skrymir** | web file explorer |
205
+ | Workspaces | **workspace/** | personal & work scopes over domains |
206
+ | Shared space | **Midgard** | shared assets & repos |
207
+ | Message bus | **Ratatoskr** | A2A 1.0 backbone (cards, lifecycle, Redis) |
208
+ | Vector memory | **Mimirsbrunn** | engram store + Kaia's bridge (`:4602`) |
209
+ | Audit ledger | **Runes** | append-only system log |
210
+ | Issue→PR | **Mjollnir** | autonomous fixes & PRs |
211
+ | Process monitor | **Valhalla** | PM2/Docker supervision |
212
+ | Skill synthesis | **Gungnir** | dynamic skill creation |
213
+ | Session digest | **Sága** | the context injected at session open |
214
+ | Watch / supervision | **Sýn** | watcher, guard, seat continuity |
215
+ | Session lock | **Gleipnir** | one live session per home |
216
+ | Scheduled jobs | **Nornir** | the fates who govern time |
217
+ | Host desktop (Omarchy) | **Omarchy** | the machine Ymir runs on: monitors, scale, themes, hooks |
218
+ | Terminal backend | **Þjazi** | agent panes — herdr (protocol 14+) or tmux |
219
+ | Harness surface | **pi** | extensions, skills, prompt templates, packages |
220
+
221
+ ---
222
+
223
+ ## Skills
224
+
225
+ Every reusable capability is a skill in [`.agents/skills/`](.agents/skills/), each
226
+ named for the figure whose role matches the work (the Gungnir naming law). Galdr is
227
+ the master builder; Tyr judges compliance.
228
+
229
+ | Skill | Norse | Purpose |
230
+ |---|---|---|
231
+ | `galdr` | Galdr | agent-CLI ergonomics + master builder/maintainer of the runtime |
232
+ | `tyr-check` | Tyr | the judge — validates tools/skills/docs against the 10 principles |
233
+ | `smidja` | Smiðja | the smithy: roster + bounded phases + typed envelopes |
234
+ | `hvild-afk` | Hvíld | away-mode supervision: routine wakes self-handled, escalations batched |
235
+ | `saga` | Sága | session bearings: fleet digest (/bearings) + recap (/ahoy) |
236
+ | `muninn-stow` | Muninn | session-knowledge curation, routing, and persistence |
237
+ | `jord-projects` | Jörð | project registry + delivery posture |
238
+ | `urdh` | Urðr | Allfather-hold lifecycle |
239
+ | `frigg-consent` | Frigg | consent / ask-user authority gate |
240
+ | `vor-diagnostics` | Vör | bootstrap + diagnostic reasoning |
241
+ | `nornir` | Nornir | fate & schedule: events + quota |
242
+ | `gjallarhorn-relay` | Gjallarhorn | public relay replies (X / Discord) |
243
+ | `eindri-homes` | Eindri | isolated worker homes |
244
+ | `syn-recovery` | Sýn | stuck-worker recovery playbook |
245
+ | `ymir` | Ymir | operate the host: update · Omarchy · Þjazi |
246
+ | `hamr` | Hamr | per-harness adapter reference (OpenCode, Pi, Claude, Cursor, Codex) |
247
+
248
+ The Galdr family enforces the 10 ergonomic principles (TOON output, minimal schemas,
249
+ self-correcting errors) and the runtime acceptance gates; run
250
+ `bash .agents/skills/galdr-cli/scripts/compliance-check.sh` before claiming done.
251
+
252
+ ---
253
+
254
+ ## Agents
255
+
256
+ The **Eindri** take a mythic name whose craft matches the job, and each runs in an
257
+ Utgard sandbox on a Yggdrasil worktree.
258
+
259
+ | Eindri | Figure | Craft | Speciality |
260
+ |---|---|---|---|
261
+ | **Sindri** | the smith | developer | code synthesis, refactoring, tests, CLIs |
262
+ | **Bragi** | the skald | marketer | content, SEO, social, campaigns |
263
+ | **Huginn** | the sage | researcher | RAG, web search, analysis |
264
+ | **Mímir** | the wise | planner | architecture, sequencing, risk |
265
+ | **Forseti** | the just | reviewer | review, QA, acceptance — changes nothing |
266
+ | **Snotra** | the wise-woman | documenter | docs, write-ups, changelogs |
267
+ | **Kvasir** | the knowing | scout | reconnaissance — changes nothing |
268
+
269
+ Profiles live in [`.agents/agents/`](.agents/agents/) and are bound to each tool by
270
+ `bin/valknut-load.sh` (OpenCode reads `.opencode/agent/`; Pi links resolve under
271
+ `.pi/agents/`).
272
+
273
+ ---
274
+
275
+ ## The Runtime — taking the seat
276
+
277
+ When a harness opens in the repo, **Sága** speaks before the first turn: the seat is
278
+ bound by **Gleipnir**, the model bridge is raised, the **Nornir** jobs start, and
279
+ the fleet context is injected (hidden, by design). Run-tier harnesses run the digest
280
+ and inject it; nudge-tier harnesses are asked.
281
+
282
+ | Harness | Session-start surface |
283
+ |---|---|
284
+ | **OpenCode** | `.opencode/plugins/{saga-sessionstart,syn-watch-arm,syn-turnend-guard}.js` |
285
+ | **Pi** | `.pi/extensions/{syn-turnend-guard,gna-pi-watch,ro,skuld-branch-supervision}.ts` |
286
+ | **Claude Code** | `.claude/settings.json` — `SessionStart` + `Stop` |
287
+ | **Cursor** | `.cursor/hooks.json` — `sessionStart` + `stop` + `preToolUse` |
288
+ | **Codex** | `.codex/hooks.json` — `SessionStart` + `PreToolUse` + `Stop` |
289
+
290
+ - **Seat:** `bin/saga-session-start.sh` — the one ordered digest.
291
+ - **Lock:** `bin/gleipnir-lock-lib.sh` — bound to the live session pid.
292
+ - **Bridge:** `bin/bifrost-bridge.sh` — raises the local model endpoint.
293
+ - **Jobs:** `bin/nornir-cron-start.sh` — daily briefing 07:00, observer, housekeeping, git sync.
294
+ - **Watch:** `bin/syn-watch-arm.sh` + the harness adapter.
295
+
296
+ Details: [`docs/session-start.md`](docs/session-start.md).
297
+
298
+ ---
299
+
300
+ ## The Control Plane — Hlidskjalf
301
+
302
+ [`apps/hlidskjalf`](apps/hlidskjalf) is the dashboard. It runs **live** against a
303
+ small local gate API that reads the runtime, or in **demo mode** on seeded data.
304
+
305
+ ```bash
306
+ scripts/start.sh # raises the gate API (:3889) + the SPA (:3888)
307
+ scripts/stop.sh
48
308
  ```
49
- YMIR_HOME where the distro lives (default ~/.ymir)
50
- YMIR_REPO the distro git remote (default https://github.com/zerwiz/ymir.git)
51
- YMIR_BRANCH the branch to track (default main)
309
+
310
+ Views: Fleet · Tasks · Well · Runes · Reviews · Processes · Files · OmniChat ·
311
+ Runtime · Cron · Forge · Profile. OmniChat speaks to **Kaia** for real (recall from
312
+ the well, replies via the local model bridge). Press **Enter demo mode** on the sign-in
313
+ screen to explore without the runtime.
314
+
315
+ ---
316
+
317
+ ## Quick Start
318
+
319
+ ```bash
320
+ git clone <this-repo> ~/Ymir && cd ~/Ymir
321
+ cp .env.example .env.local # fill in your keys (never committed)
322
+
323
+ # 1) First setup — prints a plan, asks you to accept, then validates itself
324
+ bin/ymir-install.sh # add --yes for non-interactive, or --check to preview
325
+
326
+ # 2) The control plane (live data)
327
+ scripts/start.sh # → http://127.0.0.1:3888/
328
+
329
+ # 3) The agent seat (any supported harness)
330
+ bin/saga-session-start.sh # the digest (auto-runs on harness open)
52
331
  ```
53
332
 
54
- Run it non-interactively, or just ask what it would do:
333
+ The installer is idempotent and self-healing: it provisions what it can in user
334
+ space (`bun`, `uv`, `mcp`, the Þjazi backend), installs the OSS engines, learns
335
+ the machine, places the desktop apps, and — on an **Omarchy** host — sets the
336
+ update hook that re-teaches it after every `omarchy update`. It ends by opening
337
+ both desktop apps and running `bin/ymir-validate.sh` to prove what stands.
338
+
339
+ ### What each platform buys you
340
+
341
+ The installer serves all three of Ymir's native homes on **every** run — a
342
+ non-Omarchy host loses only the Omarchy-specific hook, never the logic.
343
+
344
+ ```
345
+ platform_gifts[3]{platform,what_the_install_does,what_you_gain}:
346
+ "Omarchy","detects the host, reads hyprctl monitors+scale, writes o.window desktop rules, snapshots the setup, installs the post-update hook","your dashboards land on their own numbered desktops; Ymir knows THIS machine and relearns it when Omarchy moves"
347
+ "herdr (Þjazi)","bin/herdr-ensure.sh verifies the version against the floors and installs via the pinned, SHA-verified installer; tmux is the accepted reference","every Eindri worker gets a real pane in a real terminal; presentation spaces at 0.8.0+, panes at protocol 14+"
348
+ "pi","registers the harness surfaces, the MCP servers, and the model providers (local LM Studio / Ollama or the Bifrost bridge)","extensions, skills, prompt templates, themes, and pi PACKAGES are all live — a new Ymir capability can ship as an installable pi package"
349
+ ```
350
+
351
+ A new capability therefore has three possible homes — a shell script, a skill, or
352
+ a **pi package** — and on Omarchy it can also reach the desktop itself. That is the
353
+ freedom of being native to all three rather than portable to none.
354
+
355
+ Point a harness (OpenCode, Pi, Claude Code, Cursor, Codex) at the repo and it takes
356
+ the seat as **Brokk**. Read [`AGENTS.md`](AGENTS.md) for the operating laws and
357
+ [`docs/masterplan.md`](docs/masterplan.md) for the forge orders.
358
+
359
+ ---
360
+
361
+ ## Stack — Today vs Target
362
+
363
+ | Layer | Today (agent-proficient) |
364
+ |---|---|
365
+ | Control plane & daemons | **TypeScript** (Node 22) / **Bun** |
366
+ | Agent orchestration | **Python 3.12+** + TypeScript |
367
+ | UI / UX | **React + Vite** (Hlidskjalf) |
368
+ | Inter-agent | **A2A 1.0** (JSON-RPC 2.0 / SSE) + **Redis** |
369
+ | Memory | **engram** — the Mimirsbrunn well |
370
+ | Gateway / Auth / Tunnel | Traefik/Caddy · OAuth2-proxy · cloudflared |
371
+ | Sandbox | Docker (rootless, network-none) |
372
+ | Runtime backend | Pi / OpenCode harnesses; herdr/tmux panes |
373
+
374
+ **Target (Ymir Rut v2.6 — re-forged later, never redesigned):** Rust (Edition 2024) +
375
+ Tokio · NATS JetStream · gRPC/Protobuf · libgit2 · cgroups v2 / seccomp · PostgreSQL
376
+ 16 · MinIO/S3. See [`docs/ymir-rut.md`](docs/ymir-rut.md).
377
+
378
+ ---
379
+
380
+ ## Design Language
381
+
382
+ **Carved, not skinned.** Cinzel (rune headings) · JetBrains Mono (code & telemetry) ·
383
+ Inter (body). Canvas: obsidian slate; accents: electric cyan for Bifrost, violet for
384
+ the realms. Emblem: the Algiz rune over a blacksmith's anvil. Tokens are the single
385
+ source of truth in [`midgard/design-system/tokens.css`](midgard/design-system/tokens.css);
386
+ full spec in [`docs/design.md`](docs/design.md).
387
+
388
+ ---
389
+
390
+ ## Folder Structure
391
+
392
+ > **Single tenant.** One operator (the Allfather), many **workspaces**
393
+ > (personal · work) over knowledge **domains** (company · marketing ·
394
+ > development · life · me). Houses (Ymir Labs, Brokk Forge, …) are brands, not
395
+ > isolation. OSS engines under Norse shells: **treehouse** → Yggdrasil
396
+ > (worktrees), **sandcastle** → Utgard (sandboxes), **no-mistakes** →
397
+ > Mjollnir/Glitnir (clean-PR gate).
398
+
399
+ ```
400
+ ymir/
401
+ ├── AGENTS.md # the always-loaded contract (Brokk)
402
+ ├── bin/ # Norse runtime: saga, syn, rodd, gleipnir, nornir, einherjar,
403
+ │ # yggdrasil (treehouse), utgard (sandcastle), mimir-bridge,
404
+ │ # ymir-install, workspace-provision, project-git, mjollnir,
405
+ │ # hermes-ensure (provision the Hermes worker runtime)
406
+ ├── .agents/
407
+ │ ├── agents/ # Brokk + the Eindri profiles (and Galdr)
408
+ │ ├── skills/ # Gungnir skills (galdr, tyr-check, hvild-afk, …)
409
+ │ ├── backend/ # vendored fleet backend
410
+ │ ├── config/ # ro, cron.yaml, eindri-dispatch, eindri-harness
411
+ │ ├── memory/ # Mimirsbrunn well — kaia.engram + episodes.jsonl
412
+ │ ├── sandbox/ # Utgard barrier (Dockerfile.utgard, utgard.config.json)
413
+ │ └── bus/ # Ratatoskr (A2A) protocol
414
+ ├── .pi/extensions/ .pi/mcp.json # Pi adapters (Sýn, Gná, Ró, Skuld) + engram MCP
415
+ ├── .opencode/plugins/ # OpenCode adapters (Sága, Sýn, Rödd)
416
+ ├── apps/hlidskjalf/ # the control plane (React + Vite + Bun gate API)
417
+ ├── midgard/ # shared assets, design tokens, icons
418
+ ├── svartalfaheim/ # company container root (zerwiz) — future multi-user
419
+ ├── workspace/ # THE SINGLE TENANT: work/ · personal/ · companies/ ·
420
+ │ # workspaces.yaml · projects.yaml · memory/ · INSTALL.md
421
+ ├── smidja/ # the smithy engine + smidja.db (runs, stats, trace)
422
+ ├── state/ # runtime state: lock, chat/, bridges, cron
423
+ ├── scripts/start.sh stop.sh # raise/lower the whole system
424
+ ├── assets/ # art, the OS diagram, reference material
425
+ └── docs/ # lore, architecture, masterplan, plans, session-start
426
+ ```
427
+
428
+ ---
429
+
430
+ ## Key combinations
431
+
432
+ Every key Ymir binds. On Omarchy they live in
433
+ `~/.config/hypr/ymir-launchers.lua` (generated by `bin/desktop-place.sh apply`)
434
+ and are required from `hyprland.lua`. See what is live with
435
+ `omarchy menu keybindings --print`.
436
+
437
+ | Key | What it does | Declared by |
438
+ |---|---|---|
439
+ | **SUPER + Y** | raise **Hlidskjalf** — the control plane | `bin/desktop-place.sh` → `~/.config/hypr/ymir-launchers.lua` |
440
+ | **SUPER + M** | raise **Smiðja** — the visualizer | same file |
441
+ | **ctrl + shift + e** | open the **file picker** over the working directory | `.pi/extensions/open-editor.ts` |
442
+
443
+ Each app window opens on **its own numbered desktop** (the placement rules in
444
+ `bin/desktop-place.sh` send it there), so a speed-start both raises the app and
445
+ keeps it off the desktop you are working on. `/edit [path]` is the same editor
446
+ surface as a slash command, with tab-completion over the directory.
447
+
448
+ Each app also offers the same speed-start **in its own UI** (`POST /api/desktop`),
449
+ so the keyboard is a convenience for the operator's hands, not the only way in.
450
+
451
+ > The editor is the Allfather's own surface: it registers no LLM tool, because
452
+ > agents already have `read` and `edit`. Name it when he would reach for it;
453
+ > never try to drive it.
454
+
455
+ ---
456
+
457
+ ## Inviting someone else in
458
+
459
+ Ymir is single-operator by design: one person directs the fleet. Someone else can
460
+ try yours without being handed your account. The installer mints an **invite
461
+ code** and prints it at the end of the run:
55
462
 
56
463
  ```bash
57
- npx @zerwiz/ymir --check # report only no writes, no prompt
58
- npx @zerwiz/ymir --yes # non-interactive
464
+ bin/ymir-invite.sh mint --limit 3 # a code that admits 3 accounts
465
+ bin/ymir-invite.sh list # every code, what is spent, who is in
466
+ bin/ymir-invite.sh revoke CODE # take one back, now
59
467
  ```
60
468
 
61
- The installer is **idempotent**: run it again and it heals forward rather than
62
- duplicating. It asks before it writes and validates at the end.
469
+ They open the gate and choose **“I have an invite code”**, then pick their own
470
+ username and password. Registration stays **closed** unless a live code exists,
471
+ and each code stops admitting accounts once its ceiling is spent — so an instance
472
+ is never accidentally open, and a link that leaks is not a door.
473
+
474
+ Accounts live in `~/.config/ymir/accounts.json` (mode `0600`) as argon2id
475
+ hashes; no plaintext password is ever written, and nothing about them enters the
476
+ repo. Your own credentials stay `HLIDSKJALF_AUTH` in `.env.local`.
477
+
478
+ ---
479
+
480
+ ## Desktop & Mobile
63
481
 
64
- ## It is early
482
+ - **Desktop (Electron).** `scripts/electron.sh start` (or `npm run desktop` in
483
+ `apps/hlidskjalf`) opens Hlidskjalf + Smiðja as a native window — app icon and
484
+ a stable “Ymir · Hlidskjalf” title. It raises the stack if it is down.
65
485
 
66
- Ymir is in **alpha**. The forge is hot and the anvil works, but expect rough
67
- edges and do not run it as a public service yet (auth hardens with Heimdall).
486
+ - **Android APK (Capacitor).** A thin native shell over the Hlidskjalf web app
487
+ one codebase, pointed at your tunnel.
68
488
 
69
- ## This package
489
+ ```sh
490
+ cd apps/hlidskjalf
491
+ npm install
492
+ npm run build
493
+ npx cap sync android
494
+ cd android
495
+ JAVA_HOME=<jdk-17> ANDROID_HOME=<android-sdk> ./gradlew assembleDebug
496
+ # → android/app/build/outputs/apk/debug/app-debug.apk
497
+ ```
70
498
 
71
- This npm package is only the **bootstrap** `install.sh` plus a thin
72
- `ymir` bin. The system itself lives in the distro repo. This package carries no
73
- secrets and no private material.
499
+ Change the server later **without touching code**:
74
500
 
75
- ## Open source, with gratitude
501
+ ```sh
502
+ YMIR_SERVER_URL=https://your.server npx cap sync android
503
+ ```
504
+
505
+ Default target is `https://<your-host>` (`capacitor.config.ts`).
506
+
507
+ - **PWA.** Open the tunnel URL on a phone and “Add to Home Screen” — the manifest
508
+ ships in `apps/hlidskjalf/public/manifest.webmanifest`.
509
+
510
+ ---
76
511
 
77
- Ymir is **Apache-2.0**. It is a Norse shell over other people's excellent work —
78
- we did not build the engines, we built the hall around them, and we name them
79
- proudly: **treehouse · sandcastle · no-mistakes · pi · oh-my-pi · hermes-agent ·
80
- pi-desktop · A2A**, and the kunchenguid family (**firstmate · axi · lavish-axi**).
512
+ ## Naming Law
81
513
 
82
- Their licences are honoured in full in `NOTICE` and `THIRD-PARTY-LICENSES`.
514
+ Every subsystem, component, and process is named for the figure whose role matches
515
+ its work; the operator is the **Allfather** (Odin). The house voice is Norse-natural;
516
+ flavor may season a line, but an imported term never names a subsystem. The full
517
+ component map lives in
518
+ [`.agents/skills/galdr-cli/assets/norse-naming.md`](.agents/skills/galdr-cli/assets/norse-naming.md).
83
519
 
84
520
  ---
85
521
 
86
- <p align="center"><em>Hammered steel, raw iron, and obsidian runes.
87
- Step up to the forge and carve your own worlds from Ymir's frame.</em></p>
522
+ ## Docs
523
+
524
+ - [`docs/lore.md`](docs/lore.md) — the mythos, realm by realm
525
+ - [`docs/session-start.md`](docs/session-start.md) — how the seat is taken
526
+ - [`docs/Architecture.md`](docs/Architecture.md) — the 7 realms, A2A, memory, migration
527
+ - [`docs/masterplan.md`](docs/masterplan.md) — the append-only forge orders
528
+ - [`docs/plans/README.md`](docs/plans/README.md) — the feature plan index
529
+ - [`docs/design.md`](docs/design.md) — the design system
530
+ - [`docs/ymir-rut.md`](docs/ymir-rut.md) — the Rust re-forging spec
531
+ - [`AGENTS.md`](AGENTS.md) — Brokk's always-loaded operating contract
532
+
533
+ ---
534
+
535
+ > *“A webhook hits Bifrost and is queued on Ratatoskr. Ymir allocates resources and
536
+ > launches Brokk. Brokk drinks from Mimirsbrunn, cuts a branch via Yggdrasil inside
537
+ > Svartalfaheim, and hands execution to an Eindri inside Utgard. Tests pass, Mjollnir
538
+ > raises the PR, the outcome is observed back into the well, Runes carves the entry,
539
+ > and Hlidskjalf renders the state.”*
540
+
541
+ *The bellows feed the flame; the smith reads the metal; the well remembers every blow.*
542
+
543
+ ## What was wrought — 2026-09-14
544
+
545
+ One day, one loom. Everything below lives in this main and in the world:
546
+
547
+ - **The cloth** — Hlidskjalf, Smiðja and Sessrúmnir wear one carved look (stone,
548
+ bronze, bone, blood; Cormorant · Newsreader · IBM Plex Mono); Smiðja's default
549
+ theme is **Fensalir**; text highlighting is carved amber — the blue is dead.
550
+ - **Óðrerir, the Live Hall** — the landing's live board: a dealt slate pile, a
551
+ carved ledger (underway · landed · charted), and a planning glass fed by real
552
+ machine state. See it at the landing repo: `zerwiz/ymir-homepage` (local:
553
+ `:4321`), with the `To the Hall` rune in every app's chrome.
554
+ - **The wake bridge** — every smith's finish files a saga and wakes the
555
+ primary; the echo-guard keeps the wire honest.
556
+ - **The mark** — recoloured into the cloth, and the anvil-bars bug found and
557
+ fixed (the metal was always there; now it is seen).
558
+
559
+ The lore runs to **XXXI — The Weaving of the Halls**; the masterplan carries
560
+ the full day's ledger.
561
+
562
+ ---
563
+
564
+ ## With gratitude — the people we stand on
565
+
566
+ Ymir is a Norse shell over other people's excellent work. We did not build the
567
+ engines; we built the hall around them. Every project below is theirs, kept under
568
+ their own licence, and we are glad to name them. Go and look at what they made —
569
+ follow them, star them, learn from them.
570
+
571
+ | Project | Who made it | Licence | What it powers in Ymir |
572
+ |---|---|---|---|
573
+ | [treehouse](https://github.com/kunchenguid/treehouse) | kunchenguid | MIT | Yggdrasil — git worktrees |
574
+ | [sandcastle](https://github.com/mattpocock/sandcastle) | [Matt Pocock](https://www.youtube.com/@mattpocockuk) | MIT | Utgard — sealed sandboxes |
575
+ | [no-mistakes](https://github.com/kunchenguid/no-mistakes) | kunchenguid | MIT | the clean-PR gate |
576
+ | [pi](https://github.com/earendil-works/pi) | Earendil Works | MIT | the coding harness |
577
+ | [oh-my-pi](https://github.com/can1357/oh-my-pi) | can1357 | MIT | prior art for the pi surface |
578
+ | [hermes-agent](https://github.com/NousResearch/hermes-agent) | Nous Research | MIT | the Hermes worker runtime |
579
+ | [pi-desktop](https://github.com/FaqFirebase/pi-desktop) | FaqFirebase and the Pi Desktop contributors | Apache-2.0 | Sessrúmnir (our re-themed fork) |
580
+ | [A2A protocol](https://github.com/a2aproject/a2a) | the A2A project | Apache-2.0 | the agent-to-agent backbone |
581
+ | [firstmate](https://github.com/kunchenguid/firstmate) | kunchenguid | MIT | the fleet |
582
+ | [axi](https://github.com/kunchenguid/axi) | kunchenguid | MIT | agent-ergonomics principles |
583
+ | [lavish-axi](https://github.com/kunchenguid/lavish-axi) | kunchenguid | MIT | the HTML-artifact editor |
584
+
585
+ Their full licence texts are bundled in [THIRD-PARTY-LICENSES](THIRD-PARTY-LICENSES),
586
+ and the audit of every demand is in [docs/third-party-audit.md](docs/third-party-audit.md).
587
+ If we have benefited from your work and missed you here, tell us — we will fix it,
588
+ loudly.
589
+
590
+ Thank you all. The forge is hot because you lit it.
591
+
592
+ _Where a maker teaches on YouTube we link the channel — Matt Pocock's is
593
+ [youtube.com/@mattpocockuk](https://www.youtube.com/@mattpocockuk). If you make a
594
+ tutorial for a project we use, tell us and we will link yours too._
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zerwiz/ymir",
3
- "version": "0.1.1",
3
+ "version": "0.1.3",
4
4
  "description": "Ymir — the official local installer (curl | bash, or npx ymir)",
5
5
  "type": "module",
6
6
  "bin": {