@studiolxd/lxd-cli 0.1.0-next.0 → 0.1.0-next.1

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 CHANGED
@@ -53,6 +53,8 @@ lxd tracking --report completion score success
53
53
  lxd validate # actionable pass/fail across all checks
54
54
  lxd handoff # write .agent/** specs + prompts + scaffold generated/
55
55
  # → run YOUR agent against .agent/** to produce generated/
56
+ # → also writes .claude/commands/lxd-generate.md; in Claude Code run /project:lxd-generate
57
+ # (operational only — reads .agent/ as the source of truth; generic .agent/ stays agent-agnostic)
56
58
  lxd preview --mock-lms # build + serve locally, with a mock LMS
57
59
  lxd export --target web --target scorm-1.2 --target scorm-2004
58
60
  ```
package/dist/cli/index.js CHANGED
@@ -8,7 +8,7 @@ import { realpathSync } from "node:fs";
8
8
  // package.json
9
9
  var package_default = {
10
10
  name: "@studiolxd/lxd-cli",
11
- version: "0.1.0-next.0",
11
+ version: "0.1.0-next.1",
12
12
  description: "CLI-first authoring tool for AI-native elearning packages (agent-orchestrated, framework- and export-target-agnostic).",
13
13
  type: "module",
14
14
  license: "UNLICENSED",
@@ -16,7 +16,7 @@ var package_default = {
16
16
  node: ">=20"
17
17
  },
18
18
  bin: {
19
- lxd: "./dist/cli/index.js"
19
+ lxd: "dist/cli/index.js"
20
20
  },
21
21
  files: [
22
22
  "dist",
@@ -1542,13 +1542,13 @@ function register10(program) {
1542
1542
  }
1543
1543
 
1544
1544
  // src/cli/commands/handoff.ts
1545
- import { join as join9 } from "node:path";
1545
+ import { join as join10 } from "node:path";
1546
1546
  import { access as access4 } from "node:fs/promises";
1547
1547
  import { confirm, isCancel } from "@clack/prompts";
1548
1548
 
1549
1549
  // src/agent/handoff/producer.ts
1550
- import { mkdir as mkdir4, writeFile as writeFile4 } from "node:fs/promises";
1551
- import { join as join6 } from "node:path";
1550
+ import { mkdir as mkdir5, writeFile as writeFile5 } from "node:fs/promises";
1551
+ import { join as join7, dirname as dirname2 } from "node:path";
1552
1552
 
1553
1553
  // src/agent/handoff/scorm-skills.ts
1554
1554
  import { mkdir as mkdir2, writeFile as writeFile2 } from "node:fs/promises";
@@ -1608,17 +1608,78 @@ async function writeScormSkillsSnapshot(agentDir, opts = {}) {
1608
1608
  return { ref: `${ref}@${version}` };
1609
1609
  }
1610
1610
 
1611
- // src/core/project/assets.ts
1612
- import { mkdir as mkdir3, readFile as readFile4, writeFile as writeFile3 } from "node:fs/promises";
1611
+ // src/agent/handoff/claude-command.ts
1612
+ import { mkdir as mkdir3, writeFile as writeFile3 } from "node:fs/promises";
1613
1613
  import { join as join5 } from "node:path";
1614
+ function renderClaudeCommand(opts) {
1615
+ const lines = [
1616
+ "# lxd-generate",
1617
+ "",
1618
+ "Operational instructions for implementing this LXD elearning package with Claude Code",
1619
+ "(invoke as `/project:lxd-generate`). The `.agent/` directory is the SOURCE OF TRUTH \u2014",
1620
+ "read it and implement to it; do not infer the learning design from anything else.",
1621
+ "",
1622
+ "## Read first",
1623
+ "",
1624
+ "1. Read `.agent/spec.md` (the package specification).",
1625
+ "2. Read `.agent/instructions.md` (the agent instructions).",
1626
+ "3. Read all relevant files under `.agent/prompts/` (one per experience, plus the package shell)."
1627
+ ];
1628
+ if (opts.scormSkills) {
1629
+ lines.push("4. Read `.agent/scorm-skills/` (SCORM runtime guidance).");
1630
+ }
1631
+ lines.push(
1632
+ "",
1633
+ "Treat `.agent/` as the **source of truth** for the learning design.",
1634
+ "",
1635
+ "## Implement",
1636
+ "",
1637
+ "- Implement the package under `generated/`.",
1638
+ "- Do not modify `.agent/` (the CLI regenerates it).",
1639
+ "- Do not modify the package specification YAML files unless strictly necessary."
1640
+ );
1641
+ if (opts.scorm) {
1642
+ lines.push(
1643
+ "",
1644
+ "## SCORM",
1645
+ "",
1646
+ "- Do not generate a custom SCORM runtime.",
1647
+ "- Use `@studiolxd/scorm` as the runtime integration layer for all SCORM interactions.",
1648
+ "- Follow the SCORM guidance emitted under `.agent/scorm-skills/`."
1649
+ );
1650
+ }
1651
+ lines.push(
1652
+ "",
1653
+ "## Report",
1654
+ "",
1655
+ "When done, report the files you created or modified, then the next commands:",
1656
+ "",
1657
+ "- `lxd validate`",
1658
+ "- `lxd preview`",
1659
+ "- `lxd export`",
1660
+ ""
1661
+ );
1662
+ return lines.join("\n");
1663
+ }
1664
+ async function writeClaudeCommand(packageDir, opts) {
1665
+ const dir = join5(packageDir, ".claude", "commands");
1666
+ await mkdir3(dir, { recursive: true });
1667
+ const path = join5(dir, "lxd-generate.md");
1668
+ await writeFile3(path, renderClaudeCommand(opts), "utf8");
1669
+ return path;
1670
+ }
1671
+
1672
+ // src/core/project/assets.ts
1673
+ import { mkdir as mkdir4, readFile as readFile4, writeFile as writeFile4 } from "node:fs/promises";
1674
+ import { join as join6 } from "node:path";
1614
1675
  import { parse as parseYaml4, stringify as stringifyYaml2 } from "yaml";
1615
1676
  var MANIFEST_PATH = [".elearning", "manifest.lock"];
1616
1677
  var RECOMMENDED_ASSETS = {
1617
- scormLibraryVersion: "^1.0.0",
1678
+ scormLibraryVersion: "^2.0.0",
1618
1679
  scormSkillsSnapshot: { version: "main", ref: "github:studiolxd/scorm-skills" }
1619
1680
  };
1620
1681
  function manifestFile(dir) {
1621
- return join5(dir, ...MANIFEST_PATH);
1682
+ return join6(dir, ...MANIFEST_PATH);
1622
1683
  }
1623
1684
  async function readManifest(dir) {
1624
1685
  try {
@@ -1628,8 +1689,8 @@ async function readManifest(dir) {
1628
1689
  }
1629
1690
  }
1630
1691
  async function writeManifest(dir, manifest) {
1631
- await mkdir3(join5(dir, ".elearning"), { recursive: true });
1632
- await writeFile3(manifestFile(dir), stringifyYaml2(manifest), "utf8");
1692
+ await mkdir4(join6(dir, ".elearning"), { recursive: true });
1693
+ await writeFile4(manifestFile(dir), stringifyYaml2(manifest), "utf8");
1633
1694
  }
1634
1695
  async function updateAssets(dir, update) {
1635
1696
  const manifest = await readManifest(dir);
@@ -1668,21 +1729,21 @@ function createHandoffProducer() {
1668
1729
  version: VERSION,
1669
1730
  async produce(input) {
1670
1731
  const out = input.outputDir;
1671
- await mkdir4(join6(out, "prompts"), { recursive: true });
1732
+ await mkdir5(join7(out, "prompts"), { recursive: true });
1672
1733
  const spec = renderSpec(input);
1673
- const specPath = join6(out, "spec.md");
1674
- await writeFile4(specPath, spec, "utf8");
1734
+ const specPath = join7(out, "spec.md");
1735
+ await writeFile5(specPath, spec, "utf8");
1675
1736
  const prompts = [];
1676
- const shellPath = join6(out, "prompts", "package-shell.md");
1677
- await writeFile4(shellPath, renderShellPrompt(input), "utf8");
1737
+ const shellPath = join7(out, "prompts", "package-shell.md");
1738
+ await writeFile5(shellPath, renderShellPrompt(input), "utf8");
1678
1739
  prompts.push({ id: "package-shell", path: shellPath });
1679
1740
  for (const ref of input.package.experienceRefs) {
1680
- const p = join6(out, "prompts", `${ref}.md`);
1681
- await writeFile4(p, renderExperiencePrompt(ref, input), "utf8");
1741
+ const p = join7(out, "prompts", `${ref}.md`);
1742
+ await writeFile5(p, renderExperiencePrompt(ref, input), "utf8");
1682
1743
  prompts.push({ id: ref, path: p });
1683
1744
  }
1684
1745
  const instructions = renderInstructions(input);
1685
- await writeFile4(join6(out, "instructions.md"), instructions, "utf8");
1746
+ await writeFile5(join7(out, "instructions.md"), instructions, "utf8");
1686
1747
  let scormSkillsSnapshotRef = input.scormSkills?.snapshotRef;
1687
1748
  if (input.targets.some((t) => t.startsWith("scorm"))) {
1688
1749
  const snap = await writeScormSkillsSnapshot(out, {
@@ -1691,13 +1752,19 @@ function createHandoffProducer() {
1691
1752
  });
1692
1753
  scormSkillsSnapshotRef = snap.ref;
1693
1754
  }
1694
- logger.debug({ outputDir: out, prompts: prompts.length }, "Agent handoff produced");
1755
+ const scorm = isScormTargeted2(input.targets);
1756
+ const claudeCommandPath = await writeClaudeCommand(dirname2(out), { scorm, scormSkills: scorm });
1757
+ logger.debug(
1758
+ { outputDir: out, prompts: prompts.length, claudeCommandPath },
1759
+ "Agent handoff produced"
1760
+ );
1695
1761
  return {
1696
1762
  spec,
1697
1763
  prompts,
1698
1764
  instructions,
1699
1765
  scormSkillsSnapshotRef,
1700
- producedBy: VERSION
1766
+ producedBy: VERSION,
1767
+ claudeCommandPath
1701
1768
  };
1702
1769
  }
1703
1770
  };
@@ -1815,13 +1882,13 @@ function renderInstructions(input) {
1815
1882
  }
1816
1883
 
1817
1884
  // src/adapters/framework/webcomponents/index.ts
1818
- import { mkdir as mkdir5, writeFile as writeFile5, cp, access as access3 } from "node:fs/promises";
1819
- import { join as join8 } from "node:path";
1885
+ import { mkdir as mkdir6, writeFile as writeFile6, cp, access as access3 } from "node:fs/promises";
1886
+ import { join as join9 } from "node:path";
1820
1887
 
1821
1888
  // src/preview/server.ts
1822
1889
  import { createServer } from "node:http";
1823
1890
  import { readFile as readFile5, stat } from "node:fs/promises";
1824
- import { join as join7, normalize, extname as extname2 } from "node:path";
1891
+ import { join as join8, normalize, extname as extname2 } from "node:path";
1825
1892
 
1826
1893
  // src/preview/mock-lms/index.ts
1827
1894
  function mockLmsBrowserScript() {
@@ -1877,13 +1944,13 @@ async function startPreviewServer(opts) {
1877
1944
  res.writeHead(200, { "content-type": MIME[".js"] }).end(mockLmsBrowserScript());
1878
1945
  return;
1879
1946
  }
1880
- const safe = normalize(join7(root, rel === "/" ? "index.html" : `.${rel}`));
1947
+ const safe = normalize(join8(root, rel === "/" ? "index.html" : `.${rel}`));
1881
1948
  if (!safe.startsWith(root)) {
1882
1949
  res.writeHead(403).end("Forbidden");
1883
1950
  return;
1884
1951
  }
1885
1952
  const info = await stat(safe).catch(() => null);
1886
- const file = info?.isDirectory() ? join7(safe, "index.html") : safe;
1953
+ const file = info?.isDirectory() ? join8(safe, "index.html") : safe;
1887
1954
  const isHtml = extname2(file) === ".html";
1888
1955
  if (opts.mockLms && isHtml) {
1889
1956
  const html = await readFile5(file, "utf8");
@@ -1930,21 +1997,21 @@ var webComponentsAdapter = {
1930
1997
  version: "0.1.0",
1931
1998
  optionsSchema: { type: "object", additionalProperties: true },
1932
1999
  async scaffold(input) {
1933
- await mkdir5(input.outputDir, { recursive: true });
2000
+ await mkdir6(input.outputDir, { recursive: true });
1934
2001
  const files = [];
1935
- const configPath = join8(input.outputDir, "elearning.scaffold.json");
1936
- await writeFile5(
2002
+ const configPath = join9(input.outputDir, "elearning.scaffold.json");
2003
+ await writeFile6(
1937
2004
  configPath,
1938
2005
  JSON.stringify({ adapter: this.id, packageId: input.package.id }, null, 2),
1939
2006
  "utf8"
1940
2007
  );
1941
2008
  files.push(configPath);
1942
- const contractPath = join8(input.outputDir, "AGENT_IMPLEMENTATION.md");
1943
- await writeFile5(contractPath, IMPLEMENTATION_CONTRACT, "utf8");
2009
+ const contractPath = join9(input.outputDir, "AGENT_IMPLEMENTATION.md");
2010
+ await writeFile6(contractPath, IMPLEMENTATION_CONTRACT, "utf8");
1944
2011
  files.push(contractPath);
1945
- const generated = join8(input.outputDir, "generated");
1946
- await mkdir5(generated, { recursive: true });
1947
- const seed = join8(generated, "index.html");
2012
+ const generated = join9(input.outputDir, "generated");
2013
+ await mkdir6(generated, { recursive: true });
2014
+ const seed = join9(generated, "index.html");
1948
2015
  const preserved = [];
1949
2016
  const overwritten = [];
1950
2017
  const seedExists = await exists(seed);
@@ -1952,7 +2019,7 @@ var webComponentsAdapter = {
1952
2019
  preserved.push(seed);
1953
2020
  logger.debug({ file: seed }, "Preserved existing generated/ file (use force to overwrite)");
1954
2021
  } else {
1955
- await writeFile5(seed, "<!doctype html><title>elearning package</title>", "utf8");
2022
+ await writeFile6(seed, "<!doctype html><title>elearning package</title>", "utf8");
1956
2023
  files.push(seed);
1957
2024
  if (seedExists) {
1958
2025
  overwritten.push(seed);
@@ -1966,7 +2033,7 @@ var webComponentsAdapter = {
1966
2033
  return { files, implementationContract: IMPLEMENTATION_CONTRACT, preserved, overwritten };
1967
2034
  },
1968
2035
  async build(input) {
1969
- await mkdir5(input.outputDir, { recursive: true });
2036
+ await mkdir6(input.outputDir, { recursive: true });
1970
2037
  const source = input.generatedDir;
1971
2038
  if (source && await exists(source)) {
1972
2039
  await cp(source, input.outputDir, { recursive: true });
@@ -2080,9 +2147,10 @@ function register11(program) {
2080
2147
  scormLibraryVersion: project.manifest?.scormLibraryVersion,
2081
2148
  frameworkContract: webComponentsAdapter.displayName,
2082
2149
  targets: opts.target,
2083
- outputDir: join9(dir, ".agent")
2150
+ outputDir: join10(dir, ".agent")
2084
2151
  });
2085
2152
  console.log(`Handoff materials written to .agent/ (${materials.prompts.length} prompts).`);
2153
+ console.log("Claude Code command written to .claude/commands/lxd-generate.md (run /project:lxd-generate).");
2086
2154
  const agnostic = checkHandoffAgnostic(`${materials.spec}
2087
2155
  ${materials.instructions}`);
2088
2156
  if (!agnostic.ok) {
@@ -2091,7 +2159,7 @@ ${materials.instructions}`);
2091
2159
  }
2092
2160
  }
2093
2161
  let force = Boolean(opts.force);
2094
- const seed = join9(dir, "generated", "index.html");
2162
+ const seed = join10(dir, "generated", "index.html");
2095
2163
  if (!force && await exists2(seed)) {
2096
2164
  if (process.stdin.isTTY) {
2097
2165
  const answer = await confirm({
@@ -2126,15 +2194,15 @@ ${materials.instructions}`);
2126
2194
  }
2127
2195
 
2128
2196
  // src/cli/commands/preview.ts
2129
- import { join as join10 } from "node:path";
2197
+ import { join as join11 } from "node:path";
2130
2198
  function register12(program) {
2131
2199
  program.command("preview").description("Build the package and serve it locally").option("--mock-lms", "serve in mock LMS/SCORM mode (US2)").option("-p, --port <n>", "port", "0").action(async (opts, cmd) => {
2132
2200
  const dir = cwdOf(cmd);
2133
2201
  const project = await loadProjectLenient(dir);
2134
2202
  const built = await webComponentsAdapter.build({
2135
2203
  package: project.package,
2136
- outputDir: join10(dir, "build"),
2137
- generatedDir: join10(dir, "generated")
2204
+ outputDir: join11(dir, "build"),
2205
+ generatedDir: join11(dir, "generated")
2138
2206
  });
2139
2207
  const handle = await startPreviewServer({
2140
2208
  dir: built.outputDir,
@@ -2148,7 +2216,7 @@ function register12(program) {
2148
2216
  }
2149
2217
 
2150
2218
  // src/cli/commands/export.ts
2151
- import { join as join13 } from "node:path";
2219
+ import { join as join14 } from "node:path";
2152
2220
 
2153
2221
  // src/core/authoring/export-builder.ts
2154
2222
  function buildExportConfig(targetIds) {
@@ -2181,7 +2249,7 @@ function createExportRegistry() {
2181
2249
  }
2182
2250
 
2183
2251
  // src/adapters/export/web/index.ts
2184
- import { mkdir as mkdir6, cp as cp2, access as access5 } from "node:fs/promises";
2252
+ import { mkdir as mkdir7, cp as cp2, access as access5 } from "node:fs/promises";
2185
2253
  var webExportAdapter = {
2186
2254
  id: "web",
2187
2255
  displayName: "Web / static package",
@@ -2203,7 +2271,7 @@ var webExportAdapter = {
2203
2271
  ];
2204
2272
  },
2205
2273
  async export(input) {
2206
- await mkdir6(input.outputDir, { recursive: true });
2274
+ await mkdir7(input.outputDir, { recursive: true });
2207
2275
  await cp2(input.builtDir, input.outputDir, { recursive: true });
2208
2276
  logger.debug({ outputDir: input.outputDir }, "web export complete");
2209
2277
  return { artifactPath: input.outputDir, target: "web", warnings: [] };
@@ -2211,8 +2279,8 @@ var webExportAdapter = {
2211
2279
  };
2212
2280
 
2213
2281
  // src/adapters/export/scorm12/index.ts
2214
- import { mkdir as mkdir7, cp as cp3, writeFile as writeFile6, access as access6 } from "node:fs/promises";
2215
- import { join as join11 } from "node:path";
2282
+ import { mkdir as mkdir8, cp as cp3, writeFile as writeFile7, access as access6 } from "node:fs/promises";
2283
+ import { join as join12 } from "node:path";
2216
2284
 
2217
2285
  // src/adapters/export/scorm-common.ts
2218
2286
  import archiver from "archiver";
@@ -2326,11 +2394,11 @@ var scorm12Adapter = {
2326
2394
  return results;
2327
2395
  },
2328
2396
  async export(input) {
2329
- await mkdir7(input.outputDir, { recursive: true });
2397
+ await mkdir8(input.outputDir, { recursive: true });
2330
2398
  await cp3(input.builtDir, input.outputDir, { recursive: true });
2331
- await writeFile6(join11(input.outputDir, "imsmanifest.xml"), buildImsManifest12(input.package), "utf8");
2332
- await writeFile6(
2333
- join11(input.outputDir, "scorm-runtime.json"),
2399
+ await writeFile7(join12(input.outputDir, "imsmanifest.xml"), buildImsManifest12(input.package), "utf8");
2400
+ await writeFile7(
2401
+ join12(input.outputDir, "scorm-runtime.json"),
2334
2402
  JSON.stringify(
2335
2403
  { library: "@studiolxd/scorm", version: input.assets.scormLibraryVersion ?? "unspecified", edition: "SCORM 1.2" },
2336
2404
  null,
@@ -2347,8 +2415,8 @@ var scorm12Adapter = {
2347
2415
  };
2348
2416
 
2349
2417
  // src/adapters/export/scorm2004/index.ts
2350
- import { mkdir as mkdir8, cp as cp4, writeFile as writeFile7, access as access7 } from "node:fs/promises";
2351
- import { join as join12 } from "node:path";
2418
+ import { mkdir as mkdir9, cp as cp4, writeFile as writeFile8, access as access7 } from "node:fs/promises";
2419
+ import { join as join13 } from "node:path";
2352
2420
  var scorm2004Adapter = {
2353
2421
  id: "scorm-2004",
2354
2422
  displayName: "SCORM 2004 (4th Edition)",
@@ -2380,11 +2448,11 @@ var scorm2004Adapter = {
2380
2448
  return results;
2381
2449
  },
2382
2450
  async export(input) {
2383
- await mkdir8(input.outputDir, { recursive: true });
2451
+ await mkdir9(input.outputDir, { recursive: true });
2384
2452
  await cp4(input.builtDir, input.outputDir, { recursive: true });
2385
- await writeFile7(join12(input.outputDir, "imsmanifest.xml"), buildImsManifest2004(input.package), "utf8");
2386
- await writeFile7(
2387
- join12(input.outputDir, "scorm-runtime.json"),
2453
+ await writeFile8(join13(input.outputDir, "imsmanifest.xml"), buildImsManifest2004(input.package), "utf8");
2454
+ await writeFile8(
2455
+ join13(input.outputDir, "scorm-runtime.json"),
2388
2456
  JSON.stringify(
2389
2457
  {
2390
2458
  library: "@studiolxd/scorm",
@@ -2426,8 +2494,8 @@ function register13(program) {
2426
2494
  }
2427
2495
  const built = await webComponentsAdapter.build({
2428
2496
  package: project.package,
2429
- outputDir: join13(dir, "build"),
2430
- generatedDir: join13(dir, "generated")
2497
+ outputDir: join14(dir, "build"),
2498
+ generatedDir: join14(dir, "generated")
2431
2499
  });
2432
2500
  for (const id of targets) {
2433
2501
  if (!registry.has(id)) {
@@ -2441,7 +2509,7 @@ function register13(program) {
2441
2509
  package: project.package,
2442
2510
  tracking: project.tracking,
2443
2511
  options: {},
2444
- outputDir: join13(dir, "dist", id),
2512
+ outputDir: join14(dir, "dist", id),
2445
2513
  assets: {
2446
2514
  scormLibraryVersion: manifest.scormLibraryVersion,
2447
2515
  scormSkillsSnapshotRef: manifest.scormSkillsSnapshot?.ref
@@ -2474,7 +2542,7 @@ function register14(program) {
2474
2542
  }
2475
2543
 
2476
2544
  // src/cli/commands/create.ts
2477
- import { join as join14, resolve as resolve5 } from "node:path";
2545
+ import { join as join15, resolve as resolve5 } from "node:path";
2478
2546
  import { rm } from "node:fs/promises";
2479
2547
 
2480
2548
  // src/cli/prompt.ts
@@ -2664,7 +2732,7 @@ async function runWizard(prompter, opts) {
2664
2732
  return result;
2665
2733
  }
2666
2734
  if (replacing) {
2667
- await rm(join14(targetDir, "experiences"), { recursive: true, force: true });
2735
+ await rm(join15(targetDir, "experiences"), { recursive: true, force: true });
2668
2736
  }
2669
2737
  await saveProject(targetDir, assembleProject(answers, design));
2670
2738
  result.committed = true;
@@ -2687,7 +2755,7 @@ async function runWizard(prompter, opts) {
2687
2755
  if (await need(prompter.confirm({ message: "Generate agent handoff now?", initialValue: false }))) {
2688
2756
  await produceHandoff(await loadProjectLenient(result.dir), {
2689
2757
  targets: answers.exportTargets,
2690
- outputDir: join14(result.dir, ".agent")
2758
+ outputDir: join15(result.dir, ".agent")
2691
2759
  });
2692
2760
  result.handoffGenerated = true;
2693
2761
  console.log("Handoff materials written to .agent/.");
package/docs/commands.md CHANGED
@@ -19,7 +19,7 @@ revisitable.
19
19
  | `design -l <level> [-b <brief>] [--a11y <t...>] [--from <file>]` | 6 | Design direction (brief → full constraints). |
20
20
  | `evaluation -c <rule> [--assessed --pass-threshold <n>]` | 7 | Feedback + package completion/score rules. |
21
21
  | `tracking [--completion-rule] [--score-rule] [--report <fields...>] [--threshold <n>]` | 8 | Experience signals + package roll-up. |
22
- | `handoff [-t <targets...>] [-f]` | 9 | Generate `.agent/**` specs/prompts/instructions (full instructional context per experience: purpose, scenario, mechanic guidance + plugin enrichment, feedback, tracking; audience + package tone; source-of-truth instruction); scaffold `generated/`. |
22
+ | `handoff [-t <targets...>] [-f]` | 9 | Generate `.agent/**` specs/prompts/instructions (full instructional context per experience: purpose, scenario, mechanic guidance + plugin enrichment, feedback, tracking; audience + package tone; source-of-truth instruction); scaffold `generated/`. Also writes a Claude Code convenience command at `.claude/commands/lxd-generate.md` (run `/project:lxd-generate`) — operational only; `.agent/` stays the source of truth. Generic `.agent/` materials are unchanged for non-Claude agents. |
23
23
  | *(your agent)* | 10 | Run YOUR AI coding agent against `.agent/**` to produce `generated/`. |
24
24
  | `preview [--mock-lms] [-p <port>]` | 11 | Build + serve locally; optional mock LMS/SCORM mode. |
25
25
  | `validate [--json]` | 12 | Run all validation checks on demand. For SCORM-targeted packages, **fails** if `generated/` hand-rolls a SCORM runtime instead of using `@studiolxd/scorm` (`no-custom-scorm-runtime`). |
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@studiolxd/lxd-cli",
3
- "version": "0.1.0-next.0",
3
+ "version": "0.1.0-next.1",
4
4
  "description": "CLI-first authoring tool for AI-native elearning packages (agent-orchestrated, framework- and export-target-agnostic).",
5
5
  "type": "module",
6
6
  "license": "UNLICENSED",
@@ -8,7 +8,7 @@
8
8
  "node": ">=20"
9
9
  },
10
10
  "bin": {
11
- "lxd": "./dist/cli/index.js"
11
+ "lxd": "dist/cli/index.js"
12
12
  },
13
13
  "files": [
14
14
  "dist",