craftdesk 0.3.0 → 0.5.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 (215) hide show
  1. package/CHANGELOG.md +88 -0
  2. package/README.md +1609 -132
  3. package/dist/commands/add.d.ts +5 -0
  4. package/dist/commands/add.d.ts.map +1 -1
  5. package/dist/commands/add.js +306 -8
  6. package/dist/commands/add.js.map +1 -1
  7. package/dist/commands/convert.d.ts +8 -0
  8. package/dist/commands/convert.d.ts.map +1 -0
  9. package/dist/commands/convert.js +146 -0
  10. package/dist/commands/convert.js.map +1 -0
  11. package/dist/commands/detect-agents.d.ts +14 -0
  12. package/dist/commands/detect-agents.d.ts.map +1 -0
  13. package/dist/commands/detect-agents.js +86 -0
  14. package/dist/commands/detect-agents.js.map +1 -0
  15. package/dist/commands/embed.d.ts +14 -0
  16. package/dist/commands/embed.d.ts.map +1 -0
  17. package/dist/commands/embed.js +147 -0
  18. package/dist/commands/embed.js.map +1 -0
  19. package/dist/commands/info.d.ts +8 -0
  20. package/dist/commands/info.d.ts.map +1 -0
  21. package/dist/commands/info.js +66 -0
  22. package/dist/commands/info.js.map +1 -0
  23. package/dist/commands/init.d.ts +5 -0
  24. package/dist/commands/init.d.ts.map +1 -1
  25. package/dist/commands/init.js +8 -2
  26. package/dist/commands/init.js.map +1 -1
  27. package/dist/commands/install.d.ts +5 -0
  28. package/dist/commands/install.d.ts.map +1 -1
  29. package/dist/commands/install.js +24 -4
  30. package/dist/commands/install.js.map +1 -1
  31. package/dist/commands/list.d.ts +5 -0
  32. package/dist/commands/list.d.ts.map +1 -1
  33. package/dist/commands/list.js +75 -7
  34. package/dist/commands/list.js.map +1 -1
  35. package/dist/commands/login.d.ts +8 -0
  36. package/dist/commands/login.d.ts.map +1 -0
  37. package/dist/commands/login.js +158 -0
  38. package/dist/commands/login.js.map +1 -0
  39. package/dist/commands/logout.d.ts +8 -0
  40. package/dist/commands/logout.d.ts.map +1 -0
  41. package/dist/commands/logout.js +51 -0
  42. package/dist/commands/logout.js.map +1 -0
  43. package/dist/commands/outdated.d.ts +23 -0
  44. package/dist/commands/outdated.d.ts.map +1 -0
  45. package/dist/commands/outdated.js +268 -0
  46. package/dist/commands/outdated.js.map +1 -0
  47. package/dist/commands/publish.d.ts +8 -0
  48. package/dist/commands/publish.d.ts.map +1 -0
  49. package/dist/commands/publish.js +203 -0
  50. package/dist/commands/publish.js.map +1 -0
  51. package/dist/commands/remove.d.ts +5 -0
  52. package/dist/commands/remove.d.ts.map +1 -1
  53. package/dist/commands/remove.js +51 -10
  54. package/dist/commands/remove.js.map +1 -1
  55. package/dist/commands/search.d.ts +8 -0
  56. package/dist/commands/search.d.ts.map +1 -0
  57. package/dist/commands/search.js +60 -0
  58. package/dist/commands/search.js.map +1 -0
  59. package/dist/commands/setup-multi-agent.d.ts +17 -0
  60. package/dist/commands/setup-multi-agent.d.ts.map +1 -0
  61. package/dist/commands/setup-multi-agent.js +188 -0
  62. package/dist/commands/setup-multi-agent.js.map +1 -0
  63. package/dist/commands/sync.d.ts +14 -0
  64. package/dist/commands/sync.d.ts.map +1 -0
  65. package/dist/commands/sync.js +144 -0
  66. package/dist/commands/sync.js.map +1 -0
  67. package/dist/commands/unembed.d.ts +14 -0
  68. package/dist/commands/unembed.d.ts.map +1 -0
  69. package/dist/commands/unembed.js +96 -0
  70. package/dist/commands/unembed.js.map +1 -0
  71. package/dist/commands/update.d.ts +8 -0
  72. package/dist/commands/update.d.ts.map +1 -0
  73. package/dist/commands/update.js +372 -0
  74. package/dist/commands/update.js.map +1 -0
  75. package/dist/commands/verify.d.ts +14 -0
  76. package/dist/commands/verify.d.ts.map +1 -0
  77. package/dist/commands/verify.js +143 -0
  78. package/dist/commands/verify.js.map +1 -0
  79. package/dist/commands/whoami.d.ts +8 -0
  80. package/dist/commands/whoami.d.ts.map +1 -0
  81. package/dist/commands/whoami.js +58 -0
  82. package/dist/commands/whoami.js.map +1 -0
  83. package/dist/converters/base-converter.d.ts +89 -0
  84. package/dist/converters/base-converter.d.ts.map +1 -0
  85. package/dist/converters/base-converter.js +249 -0
  86. package/dist/converters/base-converter.js.map +1 -0
  87. package/dist/converters/continue-converter.d.ts +53 -0
  88. package/dist/converters/continue-converter.d.ts.map +1 -0
  89. package/dist/converters/continue-converter.js +243 -0
  90. package/dist/converters/continue-converter.js.map +1 -0
  91. package/dist/converters/cursor-converter.d.ts +70 -0
  92. package/dist/converters/cursor-converter.d.ts.map +1 -0
  93. package/dist/converters/cursor-converter.js +272 -0
  94. package/dist/converters/cursor-converter.js.map +1 -0
  95. package/dist/index.js +56 -3
  96. package/dist/index.js.map +1 -1
  97. package/dist/services/agent-detector.d.ts +57 -0
  98. package/dist/services/agent-detector.d.ts.map +1 -0
  99. package/dist/services/agent-detector.js +146 -0
  100. package/dist/services/agent-detector.js.map +1 -0
  101. package/dist/services/config-manager.d.ts +128 -10
  102. package/dist/services/config-manager.d.ts.map +1 -1
  103. package/dist/services/config-manager.js +190 -18
  104. package/dist/services/config-manager.js.map +1 -1
  105. package/dist/services/converter.d.ts +53 -0
  106. package/dist/services/converter.d.ts.map +1 -0
  107. package/dist/services/converter.js +185 -0
  108. package/dist/services/converter.js.map +1 -0
  109. package/dist/services/craft-wrapper.d.ts +108 -0
  110. package/dist/services/craft-wrapper.d.ts.map +1 -0
  111. package/dist/services/craft-wrapper.js +268 -0
  112. package/dist/services/craft-wrapper.js.map +1 -0
  113. package/dist/services/git-resolver.d.ts +9 -3
  114. package/dist/services/git-resolver.d.ts.map +1 -1
  115. package/dist/services/git-resolver.js +44 -20
  116. package/dist/services/git-resolver.js.map +1 -1
  117. package/dist/services/gitignore-manager.d.ts +74 -0
  118. package/dist/services/gitignore-manager.d.ts.map +1 -0
  119. package/dist/services/gitignore-manager.js +188 -0
  120. package/dist/services/gitignore-manager.js.map +1 -0
  121. package/dist/services/installer.d.ts +60 -1
  122. package/dist/services/installer.d.ts.map +1 -1
  123. package/dist/services/installer.js +295 -20
  124. package/dist/services/installer.js.map +1 -1
  125. package/dist/services/multi-agent-sync.d.ts +88 -0
  126. package/dist/services/multi-agent-sync.d.ts.map +1 -0
  127. package/dist/services/multi-agent-sync.js +316 -0
  128. package/dist/services/multi-agent-sync.js.map +1 -0
  129. package/dist/services/plugin-resolver.d.ts +80 -0
  130. package/dist/services/plugin-resolver.d.ts.map +1 -0
  131. package/dist/services/plugin-resolver.js +183 -0
  132. package/dist/services/plugin-resolver.js.map +1 -0
  133. package/dist/services/registry-client.d.ts +132 -5
  134. package/dist/services/registry-client.d.ts.map +1 -1
  135. package/dist/services/registry-client.js +239 -34
  136. package/dist/services/registry-client.js.map +1 -1
  137. package/dist/services/settings-manager.d.ts +151 -0
  138. package/dist/services/settings-manager.d.ts.map +1 -0
  139. package/dist/services/settings-manager.js +333 -0
  140. package/dist/services/settings-manager.js.map +1 -0
  141. package/dist/types/claude-settings.d.ts +155 -0
  142. package/dist/types/claude-settings.d.ts.map +1 -0
  143. package/dist/types/claude-settings.js +20 -0
  144. package/dist/types/claude-settings.js.map +1 -0
  145. package/dist/types/converter.d.ts +98 -0
  146. package/dist/types/converter.d.ts.map +1 -0
  147. package/dist/types/converter.js +6 -0
  148. package/dist/types/converter.js.map +1 -0
  149. package/dist/types/craftdesk-json.d.ts +76 -3
  150. package/dist/types/craftdesk-json.d.ts.map +1 -1
  151. package/dist/types/craftdesk-lock.d.ts +62 -1
  152. package/dist/types/craftdesk-lock.d.ts.map +1 -1
  153. package/dist/types/multi-agent.d.ts +85 -0
  154. package/dist/types/multi-agent.d.ts.map +1 -0
  155. package/dist/types/multi-agent.js +6 -0
  156. package/dist/types/multi-agent.js.map +1 -0
  157. package/dist/utils/crypto.d.ts +23 -0
  158. package/dist/utils/crypto.d.ts.map +1 -0
  159. package/dist/utils/crypto.js +52 -0
  160. package/dist/utils/crypto.js.map +1 -0
  161. package/dist/utils/file-system.d.ts +43 -0
  162. package/dist/utils/file-system.d.ts.map +1 -1
  163. package/dist/utils/file-system.js +45 -2
  164. package/dist/utils/file-system.js.map +1 -1
  165. package/dist/utils/logger.d.ts +75 -0
  166. package/dist/utils/logger.d.ts.map +1 -1
  167. package/dist/utils/logger.js +76 -1
  168. package/dist/utils/logger.js.map +1 -1
  169. package/dist/utils/version-utils.d.ts +63 -0
  170. package/dist/utils/version-utils.d.ts.map +1 -0
  171. package/dist/utils/version-utils.js +130 -0
  172. package/dist/utils/version-utils.js.map +1 -0
  173. package/package.json +36 -9
  174. package/.claude/settings.local.json +0 -19
  175. package/.github/workflows/ci.yml +0 -94
  176. package/API.md +0 -414
  177. package/TESTING.md +0 -263
  178. package/dist/commands/config.d.ts +0 -3
  179. package/dist/commands/config.d.ts.map +0 -1
  180. package/dist/commands/config.js +0 -56
  181. package/dist/commands/config.js.map +0 -1
  182. package/dist/types/config.d.ts +0 -17
  183. package/dist/types/config.d.ts.map +0 -1
  184. package/dist/types/config.js +0 -3
  185. package/dist/types/config.js.map +0 -1
  186. package/docs/DEPENDENCY_RESOLUTION.md +0 -237
  187. package/examples/craftdesk-all-sources.json +0 -79
  188. package/examples/craftdesk-git-monorepo.json +0 -41
  189. package/examples/craftdesk-multi-registry.json +0 -40
  190. package/examples/craftdesk-with-registries.json +0 -49
  191. package/examples/simple-craftdesk.json +0 -10
  192. package/src/commands/add.ts +0 -314
  193. package/src/commands/init.ts +0 -55
  194. package/src/commands/install.ts +0 -126
  195. package/src/commands/list.ts +0 -126
  196. package/src/commands/remove.ts +0 -82
  197. package/src/index.ts +0 -56
  198. package/src/services/config-manager.ts +0 -150
  199. package/src/services/git-resolver.ts +0 -373
  200. package/src/services/installer.ts +0 -314
  201. package/src/services/registry-client.ts +0 -163
  202. package/src/types/craftdesk-json.ts +0 -53
  203. package/src/types/craftdesk-lock.ts +0 -38
  204. package/src/utils/file-system.ts +0 -55
  205. package/src/utils/logger.ts +0 -82
  206. package/tests/fixtures/craftdesk-git.json +0 -17
  207. package/tests/fixtures/craftdesk.json +0 -15
  208. package/tests/helpers/test-utils.ts +0 -60
  209. package/tests/integration/init-command.test.ts +0 -70
  210. package/tests/integration/list-command.test.ts +0 -77
  211. package/tests/unit/config-manager.test.ts +0 -228
  212. package/tests/unit/git-resolver.test.ts +0 -303
  213. package/tests/unit/installer.test.ts +0 -105
  214. package/tsconfig.json +0 -20
  215. package/vitest.config.ts +0 -29
@@ -1,126 +0,0 @@
1
- import { Command } from 'commander';
2
- import { readCraftDeskJson, readCraftDeskLock } from '../utils/file-system';
3
- import { logger } from '../utils/logger';
4
- import { installer } from '../services/installer';
5
-
6
- export function createListCommand(): Command {
7
- return new Command('list')
8
- .description('List installed crafts')
9
- .option('--tree', 'Show dependency tree')
10
- .option('--depth <n>', 'Limit tree depth', parseInt)
11
- .option('--json', 'Output as JSON')
12
- .action(async (options) => {
13
- await listCommand(options);
14
- });
15
- }
16
-
17
- async function listCommand(options: any): Promise<void> {
18
- try {
19
- // Read craftdesk.json for project info
20
- const craftDeskJson = await readCraftDeskJson();
21
- if (!craftDeskJson) {
22
- logger.error('No craftdesk.json found in current directory');
23
- process.exit(1);
24
- }
25
-
26
- // Get installed crafts
27
- const installedCrafts = await installer.listInstalled();
28
-
29
- if (options.json) {
30
- // JSON output
31
- console.log(JSON.stringify({
32
- name: craftDeskJson.name,
33
- version: craftDeskJson.version,
34
- installedCrafts
35
- }, null, 2));
36
- return;
37
- }
38
-
39
- // Display project info
40
- logger.log(`${craftDeskJson.name}@${craftDeskJson.version}`);
41
-
42
- if (installedCrafts.length === 0) {
43
- logger.info('No crafts installed');
44
- logger.info('Run "craftdesk install" to install dependencies');
45
- return;
46
- }
47
-
48
- if (options.tree) {
49
- // Show dependency tree
50
- const lockfile = await readCraftDeskLock();
51
- if (!lockfile) {
52
- logger.warn('No craftdesk.lock found. Cannot show dependency tree.');
53
- logger.info('Run "craftdesk install" to generate lockfile');
54
- } else {
55
- displayDependencyTree(lockfile, options.depth);
56
- }
57
- } else {
58
- // Simple list
59
- logger.log('\nInstalled crafts:');
60
- for (const craft of installedCrafts) {
61
- const typeIcon = getTypeIcon(craft.type);
62
- logger.log(` ${typeIcon} ${craft.name}@${craft.version} (${craft.type})`);
63
- }
64
-
65
- logger.log('');
66
- logger.info(`Total: ${installedCrafts.length} crafts installed`);
67
- }
68
- } catch (error: any) {
69
- logger.error(`Failed to list crafts: ${error.message}`);
70
- process.exit(1);
71
- }
72
- }
73
-
74
- function getTypeIcon(type: string): string {
75
- switch (type) {
76
- case 'skill':
77
- return '📚';
78
- case 'agent':
79
- return '🤖';
80
- case 'command':
81
- return '⚡';
82
- case 'hook':
83
- return '🔗';
84
- default:
85
- return '📦';
86
- }
87
- }
88
-
89
- function displayDependencyTree(lockfile: any, maxDepth?: number): void {
90
- logger.log('\nDependency tree:');
91
-
92
- if (!lockfile.tree) {
93
- logger.warn('No dependency tree information in lockfile');
94
- return;
95
- }
96
-
97
- const tree = lockfile.tree;
98
- const depth = 0;
99
- const prefix = '';
100
-
101
- for (const [key, value] of Object.entries(tree)) {
102
- displayTreeNode(key, value, depth, maxDepth || Infinity, prefix, Object.keys(tree).indexOf(key) === Object.keys(tree).length - 1);
103
- }
104
- }
105
-
106
- function displayTreeNode(key: string, node: any, depth: number, maxDepth: number, prefix: string, isLast: boolean): void {
107
- if (depth > maxDepth) return;
108
-
109
- const connector = isLast ? '└── ' : '├── ';
110
- const [name, version] = key.split('@');
111
-
112
- logger.log(`${prefix}${connector}${name}@${version}`);
113
-
114
- if (typeof node === 'object' && node.dependencies && depth < maxDepth) {
115
- const newPrefix = prefix + (isLast ? ' ' : '│ ');
116
- const deps = Object.entries(node.dependencies);
117
-
118
- deps.forEach(([depKey, depValue], index) => {
119
- const isLastDep = index === deps.length - 1;
120
- displayTreeNode(depKey, depValue, depth + 1, maxDepth, newPrefix, isLastDep);
121
- });
122
- } else if (typeof node === 'string' && node === '(shared)') {
123
- // Shared dependency indicator
124
- logger.log(' (shared)');
125
- }
126
- }
@@ -1,82 +0,0 @@
1
- import { Command } from 'commander';
2
- import { readCraftDeskJson, writeCraftDeskJson, readCraftDeskLock, writeCraftDeskLock } from '../utils/file-system';
3
- import { logger } from '../utils/logger';
4
- import { installer } from '../services/installer';
5
-
6
- export function createRemoveCommand(): Command {
7
- return new Command('remove')
8
- .description('Remove a dependency')
9
- .argument('<craft>', 'Craft name to remove')
10
- .action(async (craftName: string) => {
11
- await removeCommand(craftName);
12
- });
13
- }
14
-
15
- async function removeCommand(craftName: string): Promise<void> {
16
- try {
17
- // Read craftdesk.json
18
- const craftDeskJson = await readCraftDeskJson();
19
- if (!craftDeskJson) {
20
- logger.error('No craftdesk.json found in current directory');
21
- process.exit(1);
22
- }
23
-
24
- // Check if craft exists in any dependency field
25
- let found = false;
26
- let foundInField: string | null = null;
27
-
28
- const depFields = ['dependencies', 'devDependencies', 'optionalDependencies', 'peerDependencies'];
29
-
30
- for (const field of depFields) {
31
- if (craftDeskJson[field] && craftDeskJson[field][craftName]) {
32
- found = true;
33
- foundInField = field;
34
- delete craftDeskJson[field][craftName];
35
-
36
- // Remove empty objects
37
- if (Object.keys(craftDeskJson[field]).length === 0) {
38
- delete craftDeskJson[field];
39
- }
40
- break;
41
- }
42
- }
43
-
44
- if (!found) {
45
- logger.error(`Craft '${craftName}' is not in craftdesk.json`);
46
- process.exit(1);
47
- }
48
-
49
- // Save updated craftdesk.json
50
- await writeCraftDeskJson(craftDeskJson);
51
- logger.success(`Removed ${craftName} from ${foundInField}`);
52
-
53
- // Read lockfile to get craft type
54
- const lockfile = await readCraftDeskLock();
55
- if (lockfile && lockfile.crafts[craftName]) {
56
- const craftEntry = lockfile.crafts[craftName];
57
-
58
- // Remove from file system
59
- await installer.removeCraft(craftName, craftEntry.type);
60
-
61
- // Remove from lockfile
62
- delete lockfile.crafts[craftName];
63
-
64
- // TODO: Clean up dependency tree in lockfile
65
-
66
- // Save updated lockfile
67
- await writeCraftDeskLock(lockfile);
68
- logger.success('Updated craftdesk.lock');
69
- } else {
70
- // Try to remove from file system anyway (best effort)
71
- const typesToTry = ['skill', 'agent', 'command', 'hook', 'plugin'];
72
- for (const type of typesToTry) {
73
- await installer.removeCraft(craftName, type);
74
- }
75
- }
76
-
77
- logger.success('Craft removed successfully!');
78
- } catch (error: any) {
79
- logger.error(`Failed to remove craft: ${error.message}`);
80
- process.exit(1);
81
- }
82
- }
package/src/index.ts DELETED
@@ -1,56 +0,0 @@
1
- #!/usr/bin/env node
2
-
3
- import { Command } from 'commander';
4
- import { createInitCommand } from './commands/init';
5
- import { createInstallCommand } from './commands/install';
6
- import { createAddCommand } from './commands/add';
7
- import { createRemoveCommand } from './commands/remove';
8
- import { createListCommand } from './commands/list';
9
- import { logger } from './utils/logger';
10
-
11
- const program = new Command();
12
-
13
- program
14
- .name('craftdesk')
15
- .description('CLI for managing CraftDesk AI capabilities')
16
- .version('0.3.0', '-v, --version')
17
- .option('-d, --debug', 'Enable debug output', () => {
18
- process.env.DEBUG = 'true';
19
- });
20
-
21
- // Add commands
22
- program.addCommand(createInitCommand());
23
- program.addCommand(createInstallCommand());
24
- program.addCommand(createAddCommand());
25
- program.addCommand(createRemoveCommand());
26
- program.addCommand(createListCommand());
27
-
28
- // Add aliases
29
- program.command('i', { hidden: true }).action(() => {
30
- program.parse(['', '', 'install', ...process.argv.slice(3)]);
31
- });
32
-
33
- // Error handling
34
- program.on('command:*', () => {
35
- logger.error(`Invalid command: ${program.args.join(' ')}`);
36
- logger.info('Run "craftdesk --help" for a list of available commands');
37
- process.exit(1);
38
- });
39
-
40
- // Show help if no command provided
41
- if (process.argv.length === 2) {
42
- logger.log('🚀 CraftDesk CLI');
43
- logger.log('');
44
- logger.log('Dependency management for AI capabilities');
45
- logger.log('');
46
- logger.log('Getting started:');
47
- logger.log(' craftdesk init Create a new craftdesk.json file');
48
- logger.log(' craftdesk install Install all dependencies');
49
- logger.log(' craftdesk add <pkg> Add a new dependency');
50
- logger.log('');
51
- logger.log('Run "craftdesk --help" for full command list');
52
- process.exit(0);
53
- }
54
-
55
- // Parse command line arguments
56
- program.parse(process.argv);
@@ -1,150 +0,0 @@
1
- import fs from 'fs-extra';
2
- import path from 'path';
3
- import { CraftDeskJson } from '../types/craftdesk-json';
4
- import { logger } from '../utils/logger';
5
-
6
- /**
7
- * Manages configuration for the CraftDesk CLI
8
- *
9
- * Handles reading craftdesk.json, resolving registry URLs for crafts,
10
- * managing authentication tokens, and determining installation paths.
11
- *
12
- * @example
13
- * ```typescript
14
- * const configManager = new ConfigManager();
15
- * const registry = await configManager.getRegistryForCraft('@company/auth');
16
- * const token = await configManager.getAuthToken('company-private');
17
- * ```
18
- */
19
- export class ConfigManager {
20
- private craftDeskJson: CraftDeskJson | null = null;
21
-
22
- /**
23
- * Gets the appropriate registry URL for a given craft
24
- *
25
- * Resolution order:
26
- * 1. Scoped registry matching the craft scope (e.g., @company/craft -> company registry)
27
- * 2. Default registry from craftdesk.json
28
- * 3. Global fallback (https://craftdesk.ai)
29
- *
30
- * @param craftName - The name of the craft to resolve
31
- * @returns The registry URL to use for this craft
32
- *
33
- * @example
34
- * ```typescript
35
- * // Scoped craft with configured registry
36
- * const url = await configManager.getRegistryForCraft('@company/auth');
37
- * // Returns: 'https://company.internal'
38
- *
39
- * // Regular craft
40
- * const url = await configManager.getRegistryForCraft('ruby-on-rails');
41
- * // Returns: 'https://craftdesk.ai' (or default from config)
42
- * ```
43
- */
44
- async getRegistryForCraft(craftName: string): Promise<string> {
45
- const craftDesk = await this.getCraftDeskJson();
46
-
47
- if (!craftDesk) {
48
- // Default registry if no craftdesk.json exists
49
- return 'https://craftdesk.ai';
50
- }
51
-
52
- // Check if it's a scoped craft and has a configured registry
53
- if (craftName.startsWith('@') && craftDesk.registries) {
54
- const scope = craftName.split('/')[0];
55
-
56
- // Look for a registry with matching scope
57
- for (const [name, registry] of Object.entries(craftDesk.registries)) {
58
- if (registry.scope === scope) {
59
- return registry.url;
60
- }
61
- }
62
- }
63
-
64
- // Check if there's a default registry configured
65
- if (craftDesk.registries?.default) {
66
- return craftDesk.registries.default.url;
67
- }
68
-
69
- // Final fallback
70
- return 'https://craftdesk.ai';
71
- }
72
-
73
- /**
74
- * Retrieves authentication token for a registry from environment variables
75
- *
76
- * Looks for tokens in environment variables with the pattern:
77
- * CRAFTDESK_AUTH_{REGISTRY_NAME_UPPERCASE}
78
- *
79
- * Hyphens in registry names are converted to underscores.
80
- *
81
- * @param registryName - The name of the registry from craftdesk.json
82
- * @returns The auth token if found, null otherwise
83
- *
84
- * @example
85
- * ```typescript
86
- * // For registry named 'company-private', looks for CRAFTDESK_AUTH_COMPANY_PRIVATE
87
- * const token = await configManager.getAuthToken('company-private');
88
- *
89
- * // Usage in shell:
90
- * // export CRAFTDESK_AUTH_COMPANY_PRIVATE=token_abc123
91
- * ```
92
- */
93
- async getAuthToken(registryName: string): Promise<string | null> {
94
- const craftDesk = await this.getCraftDeskJson();
95
-
96
- if (!craftDesk?.registries?.[registryName]) {
97
- return null;
98
- }
99
-
100
- // Auth tokens should be in environment variables for security
101
- // e.g., CRAFTDESK_AUTH_COMPANY_PRIVATE
102
- const envVar = `CRAFTDESK_AUTH_${registryName.toUpperCase().replace(/-/g, '_')}`;
103
- return process.env[envVar] || null;
104
- }
105
-
106
- /**
107
- * Returns the installation path for crafts
108
- *
109
- * All crafts are installed to the .claude directory in the project root.
110
- *
111
- * @returns The relative path to the installation directory
112
- */
113
- getInstallPath(): string {
114
- // Always use .claude directory in project root
115
- return '.claude';
116
- }
117
-
118
- /**
119
- * Reads and caches the craftdesk.json file from the current working directory
120
- *
121
- * The file is cached after the first read for performance. Returns null if
122
- * the file doesn't exist or contains invalid JSON.
123
- *
124
- * @returns The parsed craftdesk.json content, or null if not found/invalid
125
- *
126
- * @example
127
- * ```typescript
128
- * const config = await configManager.getCraftDeskJson();
129
- * if (config) {
130
- * console.log(`Project: ${config.name}@${config.version}`);
131
- * }
132
- * ```
133
- */
134
- async getCraftDeskJson(): Promise<CraftDeskJson | null> {
135
- if (this.craftDeskJson) {
136
- return this.craftDeskJson;
137
- }
138
-
139
- try {
140
- const craftDeskPath = path.join(process.cwd(), 'craftdesk.json');
141
- const content = await fs.readFile(craftDeskPath, 'utf-8');
142
- this.craftDeskJson = JSON.parse(content);
143
- return this.craftDeskJson;
144
- } catch (error) {
145
- return null;
146
- }
147
- }
148
- }
149
-
150
- export const configManager = new ConfigManager();