@cleocode/cleo-os 2026.4.13 → 2026.4.17

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.
@@ -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":"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"}
package/dist/cli.d.ts ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * CleoOS launcher — the batteries-included agentic development environment.
4
+ *
5
+ * Wraps Pi's `main()` entry point with the cleo-cant-bridge pre-loaded
6
+ * as an extension. Pi stays upstream (ULTRAPLAN L1). This is a thin
7
+ * launcher that injects CleoOS extensions into Pi's CLI argument list.
8
+ *
9
+ * Usage: `cleoos [pi-args...]` — launches Pi with CANT bridge extension.
10
+ *
11
+ * @packageDocumentation
12
+ */
13
+ export {};
14
+ //# sourceMappingURL=cli.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AACA;;;;;;;;;;GAUG"}
package/dist/cli.js ADDED
@@ -0,0 +1,77 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * CleoOS launcher — the batteries-included agentic development environment.
4
+ *
5
+ * Wraps Pi's `main()` entry point with the cleo-cant-bridge pre-loaded
6
+ * as an extension. Pi stays upstream (ULTRAPLAN L1). This is a thin
7
+ * launcher that injects CleoOS extensions into Pi's CLI argument list.
8
+ *
9
+ * Usage: `cleoos [pi-args...]` — launches Pi with CANT bridge extension.
10
+ *
11
+ * @packageDocumentation
12
+ */
13
+ import { existsSync } from 'node:fs';
14
+ import { join } from 'node:path';
15
+ import { resolveCleoOsPaths } from './xdg.js';
16
+ /**
17
+ * Collect CleoOS extension paths that exist on disk.
18
+ *
19
+ * Resolves the CANT bridge extension from the XDG data directory.
20
+ * Only returns paths for extensions that actually exist on the filesystem.
21
+ *
22
+ * @returns Array of absolute extension file paths.
23
+ */
24
+ function collectExtensionPaths() {
25
+ const paths = resolveCleoOsPaths();
26
+ const extensions = [];
27
+ const bridgePath = join(paths.extensions, 'cleo-cant-bridge.js');
28
+ if (existsSync(bridgePath)) {
29
+ extensions.push(bridgePath);
30
+ }
31
+ return extensions;
32
+ }
33
+ /**
34
+ * Build the argument list for Pi's `main()`, injecting CleoOS extensions.
35
+ *
36
+ * Takes the user's CLI arguments (everything after `cleoos`) and prepends
37
+ * `--extension <path>` flags for each discovered CleoOS extension.
38
+ *
39
+ * @param userArgs - Arguments passed to `cleoos` by the user.
40
+ * @param extensionPaths - Resolved extension paths to inject.
41
+ * @returns Combined argument array for Pi's `main()`.
42
+ */
43
+ function buildArgs(userArgs, extensionPaths) {
44
+ const extensionFlags = extensionPaths.flatMap((p) => ['--extension', p]);
45
+ return [...extensionFlags, ...userArgs];
46
+ }
47
+ /**
48
+ * Entry point for the `cleoos` binary.
49
+ *
50
+ * Dynamically imports Pi's coding agent (peerDependency), resolves CleoOS
51
+ * extension paths, and delegates to Pi's `main()` with the bridge extension
52
+ * injected into the argument list.
53
+ *
54
+ * Exits with code 1 if Pi is not installed, providing install instructions.
55
+ */
56
+ async function main() {
57
+ // Dynamically import Pi — it's a peerDependency, may not be installed
58
+ let piMain;
59
+ try {
60
+ const pi = await import('@mariozechner/pi-coding-agent');
61
+ piMain = pi.main;
62
+ }
63
+ catch {
64
+ console.error('CleoOS requires Pi Coding Agent to be installed.\n' +
65
+ 'Run: npm install -g @mariozechner/pi-coding-agent\n' +
66
+ 'Then try again: cleoos');
67
+ process.exit(1);
68
+ }
69
+ const extensionPaths = collectExtensionPaths();
70
+ const args = buildArgs(process.argv.slice(2), extensionPaths);
71
+ await piMain(args);
72
+ }
73
+ main().catch((err) => {
74
+ console.error('CleoOS fatal:', err instanceof Error ? err.message : String(err));
75
+ process.exit(1);
76
+ });
77
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AACA;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,kBAAkB,EAAE,MAAM,UAAU,CAAC;AAE9C;;;;;;;GAOG;AACH,SAAS,qBAAqB;IAC5B,MAAM,KAAK,GAAG,kBAAkB,EAAE,CAAC;IACnC,MAAM,UAAU,GAAa,EAAE,CAAC;IAEhC,MAAM,UAAU,GAAG,IAAI,CAAC,KAAK,CAAC,UAAU,EAAE,qBAAqB,CAAC,CAAC;IACjE,IAAI,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;QAC3B,UAAU,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;IAC9B,CAAC;IAED,OAAO,UAAU,CAAC;AACpB,CAAC;AAED;;;;;;;;;GASG;AACH,SAAS,SAAS,CAAC,QAAkB,EAAE,cAAwB;IAC7D,MAAM,cAAc,GAAG,cAAc,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,aAAa,EAAE,CAAC,CAAC,CAAC,CAAC;IACzE,OAAO,CAAC,GAAG,cAAc,EAAE,GAAG,QAAQ,CAAC,CAAC;AAC1C,CAAC;AAED;;;;;;;;GAQG;AACH,KAAK,UAAU,IAAI;IACjB,sEAAsE;IACtE,IAAI,MAAyC,CAAC;IAC9C,IAAI,CAAC;QACH,MAAM,EAAE,GAAG,MAAM,MAAM,CAAC,+BAA+B,CAAC,CAAC;QACzD,MAAM,GAAG,EAAE,CAAC,IAAI,CAAC;IACnB,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,CAAC,KAAK,CACX,oDAAoD;YAClD,qDAAqD;YACrD,wBAAwB,CAC3B,CAAC;QACF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,MAAM,cAAc,GAAG,qBAAqB,EAAE,CAAC;IAC/C,MAAM,IAAI,GAAG,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,cAAc,CAAC,CAAC;IAE9D,MAAM,MAAM,CAAC,IAAI,CAAC,CAAC;AACrB,CAAC;AAED,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,GAAY,EAAE,EAAE;IAC5B,OAAO,CAAC,KAAK,CAAC,eAAe,EAAE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;IACjF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
@@ -0,0 +1,27 @@
1
+ /**
2
+ * CleoOS keystore — Pi API key management with XDG-compliant storage.
3
+ *
4
+ * Wraps Pi's `FileAuthStorageBackend` with a CleoOS-specific XDG path so
5
+ * that credentials are persisted at `~/.config/cleo/auth/auth.json` (the
6
+ * `auth` sub-path of the CleoOS XDG config directory) rather than Pi's
7
+ * default location.
8
+ *
9
+ * This ensures:
10
+ * - Credentials survive `cleoos` reinstalls (XDG is outside the package).
11
+ * - Multiple CleoOS installations on the same host share credentials.
12
+ * - The auth file lives under the XDG Config spec (`~/.config/cleo/`).
13
+ *
14
+ * @packageDocumentation
15
+ */
16
+ import { FileAuthStorageBackend } from '@mariozechner/pi-coding-agent';
17
+ /**
18
+ * Resolve a `FileAuthStorageBackend` configured to use the CleoOS XDG
19
+ * auth directory (`~/.config/cleo/auth/auth.json`).
20
+ *
21
+ * The directory is NOT created here — that is handled by the postinstall
22
+ * script so that directory creation is a one-time operation.
23
+ *
24
+ * @returns A `FileAuthStorageBackend` pointed at the XDG-compliant path.
25
+ */
26
+ export declare function resolveKeystore(): FileAuthStorageBackend;
27
+ //# sourceMappingURL=keystore.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"keystore.d.ts","sourceRoot":"","sources":["../src/keystore.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAGH,OAAO,EAAE,sBAAsB,EAAE,MAAM,+BAA+B,CAAC;AAMvE;;;;;;;;GAQG;AACH,wBAAgB,eAAe,IAAI,sBAAsB,CAIxD"}
@@ -0,0 +1,35 @@
1
+ /**
2
+ * CleoOS keystore — Pi API key management with XDG-compliant storage.
3
+ *
4
+ * Wraps Pi's `FileAuthStorageBackend` with a CleoOS-specific XDG path so
5
+ * that credentials are persisted at `~/.config/cleo/auth/auth.json` (the
6
+ * `auth` sub-path of the CleoOS XDG config directory) rather than Pi's
7
+ * default location.
8
+ *
9
+ * This ensures:
10
+ * - Credentials survive `cleoos` reinstalls (XDG is outside the package).
11
+ * - Multiple CleoOS installations on the same host share credentials.
12
+ * - The auth file lives under the XDG Config spec (`~/.config/cleo/`).
13
+ *
14
+ * @packageDocumentation
15
+ */
16
+ import { join } from 'node:path';
17
+ import { FileAuthStorageBackend } from '@mariozechner/pi-coding-agent';
18
+ import { resolveCleoOsPaths } from './xdg.js';
19
+ /** Default auth file name inside the keystore directory. */
20
+ const AUTH_FILENAME = 'auth.json';
21
+ /**
22
+ * Resolve a `FileAuthStorageBackend` configured to use the CleoOS XDG
23
+ * auth directory (`~/.config/cleo/auth/auth.json`).
24
+ *
25
+ * The directory is NOT created here — that is handled by the postinstall
26
+ * script so that directory creation is a one-time operation.
27
+ *
28
+ * @returns A `FileAuthStorageBackend` pointed at the XDG-compliant path.
29
+ */
30
+ export function resolveKeystore() {
31
+ const paths = resolveCleoOsPaths();
32
+ const authFilePath = join(paths.auth, AUTH_FILENAME);
33
+ return new FileAuthStorageBackend(authFilePath);
34
+ }
35
+ //# sourceMappingURL=keystore.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"keystore.js","sourceRoot":"","sources":["../src/keystore.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,sBAAsB,EAAE,MAAM,+BAA+B,CAAC;AACvE,OAAO,EAAE,kBAAkB,EAAE,MAAM,UAAU,CAAC;AAE9C,4DAA4D;AAC5D,MAAM,aAAa,GAAG,WAAW,CAAC;AAElC;;;;;;;;GAQG;AACH,MAAM,UAAU,eAAe;IAC7B,MAAM,KAAK,GAAG,kBAAkB,EAAE,CAAC;IACnC,MAAM,YAAY,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,aAAa,CAAC,CAAC;IACrD,OAAO,IAAI,sBAAsB,CAAC,YAAY,CAAC,CAAC;AAClD,CAAC"}
@@ -0,0 +1,23 @@
1
+ /**
2
+ * CleoOS postinstall — scaffolds the global XDG hub and deploys extensions.
3
+ *
4
+ * Runs automatically after `npm install -g @cleocode/cleo-os`.
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
+ *
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.
15
+ *
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
21
+ */
22
+ export {};
23
+ //# sourceMappingURL=postinstall.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"postinstall.d.ts","sourceRoot":"","sources":["../src/postinstall.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG"}