@cleocode/cleo-os 2026.4.16 → 2026.4.18

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,342 @@
1
+ # CleoOS
2
+
3
+ > The batteries-included agentic development environment.
4
+ > One developer. Many agents. One operating system for the work.
5
+
6
+ CleoOS wraps [Pi](https://github.com/mariozechner/pi) — Mario Zechner's
7
+ open-source coding agent — with CLEO's governance layer: task memory,
8
+ lifecycle gates, multi-agent coordination, and the CANT DSL. Install once,
9
+ get both.
10
+
11
+ ## Quick Start
12
+
13
+ ```bash
14
+ npm install -g @cleocode/cleo-os
15
+ cleoos
16
+ ```
17
+
18
+ That's it. CleoOS installs Pi automatically. The `cleoos` command launches
19
+ Pi with CleoOS extensions pre-loaded. The `cleo` CLI is also available for
20
+ task management, memory, and lifecycle operations.
21
+
22
+ ## If You're...
23
+
24
+ | Goal | Start here |
25
+ |---|---|
26
+ | **New to AI coding agents** | [The Hearth](#the-hearth) — what you see when you run `cleoos` |
27
+ | **Already using Pi** | [What CleoOS Adds](#what-cleoos-adds-to-pi) — the extensions Pi doesn't have |
28
+ | **Comparing tools** | [Why CleoOS](#why-cleoos) — how it differs from Claude Code, Cursor, Copilot |
29
+
30
+ ---
31
+
32
+ ## Why CleoOS
33
+
34
+ AI coding agents can write code. What they cannot do is sustain a project across days, agents,
35
+ and context windows. Each session starts fresh, forgets last week's architectural decision,
36
+ and has no idea which tasks are blocked or why. The result: impressive demos, fragile projects.
37
+
38
+ CleoOS adds the missing layer. BRAIN persists memory across every session so agents never
39
+ rediscover the same facts twice. The CANT DSL defines agent roles, permissions, and mental models
40
+ in a checked-in file so governance is reproducible. The three-tier hierarchy gives leads the
41
+ authority to coordinate without giving them the power to cause chaos, and gives workers a
42
+ constrained domain where they can operate confidently.
43
+
44
+ The key differentiator is enforcement. Many tools describe role hierarchies. CleoOS enforces
45
+ them at the `tool_call` hook level inside Pi: lead agents literally cannot execute `Edit`,
46
+ `Write`, or `Bash`, and worker agents cannot write outside their declared file paths. There is
47
+ no workaround because the hook runs before Pi dispatches the tool call.
48
+
49
+ Pi provides excellent single-agent coding capability — a well-designed TUI, solid model
50
+ integration, and a stable extension API. CleoOS is not a competitor. It is the governance
51
+ shell that makes Pi production-ready for multi-agent workflows.
52
+
53
+ ---
54
+
55
+ ## The Five Named Powers
56
+
57
+ CleoOS is built on CLEO's five named powers. Each maps to a concrete runtime system:
58
+
59
+ | Power | What It Does |
60
+ |-------|-------------|
61
+ | **CLEO** | Governs continuity, routing, and system action across all sessions |
62
+ | **BRAIN** | Stores durable project knowledge — observations, decisions, patterns, learnings |
63
+ | **LOOM** | Enforces order of operations through the RCASD-IVTR+C lifecycle |
64
+ | **NEXUS** | Connects projects without merging them — cross-project registry |
65
+ | **LAFS** | Standardizes outputs for tools and agents — progressive disclosure protocol |
66
+
67
+ **CAAMP** is the provisioning ally: it equips the realm with provider configs, skills, and
68
+ injected instructions. See the [CLEO World Map](../../docs/concepts/CLEO-WORLD-MAP.md) for
69
+ the full narrative behind each power.
70
+
71
+ ---
72
+
73
+ ## The Hearth
74
+
75
+ The Hearth is what you see when you run `cleoos`. It is Pi's terminal UI with CleoOS
76
+ extensions loaded automatically:
77
+
78
+ - **CANT bridge** — reads `.cleo/cant/*.cant` files and injects agent personas, tool ACLs,
79
+ and mental model preambles into the Pi session at startup. Compiles CANT DSL to system
80
+ prompt injection transparently.
81
+ - **Chat room widget** — a below-editor panel that shows the last 15 inter-agent messages
82
+ in real time. Messages arrive from other agents in the current worktree via `conduit.db`
83
+ or `api.signaldock.io`. The chat room is a TUI view — it is not itself a messaging transport.
84
+ - **Status line** — shows the current agent tier, role name, and active task context pulled
85
+ from BRAIN on spawn.
86
+
87
+ The Hearth is the operator surface. Conduit is the agent relay below it.
88
+
89
+ ---
90
+
91
+ ## The Three-Tier Hierarchy
92
+
93
+ The three-tier hierarchy is the headline feature of CleoOS. It brings structure to multi-agent
94
+ projects by giving each tier distinct powers and hard constraints enforced at runtime.
95
+
96
+ ```
97
+ Orchestrator (you, or /cleo:auto <epicId>)
98
+
99
+ ├── Engineering Lead (thinker, NEVER executes)
100
+ │ ├── backend-dev (worker, writes code)
101
+ │ ├── frontend-dev (worker, writes code)
102
+ │ └── qa-engineer (worker, writes tests)
103
+
104
+ ├── Validation Lead
105
+ │ ├── security-reviewer (worker, audits)
106
+ │ └── doc-writer (worker, writes docs)
107
+
108
+ └── Release Lead
109
+ └── release-manager (worker, ships)
110
+ ```
111
+
112
+ ### Tier Capabilities
113
+
114
+ | Tier | Role | Power | Hard Constraint |
115
+ |------|------|-------|-----------------|
116
+ | **Orchestrator** | Runs the Conductor Loop (`/cleo:auto <epicId>`) | Full system access | HITL boundary — user approves epic-level decisions |
117
+ | **Lead** | Coordinates a worker group, reviews output, delegates | Read + think + delegate | CANNOT execute `Edit`, `Write`, or `Bash` — no exceptions |
118
+ | **Worker** | Executes concrete code changes within a declared domain | Read + write within domain | Path ACL: `permissions.files: write[glob]` — cannot write outside glob |
119
+
120
+ ### Enforcement (shipped in Wave 7b)
121
+
122
+ Enforcement runs at the Pi `tool_call` hook level. When a lead agent attempts to call
123
+ `Edit`, `Write`, or `Bash`, the hook intercepts the call before Pi dispatches it and
124
+ returns a rejection. When a worker agent attempts to write to a path outside its declared
125
+ glob pattern, the same hook rejects the call. There is no workaround at the agent level.
126
+
127
+ Teams are defined in `.cleo/teams.cant`:
128
+
129
+ ```cant
130
+ team engineering-lead {
131
+ role: lead
132
+ workers: [backend-dev, frontend-dev, qa-engineer]
133
+ }
134
+
135
+ team backend-dev {
136
+ role: worker
137
+ permissions {
138
+ files { write ["packages/core/**", "packages/contracts/**"] }
139
+ }
140
+ }
141
+ ```
142
+
143
+ ### Wave Status
144
+
145
+ | Feature | Status |
146
+ |---|---|
147
+ | Lead tool blocking (`Edit`/`Write`/`Bash` rejected for `role: lead`) | Wave 7b shipped |
148
+ | Worker path ACL (`permissions.files: write[glob]` enforced) | T422-T426 shipped |
149
+ | `.cleo/teams.cant` definition format | Wave 0 shipped |
150
+ | Model tier routing (low/mid/high per tier) | Grammar shipped, router in progress |
151
+ | JIT agent composition (spawn team from task type) | Library exists, not wired to spawn path |
152
+
153
+ ---
154
+
155
+ ## Conduit — Agent Communication
156
+
157
+ Conduit is CLEO's agent-to-agent communication layer, structured in four concentric shells.
158
+ Each shell handles a different scope of agent communication.
159
+
160
+ ### Shell 1 — Pi Native (free, built-in)
161
+
162
+ Orchestrator-to-lead-to-worker communication inside a single session. Pi handles
163
+ parent/child relay automatically via its JSONL subagent-link. No CLEO infrastructure
164
+ needed. Zero latency. Zero cost.
165
+
166
+ ### Shell 2 — conduit.db (shipped v2026.4.12)
167
+
168
+ Per-project local messaging in SQLite at `.cleo/conduit.db`. Provides messages,
169
+ conversations, delivery queue, and dead-letter handling. Used when agents communicate
170
+ across sessions or hand off state between orchestrator runs on the same machine. Also
171
+ holds `project_agent_refs` — per-project agent visibility overrides that layer on top of
172
+ the global identity registry.
173
+
174
+ ### Shell 3 — signaldock.io Cloud (shipped)
175
+
176
+ Cross-machine and cross-project agent coordination via the `signaldock-sdk` Rust crate
177
+ against `api.signaldock.io`. Four services: AgentService, MessageService,
178
+ ConversationService, DeliveryOrchestrator. TypeScript reaches the cloud tier via
179
+ `HttpTransport` (polling) or `SseTransport` (real-time EventSource). Used when a fleet
180
+ of agents spans multiple machines or CI environments.
181
+
182
+ ### Shell 4 — Durable Broker (planned)
183
+
184
+ The CLEOOS-VISION message bus with Rust broker, TypeScript semantics, lease-based delivery,
185
+ and dead-letter queue. Deferred until cross-worktree durability is required by real workflows.
186
+
187
+ > **Note**: The Chat Room (`cleo-chatroom.ts`) is a TUI view under The Hearth, not a
188
+ > Conduit shell. It gives the operator visibility into inter-agent messages. Messages
189
+ > displayed in the chat room flow through `conduit.db` or `signaldock.io` — the chat room
190
+ > itself is only a renderer.
191
+
192
+ ---
193
+
194
+ ## What CleoOS Adds to Pi
195
+
196
+ | Capability | How | Source |
197
+ |---|---|---|
198
+ | **CANT bridge** | Injects agent personas from `.cleo/cant/*.cant` into Pi sessions at startup. Compiles CANT to system prompt injection. | `extensions/cleo-cant-bridge.ts` |
199
+ | **Lead tool blocking** | `tool_call` hook rejects `Edit`/`Write`/`Bash` for `role: lead` agents | Wave 7b |
200
+ | **Worker path ACL** | `tool_call` hook enforces `permissions.files: write[glob]` per worker | T422-T426 |
201
+ | **Mental model injection** | Fetches prior observations from BRAIN on spawn, injects validate-on-load preamble | Wave 8 |
202
+ | **Chat room TUI** | 4 inter-agent tools + below-editor widget showing last 15 messages | Wave 7 |
203
+ | **XDG-compliant paths** | All CleoOS state under `~/.local/share/cleo/` (Linux), `~/Library/Application Support/cleo/` (macOS) | `src/xdg.ts` |
204
+ | **Pi keystore redirect** | Pi credentials stored at `~/.config/cleo/auth/auth.json` instead of Pi's default | `src/keystore.ts` |
205
+ | **Postinstall scaffolding** | Creates XDG dirs, deploys extensions, scaffolds `model-routing.cant` stub, installs CLEO skills | `src/postinstall.ts` |
206
+
207
+ ---
208
+
209
+ ## Database Topology
210
+
211
+ CleoOS maintains five databases across two tiers per ADR-036 and ADR-037.
212
+
213
+ ### Project Tier (`.cleo/`)
214
+
215
+ | Database | Purpose |
216
+ |---|---|
217
+ | `tasks.db` | Task hierarchy, sessions, audit log, lifecycle pipelines |
218
+ | `brain.db` | Observations, patterns, learnings, decisions (FTS5 searchable) |
219
+ | `conduit.db` | Agent messaging, delivery queue, `project_agent_refs` |
220
+
221
+ ### Global Tier (`$XDG_DATA_HOME/cleo/`)
222
+
223
+ | Database | Purpose |
224
+ |---|---|
225
+ | `nexus.db` | Cross-project registry, federated queries |
226
+ | `signaldock.db` | Canonical agent identity, cloud-sync tables |
227
+
228
+ Plus: `global-salt` (32-byte machine-bound key for API key derivation), `machine-key`,
229
+ `extensions/`, and `cant/` directories for globally installed CANT files.
230
+
231
+ ---
232
+
233
+ ## Installation
234
+
235
+ ```bash
236
+ # One command installs both CleoOS and Pi
237
+ npm install -g @cleocode/cleo-os
238
+
239
+ # Verify
240
+ cleoos --version
241
+ cleo version
242
+ ```
243
+
244
+ ### What Gets Installed
245
+
246
+ - `cleoos` binary — launches Pi with CleoOS extensions pre-loaded
247
+ - `cleo` binary — CLEO CLI (90+ commands across 10 canonical domains)
248
+ - `@mariozechner/pi-coding-agent` — Mario Zechner's open-source AI coding agent
249
+ - XDG directory structure at `~/.local/share/cleo/`
250
+ - Default CANT stubs and skill files
251
+
252
+ ### Requirements
253
+
254
+ - Node.js >= 24.0.0
255
+ - An AI provider API key (set via `cleoos` on first run, stored in `~/.config/cleo/auth/auth.json`)
256
+
257
+ ---
258
+
259
+ ## Architecture
260
+
261
+ ```
262
+ +-----------------------------------------------------------+
263
+ | @cleocode/cleo-os |
264
+ | (CleoOS — batteries-included Pi wrapper) |
265
+ | |
266
+ | +------------------------+ +------------------------+ |
267
+ | | extensions/ | | extensions/ | |
268
+ | | cleo-cant-bridge.ts | | cleo-chatroom.ts | |
269
+ | | (CANT compile, | | (4 tools, TUI widget, | |
270
+ | | ACL enforcement, | | JSONL relay, | |
271
+ | | mental model inject) | | not a Conduit shell) | |
272
+ | +------------------------+ +------------------------+ |
273
+ | src/cli.ts <- cleoos launcher |
274
+ | src/postinstall.ts <- XDG scaffolding |
275
+ +-----------------------------------------------------------+
276
+ |
277
+ v (direct dependency)
278
+ +-----------------------------------------------------------+
279
+ | @mariozechner/pi-coding-agent |
280
+ | TUI, model providers, session management, |
281
+ | extension API, tool execution, subagent spawn |
282
+ +-----------------------------------------------------------+
283
+ |
284
+ v
285
+ +-----------------------------------------------------------+
286
+ | @cleocode/cleo |
287
+ | CLI (90+ commands), dispatch registry, |
288
+ | LAFS envelopes, 10 canonical domains |
289
+ +-----------------------------------------------------------+
290
+ |
291
+ v
292
+ +-----------------------------------------------------------+
293
+ | @cleocode/core |
294
+ | Tasks, sessions, memory, orchestration, |
295
+ | lifecycle, validation, backup, conduit |
296
+ +-----------------------------------------------------------+
297
+ |
298
+ v
299
+ +-----------------------------------------------------------+
300
+ | SQLite (node:sqlite via Drizzle ORM) |
301
+ | tasks.db brain.db conduit.db nexus.db |
302
+ | signaldock.db |
303
+ +-----------------------------------------------------------+
304
+ ```
305
+
306
+ ---
307
+
308
+ ## Wave Roadmap
309
+
310
+ CleoOS ships in named waves. Each wave targets a vertical slice of the platform.
311
+
312
+ | Wave | Title | Status | Key Deliverable |
313
+ |------|-------|--------|-----------------|
314
+ | 0 | CANT Grammar | Shipped | `team`, `tool`, `mental_model` document kinds |
315
+ | 2 | CANT Bridge MVP | Shipped | `cleo-cant-bridge.ts` — compile + inject at session_start |
316
+ | 3 | Launcher + Install | Shipped | `cleoos` binary, postinstall, XDG hub |
317
+ | 7 | Chat Room + Hierarchy | Shipped | 4 inter-agent tools, TUI widget, 3-tier enforcement |
318
+ | 7b | Lead Tool Blocking | Shipped | `Edit`/`Write`/`Bash` blocked for `role: lead` |
319
+ | 8 | Mental Model Injection | Shipped | validate-on-load from BRAIN on agent spawn |
320
+ | ACL | Worker Path ACL | Shipped | `permissions.files: write[glob]` enforcement |
321
+ | 1 | Render Pipeline | Partial | Rust stubs exist, no `cant render` CLI verb yet |
322
+ | 4 | Lifecycle Codegen | Partial | `.cant` files exist, `stages.ts` connection missing |
323
+ | 5 | JIT Agent Composer | Partial | Library shipped, not wired to spawn path |
324
+ | 6 | Model Router | In progress | Rust classifier crate exists |
325
+ | 9 | Three-Tier CANT Resolution | Not started | Global/user/project `.cant` file hierarchy |
326
+
327
+ ---
328
+
329
+ ## References
330
+
331
+ - [CLEO World Map](../../docs/concepts/CLEO-WORLD-MAP.md) — the founding myth and system vocabulary
332
+ - [CleoOS Vision](../../docs/concepts/CLEOOS-VISION.md) — the long-term vision document
333
+ - [ADR-035](../../.cleo/adrs/ADR-035-pi-v2-v3-harness.md) — Pi as primary harness
334
+ - [ADR-036](../../.cleo/adrs/ADR-036-cleoos-database-topology.md) — database topology
335
+ - [ADR-037](../../.cleo/adrs/ADR-037-conduit-signaldock-separation.md) — conduit/signaldock split
336
+ - [Pi Coding Agent](https://github.com/mariozechner/pi) — the upstream agent CleoOS wraps
337
+
338
+ ---
339
+
340
+ ## License
341
+
342
+ MIT
@@ -1,94 +1,208 @@
1
- #!/usr/bin/env node
2
1
  /**
3
- * CleoOS postinstall — scaffolds global XDG hub and deploys extensions.
2
+ * CleoOS postinstall — scaffolds the global XDG hub and deploys extensions.
4
3
  *
5
4
  * Runs automatically after `npm install -g @cleocode/cleo-os`.
6
- * Creates XDG-compliant directory structure and copies the CANT bridge
7
- * extension template into the extensions directory.
5
+ * Creates an XDG-compliant directory structure, copies the compiled CANT
6
+ * bridge extension to the extensions directory, and optionally invokes
7
+ * `cleo skills install` for any bundled CleoOS skills.
8
8
  *
9
- * Skips during workspace/dev installs (non-global).
9
+ * Behaviour:
10
+ * - Skips silently during workspace/dev installs (non-global).
11
+ * - All directory creation is idempotent (no-op if directory exists).
12
+ * - All file copies are idempotent (only copies if target is missing).
13
+ * - Skill install is best-effort; failures are logged but not fatal.
14
+ * - Missing `@mariozechner/pi-coding-agent` is handled gracefully.
10
15
  *
11
- * This file is plain JS (not compiled from src/) so it can run before
12
- * the package is built, matching the @cleocode/cleo postinstall pattern.
16
+ * This source compiles to `bin/postinstall.js` via a dedicated tsconfig
17
+ * (see `tsconfig.postinstall.json`). The `postinstall` script in
18
+ * `package.json` references the compiled output at `bin/postinstall.js`.
19
+ *
20
+ * @packageDocumentation
13
21
  */
14
-
15
- import { existsSync, mkdirSync, cpSync } from 'node:fs';
22
+ import { execFileSync } from 'node:child_process';
23
+ import { cpSync, existsSync, mkdirSync, writeFileSync } from 'node:fs';
24
+ import { homedir } from 'node:os';
16
25
  import { dirname, join, resolve } from 'node:path';
17
26
  import { fileURLToPath } from 'node:url';
18
- import { homedir } from 'node:os';
19
-
20
27
  const __filename = fileURLToPath(import.meta.url);
21
28
  const __dirname = dirname(__filename);
22
-
29
+ // ---------------------------------------------------------------------------
30
+ // XDG path resolution (inline copy — avoids importing from dist/ which may
31
+ // not exist when this script runs for the first time)
32
+ // ---------------------------------------------------------------------------
33
+ /**
34
+ * Inline XDG path resolution that mirrors `src/xdg.ts`.
35
+ *
36
+ * Uses an inline copy here so the postinstall script can run before
37
+ * the compiled `dist/` tree is available on a fresh install.
38
+ *
39
+ * @returns Resolved CleoOS XDG directory paths.
40
+ */
41
+ function resolveCleoOsPaths() {
42
+ const home = homedir();
43
+ const xdgData = process.env['XDG_DATA_HOME'] ?? join(home, '.local', 'share');
44
+ const xdgConfig = process.env['XDG_CONFIG_HOME'] ?? join(home, '.config');
45
+ const data = join(xdgData, 'cleo');
46
+ const config = join(xdgConfig, 'cleo');
47
+ return {
48
+ data,
49
+ config,
50
+ agentDir: data,
51
+ extensions: join(data, 'extensions'),
52
+ cant: join(data, 'cant'),
53
+ auth: join(config, 'auth'),
54
+ };
55
+ }
56
+ // ---------------------------------------------------------------------------
57
+ // Global install detection
58
+ // ---------------------------------------------------------------------------
23
59
  /**
24
- * Detect if this is a global npm install (not a workspace/dev install).
60
+ * Detect whether this is a global npm / pnpm install.
61
+ *
62
+ * Uses four heuristics in priority order:
63
+ * 1. `npm_config_global=true` env var (set by npm/pnpm for global installs)
64
+ * 2. Package path contains `lib/node_modules/` (npm global pattern)
65
+ * 3. Package path starts with `npm_config_prefix` (npm prefix-based check)
66
+ * 4. Presence of `pnpm-workspace.yaml` two levels up (workspace = dev)
67
+ *
68
+ * @returns `true` if the install appears to be a global install.
25
69
  */
26
70
  function isGlobalInstall() {
27
- const pkgRoot = resolve(__dirname, '..');
28
-
29
- // Signal 1: npm_config_global env var (set by npm during global installs)
30
- if (process.env.npm_config_global === 'true') return true;
31
-
32
- // Signal 2: path contains a global node_modules (npm, pnpm, yarn)
33
- if (/[/\\]lib[/\\]node_modules[/\\]/.test(pkgRoot)) return true;
34
-
35
- // Signal 3: npm_config_prefix matches the package path
36
- const prefix = process.env.npm_config_prefix;
37
- if (prefix && pkgRoot.startsWith(prefix)) return true;
38
-
39
- // Signal 4: inside a pnpm workspace — definitely not global
40
- const workspaceMarker = join(pkgRoot, '..', '..', 'pnpm-workspace.yaml');
41
- if (existsSync(workspaceMarker)) return false;
42
-
43
- return false;
71
+ const pkgRoot = resolve(__dirname, '..');
72
+ // Signal 1: npm_config_global env var (set by npm during global installs)
73
+ if (process.env['npm_config_global'] === 'true')
74
+ return true;
75
+ // Signal 2: path contains a global node_modules (npm, pnpm, yarn)
76
+ if (/[/\\]lib[/\\]node_modules[/\\]/.test(pkgRoot))
77
+ return true;
78
+ // Signal 3: npm_config_prefix matches the package path
79
+ const prefix = process.env['npm_config_prefix'];
80
+ if (prefix !== undefined && pkgRoot.startsWith(prefix))
81
+ return true;
82
+ // Signal 4: inside a pnpm workspace — definitely not global
83
+ const workspaceMarker = join(pkgRoot, '..', '..', 'pnpm-workspace.yaml');
84
+ if (existsSync(workspaceMarker))
85
+ return false;
86
+ return false;
44
87
  }
45
-
88
+ // ---------------------------------------------------------------------------
89
+ // Directory scaffolding
90
+ // ---------------------------------------------------------------------------
46
91
  /**
47
- * Inline XDG path resolution (avoids importing from dist/ which may not exist).
92
+ * Idempotently create a directory if it does not already exist.
93
+ *
94
+ * @param dir - Absolute path to the directory to create.
48
95
  */
49
- function resolveCleoOsPaths() {
50
- const home = homedir();
51
- const xdgData = process.env.XDG_DATA_HOME ?? join(home, '.local', 'share');
52
- const xdgConfig = process.env.XDG_CONFIG_HOME ?? join(home, '.config');
53
-
54
- const data = join(xdgData, 'cleo');
55
- const config = join(xdgConfig, 'cleo');
56
-
57
- return {
58
- data,
59
- config,
60
- agentDir: data,
61
- extensions: join(data, 'extensions'),
62
- cant: join(data, 'cant'),
63
- auth: join(config, 'auth'),
64
- };
96
+ function ensureDir(dir) {
97
+ if (!existsSync(dir)) {
98
+ mkdirSync(dir, { recursive: true });
99
+ process.stdout.write(`CleoOS: created ${dir}\n`);
100
+ }
65
101
  }
66
-
102
+ // ---------------------------------------------------------------------------
103
+ // Extension deployment
104
+ // ---------------------------------------------------------------------------
105
+ /**
106
+ * Copy a compiled extension to the XDG extensions directory.
107
+ *
108
+ * Only copies if the target does not already exist (idempotent). The
109
+ * source is the compiled `.js` file in the package's `extensions/` folder.
110
+ *
111
+ * @param extensionName - Filename without the `.js` extension.
112
+ * @param pkgRoot - Absolute path to the installed package root.
113
+ * @param extensionsDir - Absolute path to the XDG extensions directory.
114
+ */
115
+ function deployExtension(extensionName, pkgRoot, extensionsDir) {
116
+ const src = join(pkgRoot, 'extensions', `${extensionName}.js`);
117
+ const dest = join(extensionsDir, `${extensionName}.js`);
118
+ if (!existsSync(src)) {
119
+ process.stdout.write(`CleoOS: skipping ${extensionName}.js (source not found at ${src})\n`);
120
+ return;
121
+ }
122
+ if (existsSync(dest)) {
123
+ // Already deployed — idempotent, skip.
124
+ return;
125
+ }
126
+ cpSync(src, dest, { force: false });
127
+ process.stdout.write(`CleoOS: deployed ${extensionName}.js to ${dest}\n`);
128
+ }
129
+ // ---------------------------------------------------------------------------
130
+ // Default CANT file scaffolding
131
+ // ---------------------------------------------------------------------------
132
+ /**
133
+ * Write a default `model-routing.cant` stub to the XDG CANT directory if
134
+ * no `.cant` files are present. This gives the user a starting point for
135
+ * CANT declarations without overwriting any existing work.
136
+ *
137
+ * @param cantDir - Absolute path to the XDG CANT directory.
138
+ */
139
+ function scaffoldDefaultCant(cantDir) {
140
+ const modelRoutingPath = join(cantDir, 'model-routing.cant');
141
+ if (existsSync(modelRoutingPath))
142
+ return;
143
+ const stub = [
144
+ '# CleoOS default model-routing.cant',
145
+ '# Declare agents, teams, and routing rules here.',
146
+ '# See: https://github.com/kryptobaseddev/cleo/blob/main/docs/cant-dsl.md',
147
+ '',
148
+ ].join('\n');
149
+ try {
150
+ writeFileSync(modelRoutingPath, stub, 'utf-8');
151
+ process.stdout.write(`CleoOS: created default ${modelRoutingPath}\n`);
152
+ }
153
+ catch {
154
+ // Best-effort: non-fatal.
155
+ }
156
+ }
157
+ // ---------------------------------------------------------------------------
158
+ // Skill installation
159
+ // ---------------------------------------------------------------------------
160
+ /**
161
+ * Invoke `cleo skills install` via `execFileSync` to register the CleoOS
162
+ * bundled skills with the project. This is best-effort — if `cleo` is not
163
+ * on PATH or the command fails, we log and continue.
164
+ *
165
+ * Uses `execFileSync` (not `exec`) to prevent shell injection: the command
166
+ * and arguments are passed as separate parameters so no shell is spawned.
167
+ */
168
+ function installSkills() {
169
+ try {
170
+ execFileSync('cleo', ['skills', 'install'], { stdio: 'inherit' });
171
+ process.stdout.write('CleoOS: skills install complete\n');
172
+ }
173
+ catch {
174
+ // cleo may not be installed or skills may already be up to date.
175
+ process.stdout.write('CleoOS: skipping skills install (cleo not found or already installed)\n');
176
+ }
177
+ }
178
+ // ---------------------------------------------------------------------------
179
+ // Main
180
+ // ---------------------------------------------------------------------------
181
+ /**
182
+ * Entry point for the CleoOS postinstall script.
183
+ *
184
+ * Orchestrates directory scaffolding, extension deployment, CANT stub
185
+ * creation, and optional skill installation. All operations are idempotent.
186
+ */
67
187
  function main() {
68
- if (!isGlobalInstall()) {
69
- console.log('CleoOS: skipping postinstall (not global install)');
70
- return;
71
- }
72
-
73
- const paths = resolveCleoOsPaths();
74
-
75
- // Scaffold directories
76
- for (const dir of [paths.data, paths.config, paths.extensions, paths.cant, paths.auth]) {
77
- if (!existsSync(dir)) {
78
- mkdirSync(dir, { recursive: true });
79
- console.log(`CleoOS: created ${dir}`);
188
+ if (!isGlobalInstall()) {
189
+ process.stdout.write('CleoOS: skipping postinstall (not global install)\n');
190
+ return;
191
+ }
192
+ const paths = resolveCleoOsPaths();
193
+ const pkgRoot = resolve(__dirname, '..');
194
+ // 1. Scaffold XDG directories
195
+ for (const dir of [paths.data, paths.config, paths.extensions, paths.cant, paths.auth]) {
196
+ ensureDir(dir);
80
197
  }
81
- }
82
-
83
- // Deploy bridge extension from package template
84
- const bridgeTemplate = join(__dirname, '..', 'extensions', 'cleo-cant-bridge.js');
85
- const bridgeTarget = join(paths.extensions, 'cleo-cant-bridge.js');
86
- if (existsSync(bridgeTemplate)) {
87
- cpSync(bridgeTemplate, bridgeTarget, { force: true });
88
- console.log(`CleoOS: deployed bridge extension to ${bridgeTarget}`);
89
- }
90
-
91
- console.log('CleoOS: postinstall complete');
198
+ // 2. Deploy compiled extensions
199
+ deployExtension('cleo-cant-bridge', pkgRoot, paths.extensions);
200
+ deployExtension('cleo-chatroom', pkgRoot, paths.extensions);
201
+ // 3. Write default CANT stub (only if file does not exist)
202
+ scaffoldDefaultCant(paths.cant);
203
+ // 4. Install CleoOS skills (best-effort)
204
+ installSkills();
205
+ process.stdout.write('CleoOS: postinstall complete\n');
92
206
  }
93
-
94
207
  main();
208
+ //# sourceMappingURL=postinstall.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"postinstall.js","sourceRoot":"","sources":["../src/postinstall.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AACvE,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACnD,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAEzC,MAAM,UAAU,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAClD,MAAM,SAAS,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;AAEtC,8EAA8E;AAC9E,2EAA2E;AAC3E,sDAAsD;AACtD,8EAA8E;AAE9E;;;;;;;GAOG;AACH,SAAS,kBAAkB;IAQzB,MAAM,IAAI,GAAG,OAAO,EAAE,CAAC;IACvB,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,eAAe,CAAC,IAAI,IAAI,CAAC,IAAI,EAAE,QAAQ,EAAE,OAAO,CAAC,CAAC;IAC9E,MAAM,SAAS,GAAG,OAAO,CAAC,GAAG,CAAC,iBAAiB,CAAC,IAAI,IAAI,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC;IAE1E,MAAM,IAAI,GAAG,IAAI,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;IACnC,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC;IAEvC,OAAO;QACL,IAAI;QACJ,MAAM;QACN,QAAQ,EAAE,IAAI;QACd,UAAU,EAAE,IAAI,CAAC,IAAI,EAAE,YAAY,CAAC;QACpC,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,MAAM,CAAC;QACxB,IAAI,EAAE,IAAI,CAAC,MAAM,EAAE,MAAM,CAAC;KAC3B,CAAC;AACJ,CAAC;AAED,8EAA8E;AAC9E,2BAA2B;AAC3B,8EAA8E;AAE9E;;;;;;;;;;GAUG;AACH,SAAS,eAAe;IACtB,MAAM,OAAO,GAAG,OAAO,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;IAEzC,0EAA0E;IAC1E,IAAI,OAAO,CAAC,GAAG,CAAC,mBAAmB,CAAC,KAAK,MAAM;QAAE,OAAO,IAAI,CAAC;IAE7D,kEAAkE;IAClE,IAAI,gCAAgC,CAAC,IAAI,CAAC,OAAO,CAAC;QAAE,OAAO,IAAI,CAAC;IAEhE,uDAAuD;IACvD,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,mBAAmB,CAAC,CAAC;IAChD,IAAI,MAAM,KAAK,SAAS,IAAI,OAAO,CAAC,UAAU,CAAC,MAAM,CAAC;QAAE,OAAO,IAAI,CAAC;IAEpE,4DAA4D;IAC5D,MAAM,eAAe,GAAG,IAAI,CAAC,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,qBAAqB,CAAC,CAAC;IACzE,IAAI,UAAU,CAAC,eAAe,CAAC;QAAE,OAAO,KAAK,CAAC;IAE9C,OAAO,KAAK,CAAC;AACf,CAAC;AAED,8EAA8E;AAC9E,wBAAwB;AACxB,8EAA8E;AAE9E;;;;GAIG;AACH,SAAS,SAAS,CAAC,GAAW;IAC5B,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;QACrB,SAAS,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACpC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,mBAAmB,GAAG,IAAI,CAAC,CAAC;IACnD,CAAC;AACH,CAAC;AAED,8EAA8E;AAC9E,uBAAuB;AACvB,8EAA8E;AAE9E;;;;;;;;;GASG;AACH,SAAS,eAAe,CAAC,aAAqB,EAAE,OAAe,EAAE,aAAqB;IACpF,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,EAAE,YAAY,EAAE,GAAG,aAAa,KAAK,CAAC,CAAC;IAC/D,MAAM,IAAI,GAAG,IAAI,CAAC,aAAa,EAAE,GAAG,aAAa,KAAK,CAAC,CAAC;IAExD,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;QACrB,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,oBAAoB,aAAa,4BAA4B,GAAG,KAAK,CAAC,CAAC;QAC5F,OAAO;IACT,CAAC;IAED,IAAI,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;QACrB,uCAAuC;QACvC,OAAO;IACT,CAAC;IAED,MAAM,CAAC,GAAG,EAAE,IAAI,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,CAAC;IACpC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,oBAAoB,aAAa,UAAU,IAAI,IAAI,CAAC,CAAC;AAC5E,CAAC;AAED,8EAA8E;AAC9E,gCAAgC;AAChC,8EAA8E;AAE9E;;;;;;GAMG;AACH,SAAS,mBAAmB,CAAC,OAAe;IAC1C,MAAM,gBAAgB,GAAG,IAAI,CAAC,OAAO,EAAE,oBAAoB,CAAC,CAAC;IAC7D,IAAI,UAAU,CAAC,gBAAgB,CAAC;QAAE,OAAO;IAEzC,MAAM,IAAI,GAAG;QACX,qCAAqC;QACrC,kDAAkD;QAClD,0EAA0E;QAC1E,EAAE;KACH,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAEb,IAAI,CAAC;QACH,aAAa,CAAC,gBAAgB,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC;QAC/C,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,2BAA2B,gBAAgB,IAAI,CAAC,CAAC;IACxE,CAAC;IAAC,MAAM,CAAC;QACP,0BAA0B;IAC5B,CAAC;AACH,CAAC;AAED,8EAA8E;AAC9E,qBAAqB;AACrB,8EAA8E;AAE9E;;;;;;;GAOG;AACH,SAAS,aAAa;IACpB,IAAI,CAAC;QACH,YAAY,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,SAAS,CAAC,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC,CAAC;QAClE,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,mCAAmC,CAAC,CAAC;IAC5D,CAAC;IAAC,MAAM,CAAC;QACP,iEAAiE;QACjE,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,yEAAyE,CAAC,CAAC;IAClG,CAAC;AACH,CAAC;AAED,8EAA8E;AAC9E,OAAO;AACP,8EAA8E;AAE9E;;;;;GAKG;AACH,SAAS,IAAI;IACX,IAAI,CAAC,eAAe,EAAE,EAAE,CAAC;QACvB,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,qDAAqD,CAAC,CAAC;QAC5E,OAAO;IACT,CAAC;IAED,MAAM,KAAK,GAAG,kBAAkB,EAAE,CAAC;IACnC,MAAM,OAAO,GAAG,OAAO,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;IAEzC,8BAA8B;IAC9B,KAAK,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,KAAK,CAAC,MAAM,EAAE,KAAK,CAAC,UAAU,EAAE,KAAK,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;QACvF,SAAS,CAAC,GAAG,CAAC,CAAC;IACjB,CAAC;IAED,gCAAgC;IAChC,eAAe,CAAC,kBAAkB,EAAE,OAAO,EAAE,KAAK,CAAC,UAAU,CAAC,CAAC;IAC/D,eAAe,CAAC,eAAe,EAAE,OAAO,EAAE,KAAK,CAAC,UAAU,CAAC,CAAC;IAE5D,2DAA2D;IAC3D,mBAAmB,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAEhC,yCAAyC;IACzC,aAAa,EAAE,CAAC;IAEhB,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,gCAAgC,CAAC,CAAC;AACzD,CAAC;AAED,IAAI,EAAE,CAAC"}