@aivorynet/slaide 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (145) hide show
  1. package/CHANGELOG.md +26 -0
  2. package/LICENSE +201 -0
  3. package/README.md +87 -0
  4. package/bin/slaide.js +25 -0
  5. package/dist/assets.d.ts +10 -0
  6. package/dist/assets.js +54 -0
  7. package/dist/assets.js.map +1 -0
  8. package/dist/cli.d.ts +2 -0
  9. package/dist/cli.js +433 -0
  10. package/dist/cli.js.map +1 -0
  11. package/dist/compare/index.d.ts +24 -0
  12. package/dist/compare/index.js +246 -0
  13. package/dist/compare/index.js.map +1 -0
  14. package/dist/compare/ssim.d.ts +2 -0
  15. package/dist/compare/ssim.js +46 -0
  16. package/dist/compare/ssim.js.map +1 -0
  17. package/dist/compiler/chrome.d.ts +7 -0
  18. package/dist/compiler/chrome.js +94 -0
  19. package/dist/compiler/chrome.js.map +1 -0
  20. package/dist/compiler/compile.d.ts +2 -0
  21. package/dist/compiler/compile.js +432 -0
  22. package/dist/compiler/compile.js.map +1 -0
  23. package/dist/compiler/markdown.d.ts +26 -0
  24. package/dist/compiler/markdown.js +439 -0
  25. package/dist/compiler/markdown.js.map +1 -0
  26. package/dist/compiler/tokens.d.ts +13 -0
  27. package/dist/compiler/tokens.js +127 -0
  28. package/dist/compiler/tokens.js.map +1 -0
  29. package/dist/container.d.ts +47 -0
  30. package/dist/container.js +309 -0
  31. package/dist/container.js.map +1 -0
  32. package/dist/engine-entry.d.ts +1 -0
  33. package/dist/engine-entry.js +71 -0
  34. package/dist/engine-entry.js.map +1 -0
  35. package/dist/export-keynote/keynote.d.ts +10 -0
  36. package/dist/export-keynote/keynote.js +58 -0
  37. package/dist/export-keynote/keynote.js.map +1 -0
  38. package/dist/export-pptx/embed-fonts.d.ts +5 -0
  39. package/dist/export-pptx/embed-fonts.js +159 -0
  40. package/dist/export-pptx/embed-fonts.js.map +1 -0
  41. package/dist/export-pptx/inject-anim.d.ts +28 -0
  42. package/dist/export-pptx/inject-anim.js +150 -0
  43. package/dist/export-pptx/inject-anim.js.map +1 -0
  44. package/dist/export-pptx/pptx.d.ts +10 -0
  45. package/dist/export-pptx/pptx.js +425 -0
  46. package/dist/export-pptx/pptx.js.map +1 -0
  47. package/dist/export-pptx/transitions.d.ts +16 -0
  48. package/dist/export-pptx/transitions.js +82 -0
  49. package/dist/export-pptx/transitions.js.map +1 -0
  50. package/dist/import/emit.d.ts +5 -0
  51. package/dist/import/emit.js +274 -0
  52. package/dist/import/emit.js.map +1 -0
  53. package/dist/import/index.d.ts +21 -0
  54. package/dist/import/index.js +192 -0
  55. package/dist/import/index.js.map +1 -0
  56. package/dist/import/pptx.d.ts +117 -0
  57. package/dist/import/pptx.js +1043 -0
  58. package/dist/import/pptx.js.map +1 -0
  59. package/dist/import/raster-com.d.ts +27 -0
  60. package/dist/import/raster-com.js +113 -0
  61. package/dist/import/raster-com.js.map +1 -0
  62. package/dist/import/raster-extension.d.ts +35 -0
  63. package/dist/import/raster-extension.js +27 -0
  64. package/dist/import/raster-extension.js.map +1 -0
  65. package/dist/index.d.ts +63 -0
  66. package/dist/index.js +174 -0
  67. package/dist/index.js.map +1 -0
  68. package/dist/install/detect.d.ts +17 -0
  69. package/dist/install/detect.js +82 -0
  70. package/dist/install/detect.js.map +1 -0
  71. package/dist/install/index.d.ts +20 -0
  72. package/dist/install/index.js +126 -0
  73. package/dist/install/index.js.map +1 -0
  74. package/dist/install/registry.d.ts +33 -0
  75. package/dist/install/registry.js +169 -0
  76. package/dist/install/registry.js.map +1 -0
  77. package/dist/install/skills.d.ts +17 -0
  78. package/dist/install/skills.js +72 -0
  79. package/dist/install/skills.js.map +1 -0
  80. package/dist/master-io.d.ts +7 -0
  81. package/dist/master-io.js +55 -0
  82. package/dist/master-io.js.map +1 -0
  83. package/dist/mcp/server.d.ts +3 -0
  84. package/dist/mcp/server.js +114 -0
  85. package/dist/mcp/server.js.map +1 -0
  86. package/dist/optimize/export-optimize.d.ts +21 -0
  87. package/dist/optimize/export-optimize.js +167 -0
  88. package/dist/optimize/export-optimize.js.map +1 -0
  89. package/dist/parser/frontmatter.d.ts +8 -0
  90. package/dist/parser/frontmatter.js +45 -0
  91. package/dist/parser/frontmatter.js.map +1 -0
  92. package/dist/parser/parse.d.ts +2 -0
  93. package/dist/parser/parse.js +184 -0
  94. package/dist/parser/parse.js.map +1 -0
  95. package/dist/render/anim.d.ts +50 -0
  96. package/dist/render/anim.js +213 -0
  97. package/dist/render/anim.js.map +1 -0
  98. package/dist/render/charts.d.ts +3 -0
  99. package/dist/render/charts.js +171 -0
  100. package/dist/render/charts.js.map +1 -0
  101. package/dist/render/css.d.ts +3 -0
  102. package/dist/render/css.js +183 -0
  103. package/dist/render/css.js.map +1 -0
  104. package/dist/render/echarts-lib.generated.d.ts +1 -0
  105. package/dist/render/echarts-lib.generated.js +7 -0
  106. package/dist/render/echarts-lib.generated.js.map +1 -0
  107. package/dist/render/html.d.ts +5 -0
  108. package/dist/render/html.js +186 -0
  109. package/dist/render/html.js.map +1 -0
  110. package/dist/render/inject.d.ts +12 -0
  111. package/dist/render/inject.js +19 -0
  112. package/dist/render/inject.js.map +1 -0
  113. package/dist/render/mermaid-lib.generated.d.ts +1 -0
  114. package/dist/render/mermaid-lib.generated.js +7 -0
  115. package/dist/render/mermaid-lib.generated.js.map +1 -0
  116. package/dist/render/runtime.d.ts +1 -0
  117. package/dist/render/runtime.js +393 -0
  118. package/dist/render/runtime.js.map +1 -0
  119. package/dist/render-pdf/pdf.d.ts +9 -0
  120. package/dist/render-pdf/pdf.js +53 -0
  121. package/dist/render-pdf/pdf.js.map +1 -0
  122. package/dist/render-png/montage.d.ts +14 -0
  123. package/dist/render-png/montage.js +75 -0
  124. package/dist/render-png/montage.js.map +1 -0
  125. package/dist/render-png/shoot.d.ts +25 -0
  126. package/dist/render-png/shoot.js +79 -0
  127. package/dist/render-png/shoot.js.map +1 -0
  128. package/dist/scaffold.d.ts +9 -0
  129. package/dist/scaffold.js +36 -0
  130. package/dist/scaffold.js.map +1 -0
  131. package/dist/types.d.ts +212 -0
  132. package/dist/types.js +7 -0
  133. package/dist/types.js.map +1 -0
  134. package/dist/util.d.ts +6 -0
  135. package/dist/util.js +28 -0
  136. package/dist/util.js.map +1 -0
  137. package/package.json +66 -0
  138. package/skills/slaide/SKILL.md +64 -0
  139. package/skills/slaide/agents/openai.yaml +12 -0
  140. package/skills/slaide/examples/branded-deck.slaide +198 -0
  141. package/skills/slaide/examples/branded-theme.slaide.yaml +187 -0
  142. package/skills/slaide/examples/sample.slaide +98 -0
  143. package/skills/slaide/reference.md +177 -0
  144. package/skills/slaide/themes.md +171 -0
  145. package/themes/aurora.slaide.yaml +136 -0
@@ -0,0 +1,82 @@
1
+ // Copyright 2026 AIVory, Inc.
2
+ // SPDX-License-Identifier: Apache-2.0
3
+ // Detect which AI coding CLIs are installed on this machine. Mirrors the proven approach
4
+ // from the sibling agent-manager: per CLI a set of candidate binary names; resolve each on
5
+ // PATH (where.exe + PowerShell on Windows, `command -v` + common dirs on Unix); validate by
6
+ // running `<bin> --version`. No third-party deps, just node:child_process.
7
+ import { spawnSync } from 'node:child_process';
8
+ import { existsSync } from 'node:fs';
9
+ import { join } from 'node:path';
10
+ import { homedir } from 'node:os';
11
+ const isWin = process.platform === 'win32';
12
+ /** Resolve an executable name on the Windows PATH (where.exe, then PowerShell Get-Command). */
13
+ function findWindows(name) {
14
+ const where = spawnSync('where.exe', [name], { encoding: 'utf8', timeout: 5000, windowsHide: true });
15
+ if (where.status === 0 && where.stdout.trim()) {
16
+ const lines = where.stdout
17
+ .split(/\r?\n/)
18
+ .map((l) => l.trim())
19
+ .filter(Boolean);
20
+ return lines.find((l) => /\.(cmd|exe)$/i.test(l)) ?? lines[0];
21
+ }
22
+ const ps = spawnSync('powershell', ['-NoProfile', '-NonInteractive', '-Command', `(Get-Command '${name}' -ErrorAction SilentlyContinue).Source`], { encoding: 'utf8', timeout: 6000, windowsHide: true });
23
+ const out = (ps.stdout || '').trim();
24
+ return ps.status === 0 && out ? out.split(/\r?\n/)[0].trim() : null;
25
+ }
26
+ const UNIX_DIRS = ['/opt/homebrew/bin', '/usr/local/bin', '/usr/bin', '/bin'];
27
+ /** Resolve an executable name on the Unix PATH (login shell `command -v`, then common dirs). */
28
+ function findUnix(name) {
29
+ const sh = spawnSync('sh', ['-lc', `command -v ${name}`], { encoding: 'utf8', timeout: 5000 });
30
+ const out = (sh.stdout || '').trim();
31
+ if (sh.status === 0 && out)
32
+ return out.split(/\r?\n/)[0].trim();
33
+ const home = homedir();
34
+ const dirs = [...UNIX_DIRS, join(home, '.local/bin'), join(home, '.npm-global/bin'), join(home, '.bun/bin')];
35
+ for (const d of dirs) {
36
+ const p = join(d, name);
37
+ if (existsSync(p))
38
+ return p;
39
+ }
40
+ return null;
41
+ }
42
+ function findOnPath(name) {
43
+ return isWin ? findWindows(name) : findUnix(name);
44
+ }
45
+ /** Run `<bin> --version` and return the first non-empty output line, or null if it fails. */
46
+ function probeVersion(bin, flag, timeoutMs) {
47
+ // .cmd shims on Windows must be run through cmd; on Unix spawn the binary directly.
48
+ const r = isWin
49
+ ? spawnSync('cmd', ['/c', bin, flag], { encoding: 'utf8', timeout: timeoutMs, windowsHide: true })
50
+ : spawnSync(bin, [flag], { encoding: 'utf8', timeout: timeoutMs });
51
+ const out = `${r.stdout || ''}\n${r.stderr || ''}`;
52
+ const line = out
53
+ .split(/\r?\n/)
54
+ .map((l) => l.trim())
55
+ .find(Boolean);
56
+ if (r.status === 0 || line)
57
+ return line ?? '';
58
+ return null;
59
+ }
60
+ /** Detect a single CLI: resolve any of its binaries on PATH and validate with --version. */
61
+ export function detectOne(spec, timeoutMs = 10000) {
62
+ for (const name of spec.binaries) {
63
+ const bin = findOnPath(name);
64
+ if (!bin)
65
+ continue;
66
+ const version = probeVersion(bin, spec.versionFlag, timeoutMs);
67
+ if (version != null)
68
+ return { id: spec.id, displayName: spec.displayName, bin, version };
69
+ }
70
+ return null;
71
+ }
72
+ /** Detect every CLI in the list; returns only the installed ones, in spec order. */
73
+ export function detectClis(specs, timeoutMs = 10000) {
74
+ const found = [];
75
+ for (const spec of specs) {
76
+ const d = detectOne(spec, timeoutMs);
77
+ if (d)
78
+ found.push(d);
79
+ }
80
+ return found;
81
+ }
82
+ //# sourceMappingURL=detect.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"detect.js","sourceRoot":"","sources":["../../src/install/detect.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,20 @@
1
+ import { type DetectedCli } from './detect.js';
2
+ import { type Scope } from './registry.js';
3
+ export interface InstallOptions {
4
+ cli?: string[];
5
+ scope: Scope;
6
+ projectDir: string;
7
+ skills: boolean | undefined;
8
+ mcp: boolean | undefined;
9
+ yes: boolean;
10
+ list: boolean;
11
+ dryRun: boolean;
12
+ json: boolean;
13
+ }
14
+ /** Map --scope (project|global|<dir>) onto a scope + install root. */
15
+ export declare function parseScopeArg(value: string | undefined, cwd: string): {
16
+ scope: Scope;
17
+ projectDir: string;
18
+ };
19
+ export declare function listDetected(): DetectedCli[];
20
+ export declare function runInstall(opts: InstallOptions): Promise<number>;
@@ -0,0 +1,126 @@
1
+ // Copyright 2026 AIVory, Inc.
2
+ // SPDX-License-Identifier: Apache-2.0
3
+ // `slaide install`: detect the AI coding CLIs on this machine, let the user pick, copy the
4
+ // slaide authoring skill into each, and (opt-out) register the slaide MCP server. Interactive
5
+ // when run in a terminal; fully flag-driven (--cli/--scope/--skills/--mcp/--yes/--list/--json)
6
+ // for scripts and CI. No third-party deps: prompts use node:readline/promises.
7
+ import { homedir } from 'node:os';
8
+ import { resolve } from 'node:path';
9
+ import { detectClis } from './detect.js';
10
+ import { ADAPTERS, allSpecs, getAdapter } from './registry.js';
11
+ import { skillSourceDir, readSkillName } from './skills.js';
12
+ /** Map --scope (project|global|<dir>) onto a scope + install root. */
13
+ export function parseScopeArg(value, cwd) {
14
+ if (!value || value === 'project')
15
+ return { scope: 'project', projectDir: cwd };
16
+ if (value === 'global')
17
+ return { scope: 'global', projectDir: cwd };
18
+ return { scope: 'project', projectDir: resolve(value) }; // a path -> project install into it
19
+ }
20
+ export function listDetected() {
21
+ return detectClis(allSpecs());
22
+ }
23
+ function isInteractive(opts) {
24
+ return !!process.stdin.isTTY && !opts.yes;
25
+ }
26
+ async function ask(question) {
27
+ const { createInterface } = await import('node:readline/promises');
28
+ const rl = createInterface({ input: process.stdin, output: process.stdout });
29
+ try {
30
+ return (await rl.question(question)).trim();
31
+ }
32
+ finally {
33
+ rl.close();
34
+ }
35
+ }
36
+ async function promptSelect(detected) {
37
+ console.log('Detected AI coding CLIs:');
38
+ detected.forEach((d, i) => console.log(` ${i + 1}) ${d.displayName} (${d.version.split(/\s/)[0]})`));
39
+ const ans = await ask('Install for which? (comma-separated numbers, or "all"): ');
40
+ if (!ans || /^all$/i.test(ans))
41
+ return detected;
42
+ const picks = ans
43
+ .split(',')
44
+ .map((s) => parseInt(s.trim(), 10))
45
+ .filter((n) => n >= 1 && n <= detected.length)
46
+ .map((n) => detected[n - 1]);
47
+ return picks.length ? picks : detected;
48
+ }
49
+ async function promptYesNo(question, def) {
50
+ const ans = await ask(`${question} ${def ? '[Y/n]' : '[y/N]'} `);
51
+ if (!ans)
52
+ return def;
53
+ return /^y/i.test(ans);
54
+ }
55
+ /** Resolve which adapters to act on, from --cli or an interactive pick. */
56
+ async function chooseClis(opts, detected) {
57
+ if (opts.cli && opts.cli.length) {
58
+ return opts.cli.map((id) => {
59
+ const adapter = getAdapter(id);
60
+ if (!adapter)
61
+ throw new Error(`unknown CLI "${id}". Known: ${ADAPTERS.map((a) => a.id).join(', ')}`);
62
+ return { adapter, detected: detected.find((d) => d.id === id) ?? null };
63
+ });
64
+ }
65
+ if (!detected.length)
66
+ throw new Error('no supported AI coding CLIs detected. Pass --cli <id> to install anyway.');
67
+ const picks = isInteractive(opts) ? await promptSelect(detected) : detected;
68
+ return picks.map((d) => ({ adapter: getAdapter(d.id), detected: d }));
69
+ }
70
+ export async function runInstall(opts) {
71
+ // Detection probes every CLI with `--version` (slow). Skip it when the CLIs are named
72
+ // explicitly and MCP registration is off, since a skill copy needs no detection.
73
+ const needDetect = opts.list || !(opts.cli && opts.cli.length) || opts.mcp !== false;
74
+ const detected = needDetect ? listDetected() : [];
75
+ if (opts.list) {
76
+ console.log(JSON.stringify(detected, null, 2));
77
+ return 0;
78
+ }
79
+ let chosen;
80
+ try {
81
+ chosen = await chooseClis(opts, detected);
82
+ }
83
+ catch (e) {
84
+ console.error('error: ' + e.message);
85
+ return 1;
86
+ }
87
+ // Decide skill + MCP once for the whole run.
88
+ let doSkills = opts.skills;
89
+ if (doSkills === undefined)
90
+ doSkills = isInteractive(opts) ? await promptYesNo('Install the slaide authoring skill?', true) : true;
91
+ let doMcp = opts.mcp;
92
+ if (doMcp === undefined)
93
+ doMcp = isInteractive(opts) ? await promptYesNo('Register the slaide MCP server?', true) : true;
94
+ const skillSrcDir = skillSourceDir();
95
+ const skillName = readSkillName(skillSrcDir);
96
+ const homeDir = homedir();
97
+ const summary = [];
98
+ for (const { adapter, detected: det } of chosen) {
99
+ const ctx = { scope: opts.scope, projectDir: opts.projectDir, homeDir, skillName, skillSrcDir, dryRun: opts.dryRun };
100
+ const row = { cli: adapter.id, displayName: adapter.displayName, detected: needDetect ? !!det : null };
101
+ if (doSkills) {
102
+ const r = adapter.installSkill(ctx);
103
+ row.skill = { dest: r.dest, files: r.files, notes: r.notes };
104
+ }
105
+ if (doMcp) {
106
+ const r = adapter.registerMcp(ctx, det);
107
+ row.mcp = { registered: r.registered, method: r.method, detail: r.detail };
108
+ }
109
+ summary.push(row);
110
+ }
111
+ if (opts.json) {
112
+ console.log(JSON.stringify(summary, null, 2));
113
+ }
114
+ else {
115
+ for (const row of summary) {
116
+ const tag = opts.dryRun ? '[dry-run] ' : '';
117
+ console.log(`${tag}${row.displayName}${row.detected === false ? ' (not detected)' : ''}`);
118
+ if (row.skill)
119
+ console.log(` skill -> ${row.skill.dest} (${row.skill.files} files)${row.skill.notes.length ? '; ' + row.skill.notes.join('; ') : ''}`);
120
+ if (row.mcp)
121
+ console.log(` mcp -> ${row.mcp.registered ? 'registered (' + row.mcp.method + ')' : 'skipped: ' + row.mcp.detail}`);
122
+ }
123
+ }
124
+ return 0;
125
+ }
126
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/install/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,33 @@
1
+ import type { CliSpec, DetectedCli } from './detect.js';
2
+ export type Scope = 'project' | 'global';
3
+ export interface InstallContext {
4
+ scope: Scope;
5
+ projectDir: string;
6
+ homeDir: string;
7
+ skillName: string;
8
+ skillSrcDir: string;
9
+ dryRun: boolean;
10
+ }
11
+ export interface SkillInstallResult {
12
+ installed: boolean;
13
+ dest: string;
14
+ files: number;
15
+ notes: string[];
16
+ }
17
+ export interface McpRegisterResult {
18
+ registered: boolean;
19
+ method: 'cli' | 'file' | 'skipped';
20
+ detail: string;
21
+ }
22
+ export interface CliAdapter {
23
+ id: string;
24
+ displayName: string;
25
+ spec: CliSpec;
26
+ /** Where SKILL.md lands for this scope (a folder, or a file for rule-based CLIs). */
27
+ skillTarget(ctx: InstallContext): string;
28
+ installSkill(ctx: InstallContext): SkillInstallResult;
29
+ registerMcp(ctx: InstallContext, detected: DetectedCli | null): McpRegisterResult;
30
+ }
31
+ export declare const ADAPTERS: CliAdapter[];
32
+ export declare function allSpecs(): CliSpec[];
33
+ export declare function getAdapter(id: string): CliAdapter | undefined;
@@ -0,0 +1,169 @@
1
+ // Copyright 2026 AIVory, Inc.
2
+ // SPDX-License-Identifier: Apache-2.0
3
+ // One adapter per supported AI coding CLI: where its skill files live, how to drop them, and
4
+ // how to register the slaide MCP server. New CLI = one entry here. MCP registration shells out
5
+ // to the CLI's own `mcp add` so the CLI merges its own config (we never hand-edit and clobber).
6
+ import { spawnSync } from 'node:child_process';
7
+ import { join, relative } from 'node:path';
8
+ import { readFileSync, writeFileSync, existsSync, mkdirSync } from 'node:fs';
9
+ import { copyDir, mergePointerFile } from './skills.js';
10
+ const isWin = process.platform === 'win32';
11
+ const SENTINEL = '<!-- slaide-skill -->';
12
+ const MCP_ARGS = ['npx', '-y', '@aivorynet/slaide', 'mcp']; // the stdio MCP launcher, shared by all CLIs
13
+ /** Run a CLI subcommand (e.g. `claude mcp add ...`), routing .cmd shims through cmd on Windows. */
14
+ function runCli(bin, args, cwd) {
15
+ const r = isWin
16
+ ? spawnSync('cmd', ['/c', bin, ...args], { encoding: 'utf8', cwd, windowsHide: true, timeout: 20000 })
17
+ : spawnSync(bin, args, { encoding: 'utf8', cwd, timeout: 20000 });
18
+ const out = `${r.stdout || ''}${r.stderr || ''}`.trim();
19
+ return { ok: r.status === 0, out };
20
+ }
21
+ /** Copy the skill folder; the common case for skills-folder CLIs. */
22
+ function copySkill(ctx, dest, notes = []) {
23
+ const r = copyDir(ctx.skillSrcDir, dest, ctx.dryRun);
24
+ return { installed: true, dest, files: r.files, notes };
25
+ }
26
+ /** Register via the CLI's own `mcp add`. cmdArgs is everything after the binary. */
27
+ function mcpViaCli(detected, cmdArgs, ctx) {
28
+ if (!detected)
29
+ return { registered: false, method: 'skipped', detail: 'CLI not detected' };
30
+ if (ctx.dryRun)
31
+ return { registered: true, method: 'cli', detail: `${detected.bin} ${cmdArgs.join(' ')}` };
32
+ const cwd = ctx.scope === 'project' ? ctx.projectDir : undefined;
33
+ const r = runCli(detected.bin, cmdArgs, cwd);
34
+ return r.ok
35
+ ? { registered: true, method: 'cli', detail: 'mcp add' }
36
+ : { registered: false, method: 'cli', detail: r.out.split(/\r?\n/)[0] || 'mcp add failed' };
37
+ }
38
+ const claude = {
39
+ id: 'claude',
40
+ displayName: 'Claude Code',
41
+ spec: { id: 'claude', displayName: 'Claude Code', binaries: ['claude', 'claude.cmd', 'claude.exe'], versionFlag: '--version', installHint: 'npm i -g @anthropic-ai/claude-code' },
42
+ skillTarget(ctx) {
43
+ const base = ctx.scope === 'project' ? ctx.projectDir : ctx.homeDir;
44
+ return join(base, '.claude', 'skills', ctx.skillName);
45
+ },
46
+ installSkill(ctx) {
47
+ return copySkill(ctx, this.skillTarget(ctx));
48
+ },
49
+ registerMcp(ctx, detected) {
50
+ const scope = ctx.scope === 'project' ? 'project' : 'user';
51
+ return mcpViaCli(detected, ['mcp', 'add', ctx.skillName, '-s', scope, '--', ...MCP_ARGS], ctx);
52
+ },
53
+ };
54
+ const codex = {
55
+ id: 'codex',
56
+ displayName: 'Codex CLI',
57
+ spec: { id: 'codex', displayName: 'Codex CLI', binaries: ['codex', 'codex.cmd', 'codex.exe'], versionFlag: '--version', installHint: 'npm i -g @openai/codex' },
58
+ skillTarget(ctx) {
59
+ const base = ctx.scope === 'project' ? ctx.projectDir : ctx.homeDir;
60
+ return join(base, '.codex', 'skills', ctx.skillName);
61
+ },
62
+ installSkill(ctx) {
63
+ const dest = this.skillTarget(ctx);
64
+ const notes = [];
65
+ if (ctx.scope === 'project') {
66
+ const block = `slaide deck authoring. See .codex/skills/${ctx.skillName}/SKILL.md`;
67
+ if (mergePointerFile(join(ctx.projectDir, 'AGENTS.md'), block, SENTINEL, ctx.dryRun))
68
+ notes.push('AGENTS.md pointer added');
69
+ }
70
+ return copySkill(ctx, dest, notes);
71
+ },
72
+ registerMcp(ctx, detected) {
73
+ // codex stores MCP servers globally (~/.codex/config.toml); there is no per-project scope.
74
+ const r = mcpViaCli(detected, ['mcp', 'add', ctx.skillName, '--', ...MCP_ARGS], ctx);
75
+ if (r.registered && ctx.scope === 'project')
76
+ r.detail = 'mcp add (codex registers globally)';
77
+ return r;
78
+ },
79
+ };
80
+ const gemini = {
81
+ id: 'gemini',
82
+ displayName: 'Gemini CLI',
83
+ spec: { id: 'gemini', displayName: 'Gemini CLI', binaries: ['gemini', 'gemini.cmd', 'gemini.exe'], versionFlag: '--version', installHint: 'npm i -g @google/gemini-cli' },
84
+ skillTarget(ctx) {
85
+ const base = ctx.scope === 'project' ? ctx.projectDir : ctx.homeDir;
86
+ return join(base, '.gemini', 'skills', ctx.skillName);
87
+ },
88
+ installSkill(ctx) {
89
+ const dest = this.skillTarget(ctx);
90
+ const res = copySkill(ctx, dest);
91
+ // GEMINI.md imports context with @path; point it at the freshly copied SKILL.md.
92
+ const mdFile = ctx.scope === 'project' ? join(ctx.projectDir, 'GEMINI.md') : join(ctx.homeDir, '.gemini', 'GEMINI.md');
93
+ const importPath = './' + relative(join(mdFile, '..'), join(dest, 'SKILL.md')).split('\\').join('/');
94
+ const block = `slaide deck authoring. See @${importPath}`;
95
+ if (mergePointerFile(mdFile, block, SENTINEL, ctx.dryRun))
96
+ res.notes.push('GEMINI.md pointer added');
97
+ return res;
98
+ },
99
+ registerMcp(ctx, detected) {
100
+ const scope = ctx.scope === 'project' ? 'project' : 'user';
101
+ return mcpViaCli(detected, ['mcp', 'add', ctx.skillName, '-s', scope, '-t', 'stdio', ...MCP_ARGS], ctx);
102
+ },
103
+ };
104
+ // Cursor uses project rule files (.cursor/rules/*.mdc) and a JSON MCP config; no `mcp add` CLI.
105
+ const cursor = {
106
+ id: 'cursor',
107
+ displayName: 'Cursor',
108
+ spec: { id: 'cursor', displayName: 'Cursor', binaries: ['cursor-agent', 'cursor-agent.cmd', 'agent', 'agent.exe'], versionFlag: '--version', installHint: 'https://cursor.com' },
109
+ skillTarget(ctx) {
110
+ return join(ctx.projectDir, '.cursor', 'rules', `${ctx.skillName}.mdc`);
111
+ },
112
+ installSkill(ctx) {
113
+ const dest = this.skillTarget(ctx);
114
+ const body = readFileSync(join(ctx.skillSrcDir, 'SKILL.md'), 'utf8').replace(/^---[\s\S]*?---\n/, '');
115
+ const mdc = `---\ndescription: Author and render slaide presentations\nglobs: ["**/*.slaide", "**/*.slaide.yaml", "**/*.slaidec"]\nalwaysApply: false\n---\n${body}`;
116
+ if (!ctx.dryRun) {
117
+ mkdirSync(join(dest, '..'), { recursive: true });
118
+ writeFileSync(dest, mdc, 'utf8');
119
+ }
120
+ return { installed: true, dest, files: 1, notes: [] };
121
+ },
122
+ registerMcp(ctx, detected) {
123
+ return mcpFileJson(join(ctx.scope === 'project' ? ctx.projectDir : ctx.homeDir, '.cursor', 'mcp.json'), ctx);
124
+ },
125
+ };
126
+ // Aider has no skills/MCP concept; it reads CONVENTIONS.md. Drop the skill and point at it.
127
+ const aider = {
128
+ id: 'aider',
129
+ displayName: 'Aider',
130
+ spec: { id: 'aider', displayName: 'Aider', binaries: ['aider', 'aider.exe'], versionFlag: '--version', installHint: 'pip install aider-chat' },
131
+ skillTarget(ctx) {
132
+ return join(ctx.projectDir, '.aider', 'skills', ctx.skillName);
133
+ },
134
+ installSkill(ctx) {
135
+ const dest = this.skillTarget(ctx);
136
+ const res = copySkill(ctx, dest);
137
+ const block = `slaide deck authoring. See .aider/skills/${ctx.skillName}/SKILL.md`;
138
+ if (mergePointerFile(join(ctx.projectDir, 'CONVENTIONS.md'), block, SENTINEL, ctx.dryRun))
139
+ res.notes.push('CONVENTIONS.md pointer added');
140
+ return res;
141
+ },
142
+ registerMcp() {
143
+ return { registered: false, method: 'skipped', detail: 'aider has no MCP support' };
144
+ },
145
+ };
146
+ /** Merge an mcpServers entry into a JSON config (read-modify-write, preserving other keys). */
147
+ function mcpFileJson(file, ctx) {
148
+ if (ctx.dryRun)
149
+ return { registered: true, method: 'file', detail: file };
150
+ try {
151
+ const obj = existsSync(file) ? JSON.parse(readFileSync(file, 'utf8') || '{}') : {};
152
+ obj.mcpServers = obj.mcpServers || {};
153
+ obj.mcpServers[ctx.skillName] = { command: 'npx', args: ['-y', '@aivorynet/slaide', 'mcp'] };
154
+ mkdirSync(join(file, '..'), { recursive: true });
155
+ writeFileSync(file, JSON.stringify(obj, null, 2), 'utf8');
156
+ return { registered: true, method: 'file', detail: file };
157
+ }
158
+ catch (e) {
159
+ return { registered: false, method: 'file', detail: e.message };
160
+ }
161
+ }
162
+ export const ADAPTERS = [claude, codex, gemini, cursor, aider];
163
+ export function allSpecs() {
164
+ return ADAPTERS.map((a) => a.spec);
165
+ }
166
+ export function getAdapter(id) {
167
+ return ADAPTERS.find((a) => a.id === id);
168
+ }
169
+ //# sourceMappingURL=registry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"registry.js","sourceRoot":"","sources":["../../src/install/registry.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,17 @@
1
+ /** The `core/` package root, from src/install/ (tsx dev) or dist/install/ (published). */
2
+ export declare function coreRoot(): string;
3
+ /** Absolute path to the bundled skill folder; throws a clear error if it is missing. */
4
+ export declare function skillSourceDir(name?: string): string;
5
+ /** The skill's declared name (SKILL.md frontmatter `name:`), defaulting to the folder default. */
6
+ export declare function readSkillName(srcDir: string): string;
7
+ export interface CopyResult {
8
+ files: number;
9
+ dest: string;
10
+ }
11
+ /** Recursively copy a directory (overwriting). Counts files; dryRun reports without writing. */
12
+ export declare function copyDir(srcDir: string, destDir: string, dryRun?: boolean): CopyResult;
13
+ /**
14
+ * Append a block to a context file once, delimited by a sentinel so re-runs are idempotent and
15
+ * existing content is preserved. Returns true if it wrote (or would write, in dryRun).
16
+ */
17
+ export declare function mergePointerFile(file: string, block: string, sentinel: string, dryRun?: boolean): boolean;
@@ -0,0 +1,72 @@
1
+ // Copyright 2026 AIVory, Inc.
2
+ // SPDX-License-Identifier: Apache-2.0
3
+ // Locate the bundled slaide authoring skill and copy it into a target CLI's skills folder,
4
+ // plus merge a small pointer block into context files (GEMINI.md / AGENTS.md / CONVENTIONS.md)
5
+ // without clobbering what is already there.
6
+ import { fileURLToPath } from 'node:url';
7
+ import { dirname, resolve, join } from 'node:path';
8
+ import { existsSync, mkdirSync, readdirSync, copyFileSync, readFileSync, writeFileSync } from 'node:fs';
9
+ /** The `core/` package root, from src/install/ (tsx dev) or dist/install/ (published). */
10
+ export function coreRoot() {
11
+ return resolve(dirname(fileURLToPath(import.meta.url)), '..', '..');
12
+ }
13
+ /** Absolute path to the bundled skill folder; throws a clear error if it is missing. */
14
+ export function skillSourceDir(name = 'slaide') {
15
+ const dir = join(coreRoot(), 'skills', name);
16
+ if (!existsSync(join(dir, 'SKILL.md'))) {
17
+ throw new Error(`slaide skill source not found at ${dir}. In a checkout run the skill sync ` +
18
+ `(npx tsx scripts/dev/sync-skill.ts); in a published install ensure slaide shipped its "skills" folder.`);
19
+ }
20
+ return dir;
21
+ }
22
+ /** The skill's declared name (SKILL.md frontmatter `name:`), defaulting to the folder default. */
23
+ export function readSkillName(srcDir) {
24
+ try {
25
+ const head = readFileSync(join(srcDir, 'SKILL.md'), 'utf8').slice(0, 600);
26
+ const m = head.match(/^name:\s*([A-Za-z0-9_-]+)/m);
27
+ if (m)
28
+ return m[1];
29
+ }
30
+ catch {
31
+ /* fall through to default */
32
+ }
33
+ return 'slaide';
34
+ }
35
+ /** Recursively copy a directory (overwriting). Counts files; dryRun reports without writing. */
36
+ export function copyDir(srcDir, destDir, dryRun = false) {
37
+ let files = 0;
38
+ const walk = (src, dest) => {
39
+ if (!dryRun)
40
+ mkdirSync(dest, { recursive: true });
41
+ for (const ent of readdirSync(src, { withFileTypes: true })) {
42
+ const s = join(src, ent.name);
43
+ const d = join(dest, ent.name);
44
+ if (ent.isDirectory())
45
+ walk(s, d);
46
+ else {
47
+ if (!dryRun)
48
+ copyFileSync(s, d);
49
+ files++;
50
+ }
51
+ }
52
+ };
53
+ walk(srcDir, destDir);
54
+ return { files, dest: destDir };
55
+ }
56
+ /**
57
+ * Append a block to a context file once, delimited by a sentinel so re-runs are idempotent and
58
+ * existing content is preserved. Returns true if it wrote (or would write, in dryRun).
59
+ */
60
+ export function mergePointerFile(file, block, sentinel, dryRun = false) {
61
+ const existing = existsSync(file) ? readFileSync(file, 'utf8') : '';
62
+ if (existing.includes(sentinel))
63
+ return false; // already present
64
+ const sep = existing && !existing.endsWith('\n') ? '\n\n' : existing ? '\n' : '';
65
+ const next = existing + sep + sentinel + '\n' + block + '\n';
66
+ if (!dryRun) {
67
+ mkdirSync(dirname(file), { recursive: true });
68
+ writeFileSync(file, next, 'utf8');
69
+ }
70
+ return true;
71
+ }
72
+ //# sourceMappingURL=skills.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"skills.js","sourceRoot":"","sources":["../../src/install/skills.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ import type { Master } from './types.js';
2
+ /** Schema header prepended to every emitted master (drives YAML LSP autocompletion). */
3
+ export declare const MASTER_SCHEMA_HEADER = "# yaml-language-server: $schema=https://getslaide.com/schema/v1.json\n";
4
+ /** Serialize a Master to canonical `*.slaide.yaml` text (schema header + stable key order). */
5
+ export declare function serializeMaster(master: Master): string;
6
+ /** Parse `*.slaide.yaml` master text into a Master object (inverse of serializeMaster). */
7
+ export declare function parseMaster(text: string): Master;
@@ -0,0 +1,55 @@
1
+ // Copyright 2026 AIVory, Inc.
2
+ // SPDX-License-Identifier: Apache-2.0
3
+ // Master (theme) YAML (de)serialization — the single read/write path for a *.slaide.yaml
4
+ // master. `serializeMaster()` is the canonical writer (schema header + stable top-level key
5
+ // order) used by BOTH the importer (core/src/import/emit.ts) and the editor's master
6
+ // write-back; it is the inverse of `parseMaster()` / `loadMaster()`, so an in-place theme
7
+ // edit round-trips losslessly (load → serialize → reload deep-equals the original).
8
+ import yaml from 'js-yaml';
9
+ /** Schema header prepended to every emitted master (drives YAML LSP autocompletion). */
10
+ export const MASTER_SCHEMA_HEADER = '# yaml-language-server: $schema=https://getslaide.com/schema/v1.json\n';
11
+ /** Canonical top-level key order — keeps emitted masters readable + diff-stable. Any key not
12
+ * listed here is appended afterwards in its existing order, so nothing is ever dropped. */
13
+ const KEY_ORDER = [
14
+ 'schema',
15
+ 'name',
16
+ 'description',
17
+ 'canvas',
18
+ 'fonts',
19
+ 'typeScale',
20
+ 'colors',
21
+ 'gradients',
22
+ 'tokens',
23
+ 'backgrounds',
24
+ 'layouts',
25
+ 'variants',
26
+ 'transitions',
27
+ 'animations',
28
+ 'chrome',
29
+ 'ui',
30
+ ];
31
+ /** Reorder a master's top-level keys into the canonical order (deterministic output). */
32
+ function orderKeys(master) {
33
+ const src = master;
34
+ const out = {};
35
+ for (const k of KEY_ORDER)
36
+ if (src[k] !== undefined)
37
+ out[k] = src[k];
38
+ for (const k of Object.keys(src))
39
+ if (!(k in out) && src[k] !== undefined)
40
+ out[k] = src[k];
41
+ return out;
42
+ }
43
+ /** Serialize a Master to canonical `*.slaide.yaml` text (schema header + stable key order). */
44
+ export function serializeMaster(master) {
45
+ return MASTER_SCHEMA_HEADER + yaml.dump(orderKeys(master), { lineWidth: 200 });
46
+ }
47
+ /** Parse `*.slaide.yaml` master text into a Master object (inverse of serializeMaster). */
48
+ export function parseMaster(text) {
49
+ const obj = yaml.load(text);
50
+ if (!obj || typeof obj !== 'object' || Array.isArray(obj)) {
51
+ throw new Error('Master YAML is not a valid mapping');
52
+ }
53
+ return obj;
54
+ }
55
+ //# sourceMappingURL=master-io.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"master-io.js","sourceRoot":"","sources":["../src/master-io.ts"],"names":[],"mappings":"AAAA,8BAA8B;AAC9B,sCAAsC;AACtC,yFAAyF;AACzF,4FAA4F;AAC5F,qFAAqF;AACrF,0FAA0F;AAC1F,oFAAoF;AACpF,OAAO,IAAI,MAAM,SAAS,CAAC;AAG3B,wFAAwF;AACxF,MAAM,CAAC,MAAM,oBAAoB,GAAG,wEAAwE,CAAC;AAE7G;4FAC4F;AAC5F,MAAM,SAAS,GAAsB;IACnC,QAAQ;IACR,MAAM;IACN,aAAa;IACb,QAAQ;IACR,OAAO;IACP,WAAW;IACX,QAAQ;IACR,WAAW;IACX,QAAQ;IACR,aAAa;IACb,SAAS;IACT,UAAU;IACV,aAAa;IACb,YAAY;IACZ,QAAQ;IACR,IAAI;CACL,CAAC;AAEF,yFAAyF;AACzF,SAAS,SAAS,CAAC,MAAc;IAC/B,MAAM,GAAG,GAAG,MAA4C,CAAC;IACzD,MAAM,GAAG,GAA4B,EAAE,CAAC;IACxC,KAAK,MAAM,CAAC,IAAI,SAAS;QAAE,IAAI,GAAG,CAAC,CAAC,CAAC,KAAK,SAAS;YAAE,GAAG,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC;IACrE,KAAK,MAAM,CAAC,IAAI,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC;QAAE,IAAI,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC,IAAI,GAAG,CAAC,CAAC,CAAC,KAAK,SAAS;YAAE,GAAG,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC;IAC3F,OAAO,GAAG,CAAC;AACb,CAAC;AAED,+FAA+F;AAC/F,MAAM,UAAU,eAAe,CAAC,MAAc;IAC5C,OAAO,oBAAoB,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,EAAE,EAAE,SAAS,EAAE,GAAG,EAAE,CAAC,CAAC;AACjF,CAAC;AAED,2FAA2F;AAC3F,MAAM,UAAU,WAAW,CAAC,IAAY;IACtC,MAAM,GAAG,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC5B,IAAI,CAAC,GAAG,IAAI,OAAO,GAAG,KAAK,QAAQ,IAAI,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC;QAC1D,MAAM,IAAI,KAAK,CAAC,oCAAoC,CAAC,CAAC;IACxD,CAAC;IACD,OAAO,GAAa,CAAC;AACvB,CAAC"}