loadouts 0.1.11

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 (261) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +108 -0
  3. package/bundled/loadouts/loadouts.yaml +5 -0
  4. package/bundled/skills/loadout-usage/SKILL.md +110 -0
  5. package/dist/builtins/index.d.ts +14 -0
  6. package/dist/builtins/index.d.ts.map +1 -0
  7. package/dist/builtins/index.js +58 -0
  8. package/dist/builtins/index.js.map +1 -0
  9. package/dist/builtins/kinds/extension.d.ts +3 -0
  10. package/dist/builtins/kinds/extension.d.ts.map +1 -0
  11. package/dist/builtins/kinds/extension.js +9 -0
  12. package/dist/builtins/kinds/extension.js.map +1 -0
  13. package/dist/builtins/kinds/instruction.d.ts +3 -0
  14. package/dist/builtins/kinds/instruction.d.ts.map +1 -0
  15. package/dist/builtins/kinds/instruction.js +8 -0
  16. package/dist/builtins/kinds/instruction.js.map +1 -0
  17. package/dist/builtins/kinds/prompt.d.ts +3 -0
  18. package/dist/builtins/kinds/prompt.d.ts.map +1 -0
  19. package/dist/builtins/kinds/prompt.js +8 -0
  20. package/dist/builtins/kinds/prompt.js.map +1 -0
  21. package/dist/builtins/kinds/rule.d.ts +3 -0
  22. package/dist/builtins/kinds/rule.d.ts.map +1 -0
  23. package/dist/builtins/kinds/rule.js +10 -0
  24. package/dist/builtins/kinds/rule.js.map +1 -0
  25. package/dist/builtins/kinds/skill.d.ts +3 -0
  26. package/dist/builtins/kinds/skill.d.ts.map +1 -0
  27. package/dist/builtins/kinds/skill.js +8 -0
  28. package/dist/builtins/kinds/skill.js.map +1 -0
  29. package/dist/builtins/kinds/theme.d.ts +3 -0
  30. package/dist/builtins/kinds/theme.d.ts.map +1 -0
  31. package/dist/builtins/kinds/theme.js +8 -0
  32. package/dist/builtins/kinds/theme.js.map +1 -0
  33. package/dist/builtins/tools/claude-code.d.ts +3 -0
  34. package/dist/builtins/tools/claude-code.d.ts.map +1 -0
  35. package/dist/builtins/tools/claude-code.js +30 -0
  36. package/dist/builtins/tools/claude-code.js.map +1 -0
  37. package/dist/builtins/tools/codex.d.ts +3 -0
  38. package/dist/builtins/tools/codex.d.ts.map +1 -0
  39. package/dist/builtins/tools/codex.js +17 -0
  40. package/dist/builtins/tools/codex.js.map +1 -0
  41. package/dist/builtins/tools/cursor.d.ts +3 -0
  42. package/dist/builtins/tools/cursor.d.ts.map +1 -0
  43. package/dist/builtins/tools/cursor.js +22 -0
  44. package/dist/builtins/tools/cursor.js.map +1 -0
  45. package/dist/builtins/tools/opencode.d.ts +3 -0
  46. package/dist/builtins/tools/opencode.d.ts.map +1 -0
  47. package/dist/builtins/tools/opencode.js +45 -0
  48. package/dist/builtins/tools/opencode.js.map +1 -0
  49. package/dist/builtins/tools/pi.d.ts +3 -0
  50. package/dist/builtins/tools/pi.d.ts.map +1 -0
  51. package/dist/builtins/tools/pi.js +22 -0
  52. package/dist/builtins/tools/pi.js.map +1 -0
  53. package/dist/cli/commands/activate.d.ts +12 -0
  54. package/dist/cli/commands/activate.d.ts.map +1 -0
  55. package/dist/cli/commands/activate.js +70 -0
  56. package/dist/cli/commands/activate.js.map +1 -0
  57. package/dist/cli/commands/check.d.ts +12 -0
  58. package/dist/cli/commands/check.d.ts.map +1 -0
  59. package/dist/cli/commands/check.js +152 -0
  60. package/dist/cli/commands/check.js.map +1 -0
  61. package/dist/cli/commands/clear.d.ts +12 -0
  62. package/dist/cli/commands/clear.d.ts.map +1 -0
  63. package/dist/cli/commands/clear.js +25 -0
  64. package/dist/cli/commands/clear.js.map +1 -0
  65. package/dist/cli/commands/create.d.ts +11 -0
  66. package/dist/cli/commands/create.d.ts.map +1 -0
  67. package/dist/cli/commands/create.js +113 -0
  68. package/dist/cli/commands/create.js.map +1 -0
  69. package/dist/cli/commands/deactivate.d.ts +12 -0
  70. package/dist/cli/commands/deactivate.d.ts.map +1 -0
  71. package/dist/cli/commands/deactivate.js +67 -0
  72. package/dist/cli/commands/deactivate.js.map +1 -0
  73. package/dist/cli/commands/diff.d.ts +16 -0
  74. package/dist/cli/commands/diff.d.ts.map +1 -0
  75. package/dist/cli/commands/diff.js +144 -0
  76. package/dist/cli/commands/diff.js.map +1 -0
  77. package/dist/cli/commands/docs.d.ts +12 -0
  78. package/dist/cli/commands/docs.d.ts.map +1 -0
  79. package/dist/cli/commands/docs.js +115 -0
  80. package/dist/cli/commands/docs.js.map +1 -0
  81. package/dist/cli/commands/edit.d.ts +11 -0
  82. package/dist/cli/commands/edit.d.ts.map +1 -0
  83. package/dist/cli/commands/edit.js +71 -0
  84. package/dist/cli/commands/edit.js.map +1 -0
  85. package/dist/cli/commands/fallback.d.ts +9 -0
  86. package/dist/cli/commands/fallback.d.ts.map +1 -0
  87. package/dist/cli/commands/fallback.js +35 -0
  88. package/dist/cli/commands/fallback.js.map +1 -0
  89. package/dist/cli/commands/info.d.ts +23 -0
  90. package/dist/cli/commands/info.d.ts.map +1 -0
  91. package/dist/cli/commands/info.js +314 -0
  92. package/dist/cli/commands/info.js.map +1 -0
  93. package/dist/cli/commands/init.d.ts +18 -0
  94. package/dist/cli/commands/init.d.ts.map +1 -0
  95. package/dist/cli/commands/init.js +255 -0
  96. package/dist/cli/commands/init.js.map +1 -0
  97. package/dist/cli/commands/install.d.ts +27 -0
  98. package/dist/cli/commands/install.d.ts.map +1 -0
  99. package/dist/cli/commands/install.js +586 -0
  100. package/dist/cli/commands/install.js.map +1 -0
  101. package/dist/cli/commands/instructions.d.ts +8 -0
  102. package/dist/cli/commands/instructions.d.ts.map +1 -0
  103. package/dist/cli/commands/instructions.js +218 -0
  104. package/dist/cli/commands/instructions.js.map +1 -0
  105. package/dist/cli/commands/kinds.d.ts +6 -0
  106. package/dist/cli/commands/kinds.d.ts.map +1 -0
  107. package/dist/cli/commands/kinds.js +59 -0
  108. package/dist/cli/commands/kinds.js.map +1 -0
  109. package/dist/cli/commands/list.d.ts +12 -0
  110. package/dist/cli/commands/list.d.ts.map +1 -0
  111. package/dist/cli/commands/list.js +182 -0
  112. package/dist/cli/commands/list.js.map +1 -0
  113. package/dist/cli/commands/policy.d.ts +28 -0
  114. package/dist/cli/commands/policy.d.ts.map +1 -0
  115. package/dist/cli/commands/policy.js +50 -0
  116. package/dist/cli/commands/policy.js.map +1 -0
  117. package/dist/cli/commands/remove.d.ts +24 -0
  118. package/dist/cli/commands/remove.d.ts.map +1 -0
  119. package/dist/cli/commands/remove.js +64 -0
  120. package/dist/cli/commands/remove.js.map +1 -0
  121. package/dist/cli/commands/render-engine.d.ts +36 -0
  122. package/dist/cli/commands/render-engine.d.ts.map +1 -0
  123. package/dist/cli/commands/render-engine.js +177 -0
  124. package/dist/cli/commands/render-engine.js.map +1 -0
  125. package/dist/cli/commands/rule.d.ts +11 -0
  126. package/dist/cli/commands/rule.d.ts.map +1 -0
  127. package/dist/cli/commands/rule.js +302 -0
  128. package/dist/cli/commands/rule.js.map +1 -0
  129. package/dist/cli/commands/sanitize.d.ts +14 -0
  130. package/dist/cli/commands/sanitize.d.ts.map +1 -0
  131. package/dist/cli/commands/sanitize.js +62 -0
  132. package/dist/cli/commands/sanitize.js.map +1 -0
  133. package/dist/cli/commands/skill.d.ts +11 -0
  134. package/dist/cli/commands/skill.d.ts.map +1 -0
  135. package/dist/cli/commands/skill.js +380 -0
  136. package/dist/cli/commands/skill.js.map +1 -0
  137. package/dist/cli/commands/status.d.ts +26 -0
  138. package/dist/cli/commands/status.d.ts.map +1 -0
  139. package/dist/cli/commands/status.js +454 -0
  140. package/dist/cli/commands/status.js.map +1 -0
  141. package/dist/cli/commands/sync.d.ts +14 -0
  142. package/dist/cli/commands/sync.d.ts.map +1 -0
  143. package/dist/cli/commands/sync.js +53 -0
  144. package/dist/cli/commands/sync.js.map +1 -0
  145. package/dist/cli/commands/update.d.ts +3 -0
  146. package/dist/cli/commands/update.d.ts.map +1 -0
  147. package/dist/cli/commands/update.js +48 -0
  148. package/dist/cli/commands/update.js.map +1 -0
  149. package/dist/cli/index.d.ts +11 -0
  150. package/dist/cli/index.d.ts.map +1 -0
  151. package/dist/cli/index.js +134 -0
  152. package/dist/cli/index.js.map +1 -0
  153. package/dist/core/config.d.ts +64 -0
  154. package/dist/core/config.d.ts.map +1 -0
  155. package/dist/core/config.js +166 -0
  156. package/dist/core/config.js.map +1 -0
  157. package/dist/core/discovery.d.ts +50 -0
  158. package/dist/core/discovery.d.ts.map +1 -0
  159. package/dist/core/discovery.js +249 -0
  160. package/dist/core/discovery.js.map +1 -0
  161. package/dist/core/fallback.d.ts +23 -0
  162. package/dist/core/fallback.d.ts.map +1 -0
  163. package/dist/core/fallback.js +119 -0
  164. package/dist/core/fallback.js.map +1 -0
  165. package/dist/core/import-discovery.d.ts +56 -0
  166. package/dist/core/import-discovery.d.ts.map +1 -0
  167. package/dist/core/import-discovery.js +304 -0
  168. package/dist/core/import-discovery.js.map +1 -0
  169. package/dist/core/kindLoader.d.ts +119 -0
  170. package/dist/core/kindLoader.d.ts.map +1 -0
  171. package/dist/core/kindLoader.js +141 -0
  172. package/dist/core/kindLoader.js.map +1 -0
  173. package/dist/core/manifest.d.ts +39 -0
  174. package/dist/core/manifest.d.ts.map +1 -0
  175. package/dist/core/manifest.js +167 -0
  176. package/dist/core/manifest.js.map +1 -0
  177. package/dist/core/plugin.d.ts +22 -0
  178. package/dist/core/plugin.d.ts.map +1 -0
  179. package/dist/core/plugin.js +20 -0
  180. package/dist/core/plugin.js.map +1 -0
  181. package/dist/core/registry.d.ts +115 -0
  182. package/dist/core/registry.d.ts.map +1 -0
  183. package/dist/core/registry.js +105 -0
  184. package/dist/core/registry.js.map +1 -0
  185. package/dist/core/render.d.ts +64 -0
  186. package/dist/core/render.d.ts.map +1 -0
  187. package/dist/core/render.js +457 -0
  188. package/dist/core/render.js.map +1 -0
  189. package/dist/core/resolve.d.ts +39 -0
  190. package/dist/core/resolve.d.ts.map +1 -0
  191. package/dist/core/resolve.js +128 -0
  192. package/dist/core/resolve.js.map +1 -0
  193. package/dist/core/schema.d.ts +308 -0
  194. package/dist/core/schema.d.ts.map +1 -0
  195. package/dist/core/schema.js +81 -0
  196. package/dist/core/schema.js.map +1 -0
  197. package/dist/core/scope.d.ts +74 -0
  198. package/dist/core/scope.d.ts.map +1 -0
  199. package/dist/core/scope.js +176 -0
  200. package/dist/core/scope.js.map +1 -0
  201. package/dist/core/template.d.ts +32 -0
  202. package/dist/core/template.d.ts.map +1 -0
  203. package/dist/core/template.js +32 -0
  204. package/dist/core/template.js.map +1 -0
  205. package/dist/core/tokens.d.ts +33 -0
  206. package/dist/core/tokens.d.ts.map +1 -0
  207. package/dist/core/tokens.js +97 -0
  208. package/dist/core/tokens.js.map +1 -0
  209. package/dist/core/types.d.ts +103 -0
  210. package/dist/core/types.d.ts.map +1 -0
  211. package/dist/core/types.js +10 -0
  212. package/dist/core/types.js.map +1 -0
  213. package/dist/index.d.ts +12 -0
  214. package/dist/index.d.ts.map +1 -0
  215. package/dist/index.js +24 -0
  216. package/dist/index.js.map +1 -0
  217. package/dist/lib/artifact-paths.d.ts +39 -0
  218. package/dist/lib/artifact-paths.d.ts.map +1 -0
  219. package/dist/lib/artifact-paths.js +83 -0
  220. package/dist/lib/artifact-paths.js.map +1 -0
  221. package/dist/lib/artifact-table.d.ts +126 -0
  222. package/dist/lib/artifact-table.d.ts.map +1 -0
  223. package/dist/lib/artifact-table.js +263 -0
  224. package/dist/lib/artifact-table.js.map +1 -0
  225. package/dist/lib/editor.d.ts +17 -0
  226. package/dist/lib/editor.d.ts.map +1 -0
  227. package/dist/lib/editor.js +33 -0
  228. package/dist/lib/editor.js.map +1 -0
  229. package/dist/lib/fs.d.ts +87 -0
  230. package/dist/lib/fs.d.ts.map +1 -0
  231. package/dist/lib/fs.js +229 -0
  232. package/dist/lib/fs.js.map +1 -0
  233. package/dist/lib/git.d.ts +13 -0
  234. package/dist/lib/git.d.ts.map +1 -0
  235. package/dist/lib/git.js +28 -0
  236. package/dist/lib/git.js.map +1 -0
  237. package/dist/lib/gitignore.d.ts +26 -0
  238. package/dist/lib/gitignore.d.ts.map +1 -0
  239. package/dist/lib/gitignore.js +97 -0
  240. package/dist/lib/gitignore.js.map +1 -0
  241. package/dist/lib/loadout-column.d.ts +66 -0
  242. package/dist/lib/loadout-column.d.ts.map +1 -0
  243. package/dist/lib/loadout-column.js +66 -0
  244. package/dist/lib/loadout-column.js.map +1 -0
  245. package/dist/lib/output.d.ts +15 -0
  246. package/dist/lib/output.d.ts.map +1 -0
  247. package/dist/lib/output.js +32 -0
  248. package/dist/lib/output.js.map +1 -0
  249. package/dist/lib/scope-indicators.d.ts +60 -0
  250. package/dist/lib/scope-indicators.d.ts.map +1 -0
  251. package/dist/lib/scope-indicators.js +110 -0
  252. package/dist/lib/scope-indicators.js.map +1 -0
  253. package/docs/authoring.md +182 -0
  254. package/docs/commands.md +192 -0
  255. package/docs/concepts.md +114 -0
  256. package/docs/index.md +60 -0
  257. package/docs/quickstart.md +100 -0
  258. package/docs/troubleshooting.md +147 -0
  259. package/docs/visual-language.md +251 -0
  260. package/docs/workflows.md +184 -0
  261. package/package.json +54 -0
@@ -0,0 +1,249 @@
1
+ /**
2
+ * Discovery: Find .loadouts/ directories and resolve source references
3
+ */
4
+ import * as fs from "node:fs";
5
+ import * as path from "node:path";
6
+ import * as os from "node:os";
7
+ import * as yaml from "yaml";
8
+ import { fileURLToPath } from "node:url";
9
+ const __dirname = path.dirname(fileURLToPath(import.meta.url));
10
+ import { findGitRoot } from "../lib/git.js";
11
+ const LOADOUT_DIR = ".loadouts";
12
+ const STATE_FILE = ".state.json";
13
+ export function getGlobalConfigPath() {
14
+ return path.join(os.homedir(), ".config", "loadouts");
15
+ }
16
+ const GLOBAL_CONFIG_PATH = getGlobalConfigPath();
17
+ /**
18
+ * Discover all .loadouts/ directories from cwd up to git root.
19
+ * Returns them ordered from nearest (depth 0) to furthest.
20
+ */
21
+ export async function discoverLoadoutRoots(cwd = process.cwd()) {
22
+ const roots = [];
23
+ const gitRoot = await findGitRoot(cwd);
24
+ const stopAt = gitRoot || path.parse(cwd).root;
25
+ let current = path.resolve(cwd);
26
+ let depth = 0;
27
+ // Walk up from cwd to git root (or filesystem root)
28
+ while (true) {
29
+ const loadoutPath = path.join(current, LOADOUT_DIR);
30
+ if (fs.existsSync(loadoutPath) && fs.statSync(loadoutPath).isDirectory()) {
31
+ roots.push({
32
+ path: loadoutPath,
33
+ level: "project",
34
+ depth,
35
+ });
36
+ }
37
+ // Stop if we've reached the boundary
38
+ if (current === stopAt || current === path.parse(current).root) {
39
+ break;
40
+ }
41
+ current = path.dirname(current);
42
+ depth++;
43
+ }
44
+ // Check for global config
45
+ if (fs.existsSync(GLOBAL_CONFIG_PATH) &&
46
+ fs.statSync(GLOBAL_CONFIG_PATH).isDirectory()) {
47
+ roots.push({
48
+ path: GLOBAL_CONFIG_PATH,
49
+ level: "global",
50
+ depth: Infinity,
51
+ });
52
+ }
53
+ return roots;
54
+ }
55
+ /**
56
+ * Find the nearest .loadouts/ directory.
57
+ */
58
+ export async function findNearestLoadoutRoot(cwd = process.cwd()) {
59
+ const roots = await discoverLoadoutRoots(cwd);
60
+ return roots.length > 0 ? roots[0] : null;
61
+ }
62
+ /**
63
+ * Get the project root (git root or cwd if no git).
64
+ */
65
+ export async function getProjectRoot(cwd = process.cwd()) {
66
+ const gitRoot = await findGitRoot(cwd);
67
+ return gitRoot || cwd;
68
+ }
69
+ /**
70
+ * Get the command context for a given scope.
71
+ */
72
+ export async function getContext(scope, cwd = process.cwd()) {
73
+ if (scope === "global") {
74
+ const configPath = getGlobalConfigPath();
75
+ return {
76
+ scope: "global",
77
+ configPath,
78
+ statePath: path.join(configPath, STATE_FILE),
79
+ projectRoot: os.homedir(),
80
+ };
81
+ }
82
+ else {
83
+ const nearestRoot = await findNearestLoadoutRoot(cwd);
84
+ if (!nearestRoot) {
85
+ throw new Error("No .loadouts/ directory found. Run 'loadouts init' first.");
86
+ }
87
+ // projectRoot is the directory containing .loadouts/, not git root
88
+ // This allows subprojects in monorepos to have their own loadout
89
+ const projectRoot = path.dirname(nearestRoot.path);
90
+ return {
91
+ scope: "project",
92
+ configPath: nearestRoot.path,
93
+ statePath: path.join(nearestRoot.path, STATE_FILE),
94
+ projectRoot,
95
+ };
96
+ }
97
+ }
98
+ /**
99
+ * Get global config path if it exists.
100
+ */
101
+ export function getGlobalRoot() {
102
+ if (fs.existsSync(GLOBAL_CONFIG_PATH) &&
103
+ fs.statSync(GLOBAL_CONFIG_PATH).isDirectory()) {
104
+ return {
105
+ path: GLOBAL_CONFIG_PATH,
106
+ level: "global",
107
+ depth: Infinity,
108
+ };
109
+ }
110
+ return null;
111
+ }
112
+ /**
113
+ * Find the bundled directory shipped with loadouts.
114
+ * This contains built-in loadouts and skills.
115
+ */
116
+ function findBundledPath() {
117
+ const candidates = [
118
+ // Development: relative to src/core/
119
+ path.resolve(__dirname, "../../bundled"),
120
+ // Production: relative to dist/core/
121
+ path.resolve(__dirname, "../../bundled"),
122
+ ];
123
+ for (const candidate of candidates) {
124
+ if (fs.existsSync(candidate) && fs.statSync(candidate).isDirectory()) {
125
+ return candidate;
126
+ }
127
+ }
128
+ return null;
129
+ }
130
+ /**
131
+ * Get the bundled root (ships with loadouts CLI).
132
+ * Contains built-in loadouts like 'loadouts' for self-documentation.
133
+ */
134
+ export function getBundledRoot() {
135
+ const bundledPath = findBundledPath();
136
+ if (!bundledPath)
137
+ return null;
138
+ return {
139
+ path: bundledPath,
140
+ level: "bundled",
141
+ depth: Infinity,
142
+ };
143
+ }
144
+ // ---------------------------------------------------------------------------
145
+ // Source resolution
146
+ // ---------------------------------------------------------------------------
147
+ /**
148
+ * Resolve a source path relative to a .loadouts/ directory.
149
+ * Handles ~, relative paths, and looks for .loadouts/ within the target.
150
+ */
151
+ export function resolveSourcePath(sourceRef, fromLoadoutDir) {
152
+ // Expand ~ to home directory
153
+ let resolved = sourceRef.startsWith("~")
154
+ ? path.join(os.homedir(), sourceRef.slice(1))
155
+ : sourceRef;
156
+ // Resolve relative to the directory containing .loadouts/
157
+ if (!path.isAbsolute(resolved)) {
158
+ const fromDir = path.dirname(fromLoadoutDir);
159
+ resolved = path.resolve(fromDir, resolved);
160
+ }
161
+ // If the path points directly to a .loadouts/ directory, use it
162
+ if (path.basename(resolved) === ".loadouts" && fs.existsSync(resolved)) {
163
+ return resolved;
164
+ }
165
+ // Otherwise, look for .loadouts/ within the resolved path
166
+ const loadoutPath = path.join(resolved, ".loadouts");
167
+ if (fs.existsSync(loadoutPath) && fs.statSync(loadoutPath).isDirectory()) {
168
+ return loadoutPath;
169
+ }
170
+ return null;
171
+ }
172
+ /**
173
+ * Parse sources from a loadouts.yaml file.
174
+ * Returns empty array if file doesn't exist or has no sources.
175
+ */
176
+ function parseSourcesFromConfig(loadoutDir) {
177
+ const configPath = path.join(loadoutDir, "loadouts.yaml");
178
+ if (!fs.existsSync(configPath))
179
+ return [];
180
+ try {
181
+ const content = fs.readFileSync(configPath, "utf-8");
182
+ const config = yaml.parse(content);
183
+ return config?.sources ?? [];
184
+ }
185
+ catch {
186
+ return [];
187
+ }
188
+ }
189
+ /**
190
+ * Collect all roots starting from a primary root, following sources transitively.
191
+ * Missing sources generate warnings but don't fail resolution.
192
+ *
193
+ * @param primaryRoot - The starting .loadouts/ directory
194
+ * @param includeGlobal - Whether to append the global root
195
+ * @param includeBundled - Whether to append the bundled root (default: true)
196
+ * @returns Ordered list of roots (primary first, then sources, global, bundled last)
197
+ */
198
+ export function collectRootsWithSources(primaryRoot, includeGlobal = true, includeBundled = true) {
199
+ const roots = [primaryRoot];
200
+ const seen = new Set([primaryRoot.path]);
201
+ const warnings = [];
202
+ // BFS through sources to maintain declaration order and handle transitives
203
+ const queue = [
204
+ { loadoutDir: primaryRoot.path, depth: 0 },
205
+ ];
206
+ while (queue.length > 0) {
207
+ const { loadoutDir, depth } = queue.shift();
208
+ const sources = parseSourcesFromConfig(loadoutDir);
209
+ for (const sourcePath of sources) {
210
+ const resolved = resolveSourcePath(sourcePath, loadoutDir);
211
+ if (!resolved) {
212
+ warnings.push(`Source not found: ${sourcePath} (from ${path.basename(path.dirname(loadoutDir))})`);
213
+ continue;
214
+ }
215
+ // Cycle detection
216
+ if (seen.has(resolved)) {
217
+ continue; // Skip silently - not an error, just already included
218
+ }
219
+ seen.add(resolved);
220
+ const sourceRoot = {
221
+ path: resolved,
222
+ level: "source",
223
+ depth: depth + 1,
224
+ sourceRef: sourcePath,
225
+ };
226
+ roots.push(sourceRoot);
227
+ // Queue for transitive source resolution
228
+ queue.push({ loadoutDir: resolved, depth: depth + 1 });
229
+ }
230
+ }
231
+ // Append global root (low priority)
232
+ if (includeGlobal) {
233
+ const globalRoot = getGlobalRoot();
234
+ if (globalRoot && !seen.has(globalRoot.path)) {
235
+ roots.push(globalRoot);
236
+ seen.add(globalRoot.path);
237
+ }
238
+ }
239
+ // Append bundled root last (lowest priority)
240
+ // This provides built-in loadouts like 'loadouts' for self-documentation
241
+ if (includeBundled) {
242
+ const bundledRoot = getBundledRoot();
243
+ if (bundledRoot && !seen.has(bundledRoot.path)) {
244
+ roots.push(bundledRoot);
245
+ }
246
+ }
247
+ return { roots, warnings };
248
+ }
249
+ //# sourceMappingURL=discovery.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"discovery.js","sourceRoot":"","sources":["../../src/core/discovery.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Shared fallback script content for loadouts.
3
+ * Used by both init and sync to keep the fallback script up to date.
4
+ */
5
+ export declare const FALLBACK_SCRIPT = "#!/bin/sh\n# Fallback sync for loadouts - applies basic configuration without loadouts installed\n# This script is called by git hooks and direnv when loadouts is not available\n\nset -e\ncd \"$(dirname \"$0\")/..\"\n\n# Skip if already synced\n[ -f \".loadouts/.state.json\" ] && exit 0\n\n# If loadouts is available, use it\nif command -v loadouts >/dev/null 2>&1; then\n echo \"loadouts: Applying base configuration...\"\n loadouts sync -l\n exit 0\nfi\n\n# Fallback: symlink all artifacts without loadouts\necho \"\"\necho \"\u26A0 This project uses loadouts for AI tool configuration.\"\necho \" Install with: npm install -g loadouts\"\necho \"\"\necho \" Applying fallback configuration...\"\n\n# Instructions\nif [ -f \".loadouts/AGENTS.md\" ] && [ ! -e \"AGENTS.md\" ]; then\n ln -s .loadouts/AGENTS.md AGENTS.md\n echo \" \u2713 AGENTS.md\"\nfi\nif [ ! -e \"CLAUDE.md\" ]; then\n cat > CLAUDE.md << 'CLAUDE_EOF'\n# Claude Code Instructions\n\n> This file is auto-generated. Install loadouts for full configuration.\n> npm install -g loadouts && loadouts sync\n\nSee [AGENTS.md](AGENTS.md) for project instructions.\nCLAUDE_EOF\n echo \" \u2713 CLAUDE.md\"\nfi\n\n# Rules - symlink to all tool directories\nfor rule in .loadouts/rules/*.md; do\n [ -f \"$rule\" ] || continue\n stem=$(basename \"$rule\" .md)\n for tooldir in .claude .cursor .opencode .pi; do\n mkdir -p \"$tooldir/rules\"\n ext=\"md\"\n [ \"$tooldir\" = \".cursor\" ] && ext=\"mdc\"\n target=\"$tooldir/rules/$stem.$ext\"\n [ -e \"$target\" ] || ln -s \"../../$rule\" \"$target\"\n done\n echo \" \u2713 rules/$stem.md\"\ndone\n\n# Skills - symlink individual files to all tool directories\nfor skilldir in .loadouts/skills/*/; do\n [ -d \"$skilldir\" ] || continue\n skillname=$(basename \"$skilldir\")\n find \"$skilldir\" -type f | while read -r file; do\n relpath=\"${file#$skilldir}\"\n for tooldir in .claude .cursor .opencode .agents .pi; do\n targetdir=\"$tooldir/skills/$skillname/$(dirname \"$relpath\")\"\n mkdir -p \"$targetdir\"\n target=\"$tooldir/skills/$skillname/$relpath\"\n depth=$(echo \"$target\" | tr -cd '/' | wc -c)\n updirs=$(printf '../%.0s' $(seq 1 $depth))\n [ -e \"$target\" ] || ln -s \"${updirs}$file\" \"$target\"\n done\n done\n echo \" \u2713 skills/$skillname\"\ndone\n\necho \"\"\necho \" Run 'loadouts sync' after installing for full configuration.\"\n";
6
+ export declare const HOOK_SCRIPT = "#!/bin/sh\n# Auto-sync loadouts after checkout/clone/merge\nexec .loadouts/sync-fallback.sh 2>/dev/null || true\n";
7
+ export declare const ENVRC_LINES = "\n# Auto-sync loadout on directory entry\n[ -x .loadouts/sync-fallback.sh ] && .loadouts/sync-fallback.sh\n";
8
+ /**
9
+ * Write the main fallback sync script.
10
+ * Works for both git root and subprojects.
11
+ */
12
+ export declare function writeFallbackScript(loadoutPath: string): void;
13
+ /**
14
+ * Write git hooks that call the fallback script.
15
+ * Only meaningful when .loadouts/ is at git root.
16
+ */
17
+ export declare function writeGitHooks(loadoutPath: string): void;
18
+ /**
19
+ * Write all fallback infrastructure (script + hooks).
20
+ * Use writeFallbackScript() alone for subprojects where git hooks don't apply.
21
+ */
22
+ export declare function writeFallbackScripts(loadoutPath: string): void;
23
+ //# sourceMappingURL=fallback.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fallback.d.ts","sourceRoot":"","sources":["../../src/core/fallback.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAKH,eAAO,MAAM,eAAe,+4EA2E3B,CAAC;AAEF,eAAO,MAAM,WAAW,sHAGvB,CAAC;AAEF,eAAO,MAAM,WAAW,gHAGvB,CAAC;AAEF;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI,CAG7D;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI,CAOvD;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI,CAG9D"}
@@ -0,0 +1,119 @@
1
+ /**
2
+ * Shared fallback script content for loadouts.
3
+ * Used by both init and sync to keep the fallback script up to date.
4
+ */
5
+ import * as path from "node:path";
6
+ import { writeFile, makeExecutable, ensureDir } from "../lib/fs.js";
7
+ export const FALLBACK_SCRIPT = `#!/bin/sh
8
+ # Fallback sync for loadouts - applies basic configuration without loadouts installed
9
+ # This script is called by git hooks and direnv when loadouts is not available
10
+
11
+ set -e
12
+ cd "$(dirname "$0")/.."
13
+
14
+ # Skip if already synced
15
+ [ -f ".loadouts/.state.json" ] && exit 0
16
+
17
+ # If loadouts is available, use it
18
+ if command -v loadouts >/dev/null 2>&1; then
19
+ echo "loadouts: Applying base configuration..."
20
+ loadouts sync -l
21
+ exit 0
22
+ fi
23
+
24
+ # Fallback: symlink all artifacts without loadouts
25
+ echo ""
26
+ echo "⚠ This project uses loadouts for AI tool configuration."
27
+ echo " Install with: npm install -g loadouts"
28
+ echo ""
29
+ echo " Applying fallback configuration..."
30
+
31
+ # Instructions
32
+ if [ -f ".loadouts/AGENTS.md" ] && [ ! -e "AGENTS.md" ]; then
33
+ ln -s .loadouts/AGENTS.md AGENTS.md
34
+ echo " ✓ AGENTS.md"
35
+ fi
36
+ if [ ! -e "CLAUDE.md" ]; then
37
+ cat > CLAUDE.md << 'CLAUDE_EOF'
38
+ # Claude Code Instructions
39
+
40
+ > This file is auto-generated. Install loadouts for full configuration.
41
+ > npm install -g loadouts && loadouts sync
42
+
43
+ See [AGENTS.md](AGENTS.md) for project instructions.
44
+ CLAUDE_EOF
45
+ echo " ✓ CLAUDE.md"
46
+ fi
47
+
48
+ # Rules - symlink to all tool directories
49
+ for rule in .loadouts/rules/*.md; do
50
+ [ -f "$rule" ] || continue
51
+ stem=$(basename "$rule" .md)
52
+ for tooldir in .claude .cursor .opencode .pi; do
53
+ mkdir -p "$tooldir/rules"
54
+ ext="md"
55
+ [ "$tooldir" = ".cursor" ] && ext="mdc"
56
+ target="$tooldir/rules/$stem.$ext"
57
+ [ -e "$target" ] || ln -s "../../$rule" "$target"
58
+ done
59
+ echo " ✓ rules/$stem.md"
60
+ done
61
+
62
+ # Skills - symlink individual files to all tool directories
63
+ for skilldir in .loadouts/skills/*/; do
64
+ [ -d "$skilldir" ] || continue
65
+ skillname=$(basename "$skilldir")
66
+ find "$skilldir" -type f | while read -r file; do
67
+ relpath="\${file#$skilldir}"
68
+ for tooldir in .claude .cursor .opencode .agents .pi; do
69
+ targetdir="$tooldir/skills/$skillname/$(dirname "$relpath")"
70
+ mkdir -p "$targetdir"
71
+ target="$tooldir/skills/$skillname/$relpath"
72
+ depth=$(echo "$target" | tr -cd '/' | wc -c)
73
+ updirs=$(printf '../%.0s' $(seq 1 $depth))
74
+ [ -e "$target" ] || ln -s "\${updirs}$file" "$target"
75
+ done
76
+ done
77
+ echo " ✓ skills/$skillname"
78
+ done
79
+
80
+ echo ""
81
+ echo " Run 'loadouts sync' after installing for full configuration."
82
+ `;
83
+ export const HOOK_SCRIPT = `#!/bin/sh
84
+ # Auto-sync loadouts after checkout/clone/merge
85
+ exec .loadouts/sync-fallback.sh 2>/dev/null || true
86
+ `;
87
+ export const ENVRC_LINES = `
88
+ # Auto-sync loadout on directory entry
89
+ [ -x .loadouts/sync-fallback.sh ] && .loadouts/sync-fallback.sh
90
+ `;
91
+ /**
92
+ * Write the main fallback sync script.
93
+ * Works for both git root and subprojects.
94
+ */
95
+ export function writeFallbackScript(loadoutPath) {
96
+ writeFile(path.join(loadoutPath, "sync-fallback.sh"), FALLBACK_SCRIPT);
97
+ makeExecutable(path.join(loadoutPath, "sync-fallback.sh"));
98
+ }
99
+ /**
100
+ * Write git hooks that call the fallback script.
101
+ * Only meaningful when .loadouts/ is at git root.
102
+ */
103
+ export function writeGitHooks(loadoutPath) {
104
+ const hooksDir = path.join(loadoutPath, "hooks");
105
+ ensureDir(hooksDir);
106
+ writeFile(path.join(hooksDir, "post-checkout"), HOOK_SCRIPT);
107
+ writeFile(path.join(hooksDir, "post-merge"), HOOK_SCRIPT);
108
+ makeExecutable(path.join(hooksDir, "post-checkout"));
109
+ makeExecutable(path.join(hooksDir, "post-merge"));
110
+ }
111
+ /**
112
+ * Write all fallback infrastructure (script + hooks).
113
+ * Use writeFallbackScript() alone for subprojects where git hooks don't apply.
114
+ */
115
+ export function writeFallbackScripts(loadoutPath) {
116
+ writeFallbackScript(loadoutPath);
117
+ writeGitHooks(loadoutPath);
118
+ }
119
+ //# sourceMappingURL=fallback.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fallback.js","sourceRoot":"","sources":["../../src/core/fallback.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAClC,OAAO,EAAE,SAAS,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAEpE,MAAM,CAAC,MAAM,eAAe,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA2E9B,CAAC;AAEF,MAAM,CAAC,MAAM,WAAW,GAAG;;;CAG1B,CAAC;AAEF,MAAM,CAAC,MAAM,WAAW,GAAG;;;CAG1B,CAAC;AAEF;;;GAGG;AACH,MAAM,UAAU,mBAAmB,CAAC,WAAmB;IACrD,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,kBAAkB,CAAC,EAAE,eAAe,CAAC,CAAC;IACvE,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,kBAAkB,CAAC,CAAC,CAAC;AAC7D,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,aAAa,CAAC,WAAmB;IAC/C,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC;IACjD,SAAS,CAAC,QAAQ,CAAC,CAAC;IACpB,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,eAAe,CAAC,EAAE,WAAW,CAAC,CAAC;IAC7D,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,YAAY,CAAC,EAAE,WAAW,CAAC,CAAC;IAC1D,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,eAAe,CAAC,CAAC,CAAC;IACrD,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,YAAY,CAAC,CAAC,CAAC;AACpD,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,oBAAoB,CAAC,WAAmB;IACtD,mBAAmB,CAAC,WAAW,CAAC,CAAC;IACjC,aAAa,CAAC,WAAW,CAAC,CAAC;AAC7B,CAAC"}
@@ -0,0 +1,56 @@
1
+ /**
2
+ * Import Discovery — scan tool directories for existing configurations
3
+ * that can be imported into loadout.
4
+ */
5
+ export type ImportableKind = "rule" | "skill" | "instruction";
6
+ export interface DiscoveredArtifact {
7
+ /** Artifact kind */
8
+ kind: ImportableKind;
9
+ /** Suggested name in .loadouts/ (without extension for rules) */
10
+ name: string;
11
+ /** Absolute path to source file/directory */
12
+ sourcePath: string;
13
+ /** Display path relative to project root */
14
+ displayPath: string;
15
+ /** Which tool directory it came from */
16
+ tool: string;
17
+ /** File size in bytes (for files) or total size (for directories) */
18
+ size: number;
19
+ /** Last modification time */
20
+ mtime: Date;
21
+ /** Destination path in .loadouts/ */
22
+ destPath: string;
23
+ }
24
+ export interface DiscoveryResult {
25
+ /** All discovered artifacts */
26
+ artifacts: DiscoveredArtifact[];
27
+ /** Artifacts grouped by name that conflict */
28
+ conflicts: Map<string, DiscoveredArtifact[]>;
29
+ /** Any warnings during discovery */
30
+ warnings: string[];
31
+ }
32
+ export interface DiscoveryOptions {
33
+ /** Filter to specific tools */
34
+ tools?: string[];
35
+ /** Filter to specific kinds */
36
+ kinds?: ImportableKind[];
37
+ /** Path to .loadouts/ directory (to check for existing artifacts) */
38
+ loadoutPath?: string;
39
+ }
40
+ /**
41
+ * Discover all importable artifacts in a project.
42
+ */
43
+ export declare function discoverImportableArtifacts(projectRoot: string, options?: DiscoveryOptions): DiscoveryResult;
44
+ /**
45
+ * Group artifacts by kind for display.
46
+ */
47
+ export declare function groupByKind(artifacts: DiscoveredArtifact[]): Record<ImportableKind, DiscoveredArtifact[]>;
48
+ /**
49
+ * Format file size for display.
50
+ */
51
+ export declare function formatSize(bytes: number): string;
52
+ /**
53
+ * Format relative time for display.
54
+ */
55
+ export declare function formatRelativeTime(date: Date): string;
56
+ //# sourceMappingURL=import-discovery.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"import-discovery.d.ts","sourceRoot":"","sources":["../../src/core/import-discovery.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAWH,MAAM,MAAM,cAAc,GAAG,MAAM,GAAG,OAAO,GAAG,aAAa,CAAC;AAE9D,MAAM,WAAW,kBAAkB;IACjC,oBAAoB;IACpB,IAAI,EAAE,cAAc,CAAC;IACrB,iEAAiE;IACjE,IAAI,EAAE,MAAM,CAAC;IACb,6CAA6C;IAC7C,UAAU,EAAE,MAAM,CAAC;IACnB,4CAA4C;IAC5C,WAAW,EAAE,MAAM,CAAC;IACpB,wCAAwC;IACxC,IAAI,EAAE,MAAM,CAAC;IACb,qEAAqE;IACrE,IAAI,EAAE,MAAM,CAAC;IACb,6BAA6B;IAC7B,KAAK,EAAE,IAAI,CAAC;IACZ,qCAAqC;IACrC,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,eAAe;IAC9B,+BAA+B;IAC/B,SAAS,EAAE,kBAAkB,EAAE,CAAC;IAChC,8CAA8C;IAC9C,SAAS,EAAE,GAAG,CAAC,MAAM,EAAE,kBAAkB,EAAE,CAAC,CAAC;IAC7C,oCAAoC;IACpC,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB;AAED,MAAM,WAAW,gBAAgB;IAC/B,+BAA+B;IAC/B,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;IACjB,+BAA+B;IAC/B,KAAK,CAAC,EAAE,cAAc,EAAE,CAAC;IACzB,qEAAqE;IACrE,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAqPD;;GAEG;AACH,wBAAgB,2BAA2B,CACzC,WAAW,EAAE,MAAM,EACnB,OAAO,GAAE,gBAAqB,GAC7B,eAAe,CAoDjB;AAED;;GAEG;AACH,wBAAgB,WAAW,CACzB,SAAS,EAAE,kBAAkB,EAAE,GAC9B,MAAM,CAAC,cAAc,EAAE,kBAAkB,EAAE,CAAC,CAY9C;AAED;;GAEG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAIhD;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,IAAI,GAAG,MAAM,CAWrD"}