@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 +342 -0
- package/bin/postinstall.js +187 -73
- package/bin/postinstall.js.map +1 -0
- package/extensions/cleo-cant-bridge.d.ts +85 -0
- package/extensions/cleo-cant-bridge.d.ts.map +1 -0
- package/extensions/cleo-cant-bridge.js +451 -0
- package/extensions/cleo-cant-bridge.js.map +1 -0
- package/extensions/cleo-chatroom.d.ts +83 -0
- package/extensions/cleo-chatroom.d.ts.map +1 -0
- package/extensions/cleo-chatroom.js +344 -0
- package/extensions/cleo-chatroom.js.map +1 -0
- package/package.json +6 -13
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
|
package/bin/postinstall.js
CHANGED
|
@@ -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
|
|
7
|
-
* extension
|
|
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
|
-
*
|
|
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
|
|
12
|
-
*
|
|
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,
|
|
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
|
|
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
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
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
|
-
*
|
|
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
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
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
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
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
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
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":"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"}
|