asdm-cli 0.1.2 → 0.1.3

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
@@ -19,7 +19,8 @@ npm install -g asdm-cli
19
19
  asdm init --registry github://your-org/asdm-registry --profile fullstack-engineer
20
20
 
21
21
  # 3. Sync agents, skills, and commands from the registry
22
- asdm sync
22
+ asdm sync # project-local (inside current directory)
23
+ asdm sync --global # install to global provider config dirs
23
24
  ```
24
25
 
25
26
  That's it. ASDM will download your team's canonical AI assistant configurations and emit them into the correct locations for every provider your project uses — OpenCode, Claude Code, and GitHub Copilot — all from a single command.
@@ -113,6 +114,7 @@ Download agents, skills, and commands from the registry and emit them for all co
113
114
 
114
115
  ```bash
115
116
  asdm sync # full sync for all providers
117
+ asdm sync --global # install to global provider config directories
116
118
  asdm sync --provider opencode # sync only OpenCode files
117
119
  asdm sync --force # re-download everything (ignore cache)
118
120
  asdm sync --dry-run # preview changes without writing files
@@ -121,6 +123,7 @@ asdm sync --verbose # detailed output
121
123
 
122
124
  | Option | Description |
123
125
  |--------|-------------|
126
+ | `--global` | Install to global provider config dirs (`~/.config/opencode/`, `~/.claude/`, etc.) instead of project-local folders |
124
127
  | `--provider <name>` | Sync only for `opencode`, `claude-code`, or `copilot` |
125
128
  | `--force` | Re-download all assets, bypassing the local cache |
126
129
  | `--dry-run` | Show what would change without writing anything |
@@ -361,6 +364,8 @@ Generated by `asdm sync`. Records the exact SHA-256 of every emitted file and th
361
364
  - **Incremental sync** — only re-download changed assets
362
365
  - **Audit trail** — full history via git blame
363
366
 
367
+ > In global mode (`asdm sync --global`), the lockfile is stored at `~/.config/asdm/global-lock.json`.
368
+
364
369
  ### Configuration Layers
365
370
 
366
371
  Config is resolved in three layers (highest precedence wins for non-locked fields):
@@ -556,6 +561,39 @@ ASDM emits files in each provider's native format. You never write provider-spec
556
561
 
557
562
  ---
558
563
 
564
+ ## Global Installation
565
+
566
+ Use `asdm sync --global` to install agents, skills, and commands into the global config directories of each provider. This makes your AI assistant configuration available in **every project** without per-project setup.
567
+
568
+ ```bash
569
+ asdm init # initialize once (uses github://lennonalvesdias/asdm by default)
570
+ asdm sync --global # install to global provider dirs
571
+ asdm verify --global # verify global installation integrity
572
+ ```
573
+
574
+ ### Global config directories
575
+
576
+ | Provider | macOS / Linux | Windows |
577
+ |----------|--------------|---------|
578
+ | OpenCode | `~/.config/opencode/` | `%APPDATA%\opencode\` |
579
+ | Claude Code | `~/.claude/` | `%APPDATA%\Claude\` |
580
+ | GitHub Copilot | `~/.config/github-copilot/` | `%APPDATA%\GitHub Copilot\` |
581
+
582
+ ### How it works
583
+
584
+ In global mode, ASDM strips the provider-specific prefix from each file path and writes directly to the provider's global config directory:
585
+
586
+ ```
587
+ .opencode/agents/code-reviewer.md → ~/.config/opencode/agents/code-reviewer.md
588
+ .claude/agents/code-reviewer.md → ~/.claude/agents/code-reviewer.md
589
+ ```
590
+
591
+ Project-root files (`AGENTS.md`, `CLAUDE.md`) are skipped in global mode — they have no meaningful global equivalent.
592
+
593
+ The global lockfile is stored at `~/.config/asdm/global-lock.json`, separate from any project's `.asdm-lock.json`.
594
+
595
+ ---
596
+
559
597
  ## Integrity & Governance
560
598
 
561
599
  ### How Integrity Works
package/dist/index.mjs CHANGED
@@ -17,11 +17,13 @@ __export(fs_exports, {
17
17
  exists: () => exists,
18
18
  getAsdmCacheDir: () => getAsdmCacheDir,
19
19
  getAsdmConfigDir: () => getAsdmConfigDir,
20
+ getGlobalLockfilePath: () => getGlobalLockfilePath,
20
21
  listFiles: () => listFiles,
21
22
  normalizePath: () => normalizePath,
22
23
  readFile: () => readFile,
23
24
  readJson: () => readJson,
24
25
  removeFile: () => removeFile,
26
+ resolveGlobalEmitPath: () => resolveGlobalEmitPath,
25
27
  writeFile: () => writeFile,
26
28
  writeJson: () => writeJson
27
29
  });
@@ -80,6 +82,17 @@ async function listFiles(dirPath) {
80
82
  function getAsdmConfigDir() {
81
83
  return path.join(os.homedir(), ".config", "asdm");
82
84
  }
85
+ function resolveGlobalEmitPath(relativePath, provider) {
86
+ const prefix = PROVIDER_PATH_PREFIXES[provider];
87
+ const globalDir = PROVIDER_GLOBAL_DIRS[provider];
88
+ if (!prefix || !globalDir) return null;
89
+ if (!relativePath.startsWith(prefix)) return null;
90
+ const stripped = relativePath.slice(prefix.length);
91
+ return path.join(globalDir, stripped);
92
+ }
93
+ function getGlobalLockfilePath() {
94
+ return path.join(getAsdmConfigDir(), "global-lock.json");
95
+ }
83
96
  function getAsdmCacheDir() {
84
97
  const xdgCache = process.env["XDG_CACHE_HOME"];
85
98
  if (xdgCache) return path.join(xdgCache, "asdm");
@@ -97,9 +110,20 @@ async function copyFile(src, dest) {
97
110
  await ensureDir(path.dirname(dest));
98
111
  await fs.copyFile(src, dest);
99
112
  }
113
+ var PROVIDER_GLOBAL_DIRS, PROVIDER_PATH_PREFIXES;
100
114
  var init_fs = __esm({
101
115
  "src/utils/fs.ts"() {
102
116
  "use strict";
117
+ PROVIDER_GLOBAL_DIRS = {
118
+ opencode: process.platform === "win32" ? path.join(os.homedir(), "AppData", "Roaming", "opencode") : path.join(os.homedir(), ".config", "opencode"),
119
+ "claude-code": process.platform === "win32" ? path.join(os.homedir(), "AppData", "Roaming", "Claude") : path.join(os.homedir(), ".claude"),
120
+ copilot: process.platform === "win32" ? path.join(os.homedir(), "AppData", "Roaming", "GitHub Copilot") : path.join(os.homedir(), ".config", "github-copilot")
121
+ };
122
+ PROVIDER_PATH_PREFIXES = {
123
+ opencode: ".opencode/",
124
+ "claude-code": ".claude/",
125
+ copilot: ".github/"
126
+ };
103
127
  }
104
128
  });
105
129
 
@@ -755,7 +779,7 @@ var TelemetryWriter = class {
755
779
  const fullEvent = {
756
780
  timestamp: (/* @__PURE__ */ new Date()).toISOString(),
757
781
  machineId: machineId(),
758
- version: "0.1.2",
782
+ version: "0.1.3",
759
783
  ...event
760
784
  };
761
785
  const line = JSON.stringify(fullEvent) + "\n";
@@ -1264,13 +1288,13 @@ async function loadCachedManifest(cacheDir) {
1264
1288
  // src/core/lockfile.ts
1265
1289
  init_fs();
1266
1290
  import path7 from "path";
1267
- var LOCKFILE_NAME = ".asdm-lock.json";
1268
- async function readLockfile(cwd) {
1269
- const filePath = path7.join(cwd, LOCKFILE_NAME);
1291
+ var LOCKFILE_FILENAME = ".asdm-lock.json";
1292
+ async function readLockfile(cwd, lockfilePath) {
1293
+ const filePath = lockfilePath ?? path7.join(cwd, LOCKFILE_FILENAME);
1270
1294
  return readJson(filePath);
1271
1295
  }
1272
- async function writeLockfile(cwd, lockfile) {
1273
- const filePath = path7.join(cwd, LOCKFILE_NAME);
1296
+ async function writeLockfile(cwd, lockfile, lockfilePath) {
1297
+ const filePath = lockfilePath ?? path7.join(cwd, LOCKFILE_FILENAME);
1274
1298
  await writeJson(filePath, {
1275
1299
  $schema: "https://asdm.dev/schemas/lock.schema.json",
1276
1300
  ...lockfile
@@ -1378,7 +1402,7 @@ async function loadAdapters(providers) {
1378
1402
  return adapters;
1379
1403
  }
1380
1404
  async function getCliVersion() {
1381
- return "0.1.2";
1405
+ return "0.1.3";
1382
1406
  }
1383
1407
  async function sync(options) {
1384
1408
  const startTime = Date.now();
@@ -1399,7 +1423,8 @@ async function sync(options) {
1399
1423
  resolvedProfile.skills,
1400
1424
  resolvedProfile.commands
1401
1425
  );
1402
- const existingLockfile = options.force ? null : await readLockfile(cwd);
1426
+ const lockfilePath = options.global ? getGlobalLockfilePath() : void 0;
1427
+ const existingLockfile = options.force ? null : await readLockfile(cwd, lockfilePath);
1403
1428
  const localSourceShas = {};
1404
1429
  if (existingLockfile) {
1405
1430
  for (const [, entry] of Object.entries(existingLockfile.files)) {
@@ -1493,12 +1518,21 @@ async function sync(options) {
1493
1518
  const configFiles = adapter.emitConfig(resolvedProfile, cwd);
1494
1519
  allEmittedFiles.push(...configFiles);
1495
1520
  }
1521
+ const resolvedPaths = /* @__PURE__ */ new Map();
1496
1522
  for (const emittedFile of allEmittedFiles) {
1497
- const absolutePath = path11.join(cwd, emittedFile.relativePath);
1523
+ const absolutePath = options.global ? resolveGlobalEmitPath(emittedFile.relativePath, emittedFile.adapter) : path11.join(cwd, emittedFile.relativePath);
1524
+ if (absolutePath !== null) {
1525
+ resolvedPaths.set(emittedFile.relativePath, absolutePath);
1526
+ }
1527
+ }
1528
+ for (const emittedFile of allEmittedFiles) {
1529
+ const absolutePath = resolvedPaths.get(emittedFile.relativePath);
1530
+ if (absolutePath === void 0) continue;
1498
1531
  await writeFile(absolutePath, emittedFile.content);
1499
1532
  }
1500
1533
  const lockfileFiles = {};
1501
1534
  for (const emittedFile of allEmittedFiles) {
1535
+ if (!resolvedPaths.has(emittedFile.relativePath)) continue;
1502
1536
  lockfileFiles[emittedFile.relativePath] = createLockEntry(
1503
1537
  emittedFile.sha256,
1504
1538
  emittedFile.sourcePath,
@@ -1515,7 +1549,7 @@ async function sync(options) {
1515
1549
  resolvedProfiles: resolvedProfile.resolvedFrom,
1516
1550
  files: lockfileFiles
1517
1551
  });
1518
- await writeLockfile(cwd, lockfile);
1552
+ await writeLockfile(cwd, lockfile, lockfilePath);
1519
1553
  const stats = {
1520
1554
  filesAdded: diff.added.length,
1521
1555
  filesUpdated: diff.updated.length,
@@ -1571,6 +1605,11 @@ var sync_default = defineCommand2({
1571
1605
  provider: {
1572
1606
  type: "string",
1573
1607
  description: "Sync only for a specific provider"
1608
+ },
1609
+ global: {
1610
+ type: "boolean",
1611
+ description: "Install to global provider config directories instead of project-local folders",
1612
+ default: false
1574
1613
  }
1575
1614
  },
1576
1615
  async run(ctx) {
@@ -1590,6 +1629,7 @@ var sync_default = defineCommand2({
1590
1629
  dryRun,
1591
1630
  verbose,
1592
1631
  provider: ctx.args.provider,
1632
+ global: ctx.args.global ?? false,
1593
1633
  telemetry
1594
1634
  });
1595
1635
  const { stats } = result;
@@ -1635,8 +1675,9 @@ var VERIFY_EXIT_CODES = {
1635
1675
  NO_LOCK: 2,
1636
1676
  OUTDATED: 3
1637
1677
  };
1638
- async function verify(cwd, latestManifestVersion, onlyManaged = true, telemetry) {
1639
- const lockfile = await readLockfile(cwd);
1678
+ async function verify(cwd, latestManifestVersion, onlyManaged = true, telemetry, lockfilePath) {
1679
+ const lockfile = await readLockfile(cwd, lockfilePath);
1680
+ const isGlobal = lockfilePath !== void 0;
1640
1681
  if (!lockfile) {
1641
1682
  telemetry?.write({ event: "verify.failed" }).catch(() => {
1642
1683
  });
@@ -1650,7 +1691,7 @@ async function verify(cwd, latestManifestVersion, onlyManaged = true, telemetry)
1650
1691
  let checkedFiles = 0;
1651
1692
  const filesToCheck = onlyManaged ? Object.entries(lockfile.files).filter(([, entry]) => entry.managed) : Object.entries(lockfile.files);
1652
1693
  for (const [relativePath, entry] of filesToCheck) {
1653
- const absolutePath = path12.join(cwd, relativePath);
1694
+ const absolutePath = isGlobal ? resolveGlobalEmitPath(relativePath, entry.adapter) ?? path12.join(cwd, relativePath) : path12.join(cwd, relativePath);
1654
1695
  checkedFiles++;
1655
1696
  const fileExists = await exists(absolutePath);
1656
1697
  if (!fileExists) {
@@ -1694,6 +1735,7 @@ async function verify(cwd, latestManifestVersion, onlyManaged = true, telemetry)
1694
1735
  }
1695
1736
 
1696
1737
  // src/cli/commands/verify.ts
1738
+ init_fs();
1697
1739
  var verify_default = defineCommand3({
1698
1740
  meta: {
1699
1741
  name: "verify",
@@ -1714,6 +1756,11 @@ var verify_default = defineCommand3({
1714
1756
  type: "boolean",
1715
1757
  description: "Suppress non-error output",
1716
1758
  default: false
1759
+ },
1760
+ global: {
1761
+ type: "boolean",
1762
+ description: "Verify files installed to global provider config directories",
1763
+ default: false
1717
1764
  }
1718
1765
  },
1719
1766
  async run(ctx) {
@@ -1722,8 +1769,9 @@ var verify_default = defineCommand3({
1722
1769
  const quiet = ctx.args.quiet;
1723
1770
  if (quiet) logger.setQuiet(true);
1724
1771
  const telemetry = new TelemetryWriter(cwd);
1772
+ const lockfilePath = ctx.args.global ? getGlobalLockfilePath() : void 0;
1725
1773
  if (ctx.args.strict) {
1726
- const result = await verify(cwd, void 0, true, telemetry);
1774
+ const result = await verify(cwd, void 0, true, telemetry, lockfilePath);
1727
1775
  if (useJson) {
1728
1776
  console.log(JSON.stringify({
1729
1777
  status: result.exitCode === VERIFY_EXIT_CODES.OK ? "ok" : "error",
@@ -1741,15 +1789,15 @@ var verify_default = defineCommand3({
1741
1789
  return;
1742
1790
  }
1743
1791
  try {
1744
- const result = await verify(cwd, void 0, true, telemetry);
1792
+ const result = await verify(cwd, void 0, true, telemetry, lockfilePath);
1745
1793
  if (useJson) {
1746
1794
  console.log(JSON.stringify(result, null, 2));
1747
1795
  process.exitCode = result.exitCode;
1748
1796
  return;
1749
1797
  }
1750
1798
  if (result.exitCode === VERIFY_EXIT_CODES.NO_LOCK) {
1751
- logger.warn("No lockfile found (.asdm-lock.json)");
1752
- logger.info("Run `asdm sync` to initialize");
1799
+ logger.warn(lockfilePath ? "No global lockfile found" : "No lockfile found (.asdm-lock.json)");
1800
+ logger.info(lockfilePath ? "Run `asdm sync --global` to initialize" : "Run `asdm sync` to initialize");
1753
1801
  process.exitCode = VERIFY_EXIT_CODES.NO_LOCK;
1754
1802
  return;
1755
1803
  }
@@ -2252,7 +2300,7 @@ var version_default = defineCommand10({
2252
2300
  description: "Print CLI version and environment info"
2253
2301
  },
2254
2302
  run(_ctx) {
2255
- console.log(`asdm v${"0.1.2"}`);
2303
+ console.log(`asdm v${"0.1.3"}`);
2256
2304
  console.log(`node ${process.version}`);
2257
2305
  console.log(`os ${os3.type()} ${os3.release()} (${process.platform})`);
2258
2306
  }
@@ -2495,7 +2543,7 @@ import path15 from "path";
2495
2543
  import { promises as fs5 } from "fs";
2496
2544
  import readline from "readline";
2497
2545
  init_fs();
2498
- var LOCKFILE_NAME2 = ".asdm-lock.json";
2546
+ var LOCKFILE_NAME = ".asdm-lock.json";
2499
2547
  async function getFileSizeBytes(filePath) {
2500
2548
  try {
2501
2549
  const stat = await fs5.stat(filePath);
@@ -2608,7 +2656,7 @@ var clean_default = defineCommand12({
2608
2656
  logger.bullet(`removed: ${relativePath}`);
2609
2657
  removed++;
2610
2658
  }
2611
- const lockfilePath = path15.join(cwd, LOCKFILE_NAME2);
2659
+ const lockfilePath = path15.join(cwd, LOCKFILE_NAME);
2612
2660
  const lockfileOnDisk = await exists(lockfilePath);
2613
2661
  if (target) {
2614
2662
  if (!dryRun && lockfileOnDisk) {
@@ -2616,19 +2664,19 @@ var clean_default = defineCommand12({
2616
2664
  Object.entries(lockfile.files).filter(([, entry]) => entry.adapter !== target)
2617
2665
  );
2618
2666
  await writeLockfile(cwd, { ...lockfile, files: updatedFiles });
2619
- logger.bullet(`updated: ${LOCKFILE_NAME2} (removed ${target} entries)`);
2667
+ logger.bullet(`updated: ${LOCKFILE_NAME} (removed ${target} entries)`);
2620
2668
  } else if (dryRun) {
2621
- logger.bullet(`would update: ${LOCKFILE_NAME2} (remove ${target} entries)`);
2669
+ logger.bullet(`would update: ${LOCKFILE_NAME} (remove ${target} entries)`);
2622
2670
  }
2623
2671
  } else {
2624
2672
  if (lockfileOnDisk) {
2625
2673
  if (dryRun) {
2626
- logger.bullet(`would remove: ${LOCKFILE_NAME2}`);
2674
+ logger.bullet(`would remove: ${LOCKFILE_NAME}`);
2627
2675
  } else {
2628
2676
  const lockfileSize = await getFileSizeBytes(lockfilePath);
2629
2677
  await removeFile(lockfilePath);
2630
2678
  totalBytesFreed += lockfileSize;
2631
- logger.bullet(`removed: ${LOCKFILE_NAME2}`);
2679
+ logger.bullet(`removed: ${LOCKFILE_NAME}`);
2632
2680
  }
2633
2681
  }
2634
2682
  }
@@ -2987,7 +3035,7 @@ async function checkForUpdate(currentVersion) {
2987
3035
  var rootCommand = defineCommand16({
2988
3036
  meta: {
2989
3037
  name: "asdm",
2990
- version: "0.1.2",
3038
+ version: "0.1.3",
2991
3039
  description: "Agentic Software Delivery Model \u2014 Write Once, Emit Many"
2992
3040
  },
2993
3041
  subCommands: {
@@ -3033,9 +3081,9 @@ async function main() {
3033
3081
  await runMain(rootCommand);
3034
3082
  if (process.exitCode !== void 0 && process.exitCode !== 0) return;
3035
3083
  try {
3036
- const latestVersion = await checkForUpdate("0.1.2");
3084
+ const latestVersion = await checkForUpdate("0.1.3");
3037
3085
  if (latestVersion) {
3038
- printUpdateBox("0.1.2", latestVersion);
3086
+ printUpdateBox("0.1.3", latestVersion);
3039
3087
  }
3040
3088
  } catch {
3041
3089
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "asdm-cli",
3
- "version": "0.1.2",
3
+ "version": "0.1.3",
4
4
  "description": "Agentic Software Delivery Model — CLI for unified AI coding assistant governance",
5
5
  "type": "module",
6
6
  "bin": {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "$schema": "https://asdm.dev/schemas/manifest.schema.json",
3
- "version": "0.1.2",
3
+ "version": "0.1.3",
4
4
  "policy": {
5
5
  "locked_fields": [
6
6
  "telemetry",
@@ -22,7 +22,7 @@
22
22
  "claude-code",
23
23
  "copilot"
24
24
  ],
25
- "min_cli_version": "0.1.2"
25
+ "min_cli_version": "0.1.3"
26
26
  },
27
27
  "profiles": {
28
28
  "base": {
@@ -0,0 +1,253 @@
1
+ {
2
+ "$schema": "https://asdm.dev/schemas/manifest.schema.json",
3
+ "version": "0.1.3",
4
+ "policy": {
5
+ "locked_fields": [
6
+ "telemetry",
7
+ "install_hooks",
8
+ "auto_verify"
9
+ ],
10
+ "telemetry": true,
11
+ "auto_verify": true,
12
+ "install_hooks": true,
13
+ "allowed_profiles": [
14
+ "base",
15
+ "fullstack-engineer",
16
+ "data-analytics",
17
+ "mobile",
18
+ "security"
19
+ ],
20
+ "allowed_providers": [
21
+ "opencode",
22
+ "claude-code",
23
+ "copilot"
24
+ ],
25
+ "min_cli_version": "0.1.3"
26
+ },
27
+ "profiles": {
28
+ "base": {
29
+ "agents": [
30
+ "code-reviewer",
31
+ "documentation-writer"
32
+ ],
33
+ "skills": [
34
+ "plan-protocol",
35
+ "code-review"
36
+ ],
37
+ "commands": [
38
+ "check-file",
39
+ "summarize"
40
+ ],
41
+ "providers": [
42
+ "opencode",
43
+ "claude-code",
44
+ "copilot"
45
+ ]
46
+ },
47
+ "data-analytics": {
48
+ "extends": [
49
+ "base"
50
+ ],
51
+ "agents": [
52
+ "code-reviewer",
53
+ "data-analyst",
54
+ "documentation-writer"
55
+ ],
56
+ "skills": [
57
+ "plan-protocol",
58
+ "code-review",
59
+ "data-pipeline"
60
+ ],
61
+ "commands": [
62
+ "check-file",
63
+ "summarize",
64
+ "analyze-schema"
65
+ ],
66
+ "providers": [
67
+ "opencode",
68
+ "claude-code",
69
+ "copilot"
70
+ ]
71
+ },
72
+ "fullstack-engineer": {
73
+ "extends": [
74
+ "base"
75
+ ],
76
+ "agents": [
77
+ "code-reviewer",
78
+ "documentation-writer",
79
+ "architect",
80
+ "test-engineer"
81
+ ],
82
+ "skills": [
83
+ "plan-protocol",
84
+ "code-review",
85
+ "frontend-design",
86
+ "api-design"
87
+ ],
88
+ "commands": [
89
+ "check-file",
90
+ "summarize",
91
+ "generate-types",
92
+ "scaffold-component"
93
+ ],
94
+ "providers": [
95
+ "opencode",
96
+ "claude-code",
97
+ "copilot"
98
+ ]
99
+ },
100
+ "mobile": {
101
+ "extends": [
102
+ "base"
103
+ ],
104
+ "agents": [
105
+ "code-reviewer",
106
+ "documentation-writer",
107
+ "mobile-engineer"
108
+ ],
109
+ "skills": [
110
+ "plan-protocol",
111
+ "code-review",
112
+ "mobile-patterns"
113
+ ],
114
+ "commands": [
115
+ "check-file",
116
+ "summarize",
117
+ "scaffold-component"
118
+ ],
119
+ "providers": [
120
+ "opencode",
121
+ "claude-code",
122
+ "copilot"
123
+ ]
124
+ },
125
+ "security": {
126
+ "extends": [
127
+ "base"
128
+ ],
129
+ "agents": [
130
+ "code-reviewer",
131
+ "security-auditor",
132
+ "documentation-writer"
133
+ ],
134
+ "skills": [
135
+ "plan-protocol",
136
+ "code-review",
137
+ "threat-modeling"
138
+ ],
139
+ "commands": [
140
+ "check-file",
141
+ "summarize",
142
+ "audit-deps"
143
+ ],
144
+ "providers": [
145
+ "opencode",
146
+ "claude-code",
147
+ "copilot"
148
+ ]
149
+ }
150
+ },
151
+ "assets": {
152
+ "agents/architect.asdm.md": {
153
+ "sha256": "cac0b010fd350f9d23bfbb090327dc2e8e971be9daafa764269619224c5ca742",
154
+ "size": 3011,
155
+ "version": "1.0.0"
156
+ },
157
+ "agents/code-reviewer.asdm.md": {
158
+ "sha256": "682c73710a84ad8c40e3d8548f82811390ce3db32c6f136116afcde7f87fc75d",
159
+ "size": 2911,
160
+ "version": "1.0.0"
161
+ },
162
+ "agents/data-analyst.asdm.md": {
163
+ "sha256": "bb0ce105b9dd19eaef3be5d6b76f5ad273b4b95057d3bb2c998acbaf3dfc7589",
164
+ "size": 2865,
165
+ "version": "1.0.0"
166
+ },
167
+ "agents/documentation-writer.asdm.md": {
168
+ "sha256": "05f22780898bdc7dc9e842caab967241b99e02ca7d43d30b09ca8d19fc85d63a",
169
+ "size": 2788,
170
+ "version": "1.0.0"
171
+ },
172
+ "agents/mobile-engineer.asdm.md": {
173
+ "sha256": "ab51f952dcc8ce72cf3f48359e11c30fc7a3f5b32b534e56b04ee47cd382c3bd",
174
+ "size": 2903,
175
+ "version": "1.0.0"
176
+ },
177
+ "agents/security-auditor.asdm.md": {
178
+ "sha256": "8285378a7b30009a02f537d9fc882344c50444c1c1fe1b0ff35b8e49e475b2eb",
179
+ "size": 3167,
180
+ "version": "1.0.0"
181
+ },
182
+ "agents/test-engineer.asdm.md": {
183
+ "sha256": "e23266b82c0e3ccb96d613167c3c27d88651ff159fcb8e9b8eaf34b125681278",
184
+ "size": 2811,
185
+ "version": "1.0.0"
186
+ },
187
+ "skills/api-design/SKILL.asdm.md": {
188
+ "sha256": "637fc8014c22ddd8fa9122a44eb68cef70ffecfed724e8535b8d7d54091c579c",
189
+ "size": 3506,
190
+ "version": "1.0.0"
191
+ },
192
+ "skills/code-review/SKILL.asdm.md": {
193
+ "sha256": "de2011667b7f9e5c07cef878d43e85bb2d9fa2109c4ba64e161b6038012fab20",
194
+ "size": 3112,
195
+ "version": "1.0.0"
196
+ },
197
+ "skills/data-pipeline/SKILL.asdm.md": {
198
+ "sha256": "35e45153c4eafc4f1654b46865a226509634b3659365b03e19de482d10233699",
199
+ "size": 3686,
200
+ "version": "1.0.0"
201
+ },
202
+ "skills/frontend-design/SKILL.asdm.md": {
203
+ "sha256": "9cdddedd6f2b6caa8bafb8f8fa9864b6473c89170c4feedd05aaa9f1a30a8d3f",
204
+ "size": 3267,
205
+ "version": "1.0.0"
206
+ },
207
+ "skills/mobile-patterns/SKILL.asdm.md": {
208
+ "sha256": "9f336da4b1979cbdadad95012a4347f0e9830597f60e98e9084d6a0d07459acd",
209
+ "size": 3561,
210
+ "version": "1.0.0"
211
+ },
212
+ "skills/plan-protocol/SKILL.asdm.md": {
213
+ "sha256": "c0226a04e91caedc6dd9b51946508b9c05c29b51aa3402217c176161c0e7a16c",
214
+ "size": 2781,
215
+ "version": "1.0.0"
216
+ },
217
+ "skills/threat-modeling/SKILL.asdm.md": {
218
+ "sha256": "255ec1cc1773315b994bff8f09e647750210bc34f233c5ff83053fb6568f67e5",
219
+ "size": 4256,
220
+ "version": "1.0.0"
221
+ },
222
+ "commands/analyze-schema.asdm.md": {
223
+ "sha256": "2c855b9b02257cecc71c5a03faa05da52e215df148aa141c9258db8e0d2b6174",
224
+ "size": 2538,
225
+ "version": "1.0.0"
226
+ },
227
+ "commands/audit-deps.asdm.md": {
228
+ "sha256": "b5d54e07d9596b996090aae8e83476fb2d53b62301dd3feef82facd3d08f7150",
229
+ "size": 2781,
230
+ "version": "1.0.0"
231
+ },
232
+ "commands/check-file.asdm.md": {
233
+ "sha256": "3090793fb1eb3484626f7a4c9569df87ff486586e2e3f4046c15749003a4af73",
234
+ "size": 1700,
235
+ "version": "1.0.0"
236
+ },
237
+ "commands/generate-types.asdm.md": {
238
+ "sha256": "d1b1401c495410ee68aedc055700cfb11794228d8f363bdf6463b75e58bdff20",
239
+ "size": 2259,
240
+ "version": "1.0.0"
241
+ },
242
+ "commands/scaffold-component.asdm.md": {
243
+ "sha256": "312cf07c16a44fe334037281213aed99d8410070acbfe35e6ae0968ec8a5263f",
244
+ "size": 2327,
245
+ "version": "1.0.0"
246
+ },
247
+ "commands/summarize.asdm.md": {
248
+ "sha256": "0f52ab9a25f6f802aa2a9025d8a4e9a5825aa04ba94173884bb189566ad07ad0",
249
+ "size": 1919,
250
+ "version": "1.0.0"
251
+ }
252
+ }
253
+ }