@looplia/looplia-cli 0.6.10 → 0.7.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.
@@ -0,0 +1,28 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ addSource,
4
+ compileRegistry,
5
+ createEmptyManifest,
6
+ getCompiledRegistryPath,
7
+ getRegistryPath,
8
+ getSkillCatalogPath,
9
+ getSourcesPath,
10
+ initializeRegistry,
11
+ loadSources,
12
+ removeSource,
13
+ saveSources
14
+ } from "./chunk-GN6D7YWI.js";
15
+ import "./chunk-FCL2HRTX.js";
16
+ export {
17
+ addSource,
18
+ compileRegistry,
19
+ createEmptyManifest,
20
+ getCompiledRegistryPath,
21
+ getRegistryPath,
22
+ getSkillCatalogPath,
23
+ getSourcesPath,
24
+ initializeRegistry,
25
+ loadSources,
26
+ removeSource,
27
+ saveSources
28
+ };
@@ -0,0 +1,59 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ CORE_SKILLS,
4
+ ensureWorkflowSkills,
5
+ ensureWorkspace,
6
+ findSkill,
7
+ getAvailableSkills,
8
+ getInstalledSkills,
9
+ getSkillsByCategory,
10
+ getSkillsBySource,
11
+ installMarketplaceSkill,
12
+ installSkill,
13
+ installSkillFromUrl,
14
+ isCoreSkill,
15
+ loadCompiledRegistry,
16
+ removeSkill,
17
+ updateSkill
18
+ } from "./chunk-APETX7TD.js";
19
+ import "./chunk-IVTVHH75.js";
20
+ import {
21
+ addSource,
22
+ compileRegistry,
23
+ getCompiledRegistryPath,
24
+ getRegistryPath,
25
+ getSkillCatalogPath,
26
+ getSourcesPath,
27
+ initializeRegistry,
28
+ loadSources,
29
+ removeSource,
30
+ saveSources
31
+ } from "./chunk-GN6D7YWI.js";
32
+ import "./chunk-FCL2HRTX.js";
33
+ export {
34
+ CORE_SKILLS,
35
+ addSource,
36
+ compileRegistry,
37
+ ensureWorkflowSkills,
38
+ ensureWorkspace,
39
+ findSkill,
40
+ getAvailableSkills,
41
+ getCompiledRegistryPath,
42
+ getInstalledSkills,
43
+ getRegistryPath,
44
+ getSkillCatalogPath,
45
+ getSkillsByCategory,
46
+ getSkillsBySource,
47
+ getSourcesPath,
48
+ initializeRegistry,
49
+ installMarketplaceSkill,
50
+ installSkill,
51
+ installSkillFromUrl,
52
+ isCoreSkill,
53
+ loadCompiledRegistry,
54
+ loadSources,
55
+ removeSkill,
56
+ removeSource,
57
+ saveSources,
58
+ updateSkill
59
+ };
@@ -0,0 +1,18 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ CORE_SKILLS,
4
+ getPluginSkills,
5
+ getSelectivePluginPaths,
6
+ installDefaultSources,
7
+ installThirdPartyPlugin,
8
+ isCoreSkill
9
+ } from "./chunk-IVTVHH75.js";
10
+ import "./chunk-FCL2HRTX.js";
11
+ export {
12
+ CORE_SKILLS,
13
+ getPluginSkills,
14
+ getSelectivePluginPaths,
15
+ installDefaultSources,
16
+ installThirdPartyPlugin,
17
+ isCoreSkill
18
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@looplia/looplia-cli",
3
- "version": "0.6.10",
3
+ "version": "0.7.0",
4
4
  "description": "Looplia CLI - AI-powered workflow automation tool",
5
5
  "type": "module",
6
6
  "license": "Elastic-2.0",
@@ -1,4 +1,5 @@
1
1
  import { describe, expect, it } from "bun:test";
2
+ import { join } from "node:path";
2
3
  import {
3
4
  CAPABILITY_PATTERNS,
4
5
  extractFrontmatter,
@@ -6,6 +7,9 @@ import {
6
7
  scanPlugins,
7
8
  } from "../scripts/scan-plugins";
8
9
 
10
+ // Use absolute path to ensure tests work from any directory
11
+ const PLUGINS_DIR = join(import.meta.dir, "../../../..");
12
+
9
13
  describe("scan-plugins", () => {
10
14
  describe("extractFrontmatter", () => {
11
15
  it("should extract valid YAML frontmatter", () => {
@@ -162,7 +166,7 @@ description: Missing closing delimiter
162
166
 
163
167
  describe("scanPlugins", () => {
164
168
  it("should discover looplia-core skills", async () => {
165
- const result = await scanPlugins("plugins");
169
+ const result = await scanPlugins(PLUGINS_DIR);
166
170
  const corePlugin = result.plugins.find((p) => p.name === "looplia-core");
167
171
 
168
172
  expect(corePlugin).toBeDefined();
@@ -175,7 +179,7 @@ description: Missing closing delimiter
175
179
  });
176
180
 
177
181
  it("should discover looplia-writer skills", async () => {
178
- const result = await scanPlugins("plugins");
182
+ const result = await scanPlugins(PLUGINS_DIR);
179
183
  const writerPlugin = result.plugins.find(
180
184
  (p) => p.name === "looplia-writer"
181
185
  );
@@ -190,7 +194,7 @@ description: Missing closing delimiter
190
194
  });
191
195
 
192
196
  it("should return valid registry JSON schema", async () => {
193
- const result = await scanPlugins("plugins");
197
+ const result = await scanPlugins(PLUGINS_DIR);
194
198
 
195
199
  // Check top-level structure
196
200
  expect(result).toHaveProperty("plugins");
@@ -214,7 +218,7 @@ description: Missing closing delimiter
214
218
  });
215
219
 
216
220
  it("should include tools and model when specified", async () => {
217
- const result = await scanPlugins("plugins");
221
+ const result = await scanPlugins(PLUGINS_DIR);
218
222
  const corePlugin = result.plugins.find((p) => p.name === "looplia-core");
219
223
  const scanner = corePlugin?.skills.find(
220
224
  (s) => s.name === "plugin-registry-scanner"
@@ -234,7 +238,7 @@ description: Missing closing delimiter
234
238
  });
235
239
 
236
240
  it("should calculate correct totals", async () => {
237
- const result = await scanPlugins("plugins");
241
+ const result = await scanPlugins(PLUGINS_DIR);
238
242
 
239
243
  const calculatedTotal = result.plugins.reduce(
240
244
  (sum, p) => sum + p.skills.length,
@@ -245,11 +249,11 @@ description: Missing closing delimiter
245
249
  expect(result.summary.totalPlugins).toBe(result.plugins.length);
246
250
  });
247
251
 
248
- it("should discover exactly 14 skills after adding workflow-executor-inline", async () => {
249
- const result = await scanPlugins("plugins");
252
+ it("should discover exactly 15 skills after adding registry-loader", async () => {
253
+ const result = await scanPlugins(PLUGINS_DIR);
250
254
 
251
- // After adding workflow-executor-inline skill, we should have all 14 skills
252
- expect(result.summary.totalSkills).toBe(14);
255
+ // After adding registry-loader skill, we should have all 15 skills
256
+ expect(result.summary.totalSkills).toBe(15);
253
257
  expect(result.summary.totalPlugins).toBe(2);
254
258
  });
255
259
  });
@@ -0,0 +1,175 @@
1
+ ---
2
+ name: registry-loader
3
+ description: |
4
+ Load the skill catalog for workflow building. This skill should be used when
5
+ discovering available looplia skills or listing what capabilities are available. Use when
6
+ someone says "what looplia skills are installed", "list available skills", "/build",
7
+ "what can looplia do", or "show me all looplia capabilities".
8
+
9
+ v0.7.0: Replaces plugin-registry-scanner with skill catalog for faster access.
10
+ Auto-syncs from all sources on every build to ensure freshest skill catalog.
11
+ tools: Read
12
+ model: claude-haiku-4-5-20251001
13
+ ---
14
+
15
+ # Registry Loader
16
+
17
+ Load the skill catalog for workflow building and skill discovery.
18
+
19
+ ## Purpose
20
+
21
+ Provides fast access to the skill catalog for the build pipeline.
22
+ Uses the pre-compiled `~/.looplia/registry/skill-catalog.json` instead of runtime scanning.
23
+
24
+ ## Behavior
25
+
26
+ 1. Read the skill catalog from `~/.looplia/registry/skill-catalog.json`
27
+ 2. If catalog doesn't exist, return empty registry with instructions to run `looplia registry sync`
28
+ 3. Return catalog data for skill-capability-matcher
29
+
30
+ ## Process
31
+
32
+ ### 1. Load Skill Catalog
33
+
34
+ Read the skill catalog file:
35
+
36
+ ```bash
37
+ cat ~/.looplia/registry/skill-catalog.json
38
+ ```
39
+
40
+ Or use the Read tool to access the file directly.
41
+
42
+ ### 2. Parse Catalog Data
43
+
44
+ The skill catalog contains:
45
+
46
+ ```json
47
+ {
48
+ "compiledAt": "2026-01-04T12:00:00Z",
49
+ "version": "1.0.0",
50
+ "sources": [
51
+ {
52
+ "id": "official",
53
+ "type": "official",
54
+ "url": "https://github.com/memorysaver/looplia-core/releases/latest/download/registry.json",
55
+ "enabled": true,
56
+ "priority": 100
57
+ }
58
+ ],
59
+ "skills": [
60
+ {
61
+ "name": "media-reviewer",
62
+ "title": "Media Reviewer",
63
+ "description": "Deep content analysis (structure, themes, narrative)",
64
+ "plugin": "looplia-writer",
65
+ "category": "analysis",
66
+ "capabilities": ["content-analysis", "media-processing"],
67
+ "tools": ["Read", "Grep", "Glob"],
68
+ "model": "claude-haiku-4-5-20251001",
69
+ "source": "local",
70
+ "sourceType": "builtin",
71
+ "installed": true,
72
+ "installedPath": "/home/user/.looplia/looplia-writer/skills/media-reviewer"
73
+ }
74
+ ],
75
+ "summary": {
76
+ "totalSkills": 14,
77
+ "byCategory": {
78
+ "analysis": 3,
79
+ "generation": 2,
80
+ "assembly": 2,
81
+ "validation": 1,
82
+ "search": 1,
83
+ "orchestration": 3,
84
+ "utility": 2
85
+ },
86
+ "bySource": {
87
+ "local": 14
88
+ }
89
+ }
90
+ }
91
+ ```
92
+
93
+ ### 3. Format for skill-capability-matcher
94
+
95
+ Transform the skill catalog into the format expected by skill-capability-matcher:
96
+
97
+ ```json
98
+ {
99
+ "plugins": [
100
+ {
101
+ "name": "looplia-writer",
102
+ "path": "~/.looplia/looplia-writer",
103
+ "skills": [
104
+ {
105
+ "name": "media-reviewer",
106
+ "description": "Deep content analysis (structure, themes, narrative)",
107
+ "tools": ["Read", "Grep", "Glob"],
108
+ "model": "haiku",
109
+ "capabilities": ["content-analysis", "media-processing"],
110
+ "installed": true
111
+ }
112
+ ]
113
+ }
114
+ ],
115
+ "summary": {
116
+ "totalPlugins": 2,
117
+ "totalSkills": 14,
118
+ "installedSkills": 14,
119
+ "availableSkills": 0
120
+ }
121
+ }
122
+ ```
123
+
124
+ ## Output Schema
125
+
126
+ ```json
127
+ {
128
+ "plugins": [
129
+ {
130
+ "name": "string",
131
+ "path": "string",
132
+ "skills": [
133
+ {
134
+ "name": "string",
135
+ "description": "string",
136
+ "tools": ["string"],
137
+ "model": "string",
138
+ "capabilities": ["string"],
139
+ "installed": "boolean"
140
+ }
141
+ ]
142
+ }
143
+ ],
144
+ "summary": {
145
+ "totalPlugins": "number",
146
+ "totalSkills": "number",
147
+ "installedSkills": "number",
148
+ "availableSkills": "number"
149
+ }
150
+ }
151
+ ```
152
+
153
+ ## Advantages over plugin-registry-scanner
154
+
155
+ | Aspect | plugin-registry-scanner | registry-loader (v0.7.0) |
156
+ |--------|------------------------|--------------------------|
157
+ | Speed | Scans filesystem at runtime | Reads pre-compiled JSON |
158
+ | Sources | Local only | Official + third-party |
159
+ | Installation Status | Not tracked | Included in output |
160
+ | Third-party Skills | Not discovered | Included from remote registries |
161
+
162
+ ## Usage
163
+
164
+ This skill is typically invoked as the first step in workflow building:
165
+
166
+ 1. Load skill catalog (this skill)
167
+ 2. Pass catalog to skill-capability-matcher
168
+ 3. Use matched skills in workflow-schema-composer
169
+
170
+ ## Notes
171
+
172
+ - If skill catalog doesn't exist, advise user to run `looplia registry sync`
173
+ - Catalog is auto-synced on every `looplia build` command
174
+ - Includes installation status for each skill
175
+ - Third-party skills may show `installed: false` until installed via `looplia skill add`
@@ -1,12 +1,16 @@
1
1
  ---
2
2
  name: skill-capability-matcher
3
3
  description: |
4
- This skill should be used when the user wants to find the right looplia skills for a task,
5
- match requirements to available capabilities, or determine which skills should handle each
6
- workflow step. Use when someone says "which looplia skill handles X", "find skills for this
7
- task", "match my requirements to skills", or "/build" (after registry scan).
4
+ This skill should be used when matching user requirements to available skills from a
5
+ compiled registry. It receives a skill registry (from registry-loader) and user requirements,
6
+ then scores each skill based on capability alignment, producing prioritized matches with
7
+ confidence scores.
8
8
 
9
- Second step in looplia workflow building: takes user requirements and skill registry,
9
+ Triggers: "match skills to requirements", "find relevant skills for workflow", "which skill
10
+ handles X", "score skill capabilities", "/build" (after registry load), "find skills for
11
+ this task", "match my requirements to skills".
12
+
13
+ Second step in looplia workflow building pipeline: takes user requirements and skill registry,
10
14
  recommends skill sequences with missions. Designs one workflow step → one skill-executor
11
15
  → multiple skills orchestration pattern.
12
16
  model: claude-haiku-4-5-20251001
@@ -50,16 +54,17 @@ Extract from the user's description:
50
54
 
51
55
  ### Step 2: Load Registry
52
56
 
53
- Read the plugin registry from plugin-registry-scanner output:
57
+ Read the plugin registry from registry-loader output (v0.7.0):
54
58
 
55
59
  ```json
56
60
  {
57
61
  "plugins": [...],
58
- "summary": { "totalSkills": N }
62
+ "summary": { "totalSkills": N, "installedSkills": N, "availableSkills": N }
59
63
  }
60
64
  ```
61
65
 
62
66
  Build a capability index from skill descriptions and inferred capabilities.
67
+ Include `installed` status when scoring - prefer installed skills for immediate execution.
63
68
 
64
69
  ### Step 3: Match Capabilities
65
70
 
@@ -232,6 +237,69 @@ Provide:
232
237
  | Weak/inferred match | 0.3-0.5 |
233
238
  | No clear match | < 0.3 |
234
239
 
240
+ ## Scoring Rubric
241
+
242
+ Use these concrete criteria when assigning scores:
243
+
244
+ ### Relevance Score (Primary Factor)
245
+ - **90-100**: Skill's primary purpose directly addresses requirement
246
+ - **70-89**: Skill clearly capable of addressing requirement
247
+ - **50-69**: Skill partially addresses requirement
248
+ - **30-49**: Skill tangentially related
249
+ - **0-29**: Minimal or no relevance
250
+
251
+ ### Completeness Score
252
+ - **90-100**: Skill fully addresses all aspects of requirement
253
+ - **70-89**: Skill addresses most aspects, minor gaps
254
+ - **50-69**: Skill addresses core need, notable gaps
255
+ - **Below 50**: Significant portions unaddressed
256
+
257
+ ### Specificity Score
258
+ - **90-100**: Skill specifically designed for this exact use case
259
+ - **70-89**: Skill well-suited for use case category
260
+ - **50-69**: General-purpose skill applicable to use case
261
+ - **Below 50**: Very general skill with broad applicability
262
+
263
+ ### Confidence Calculation
264
+
265
+ ```
266
+ confidence = (relevance * 0.5) + (completeness * 0.3) + (specificity * 0.2)
267
+ ```
268
+
269
+ **Minimum threshold: 60%** - Skills below this should not be recommended.
270
+
271
+ ## Semantic Matching Guidelines
272
+
273
+ Match requirements to skills beyond simple keyword matching:
274
+
275
+ ### 1. Synonym Recognition
276
+ Match conceptually equivalent terms:
277
+ - "authentication" ↔ "login", "session management", "user verification"
278
+ - "database" ↔ "data persistence", "storage", specific ORMs
279
+ - "analyze" ↔ "review", "examine", "inspect", "assess"
280
+ - "generate" ↔ "create", "produce", "synthesize", "build"
281
+
282
+ ### 2. Hierarchical Matching
283
+ Understand skill scope and specificity:
284
+ - General skill may satisfy specific requirement (e.g., "api-client" for "REST calls")
285
+ - Prefer specific skill over general when available (e.g., "stripe-integration" over "payment-api")
286
+
287
+ ### 3. Intent Extraction
288
+ Focus on what user wants to accomplish, not just keywords:
289
+ - "I need to send emails" → match email/notification skills
290
+ - "Process video content" → match media-reviewer, not just skills with "video" in name
291
+ - "Build a report from data" → match assembly/documentation skills
292
+
293
+ ## Edge Cases
294
+
295
+ | Scenario | Handling |
296
+ |----------|----------|
297
+ | No matches above 60% threshold | Return empty `recommendations[]` with `gaps` listing unmet needs |
298
+ | Multiple skills with identical scores | Prefer more specific skill (higher specificity score) |
299
+ | Ambiguous user requirements | Set `clarificationNeeded: true` with targeted questions |
300
+ | Skill matches multiple requirements | Include once with highest-scoring requirement as primary |
301
+ | Installed vs available skills | Prefer installed skills when scores are within 10% |
302
+
235
303
  ## Mission Writing Guidelines
236
304
 
237
305
  Each mission should:
@@ -6,10 +6,11 @@ description: |
6
6
  someone says "create a looplia workflow", "generate workflow.md", "compose workflow steps",
7
7
  "build me an automation pipeline", or "/build" (final step).
8
8
 
9
- Final step in looplia workflow building: transforms skill recommendations into valid v0.6.3
9
+ Final step in looplia workflow building: transforms skill recommendations into valid v0.7.0
10
10
  workflow YAML/Markdown files. Each step uses skill: + mission: syntax, following the one
11
11
  workflow step → one skill-executor → multiple skills architecture.
12
12
 
13
+ v0.7.0: Generates explicit `skills:` declaration for selective plugin loading.
13
14
  v0.6.3: Supports input-less workflows using input-less capable skills (e.g., search).
14
15
  model: claude-haiku-4-5-20251001
15
16
  ---
@@ -122,7 +123,7 @@ Based on skill output type:
122
123
  - Idea skills: `required_fields: [contentId, hooks, angles]`
123
124
  - Assembly skills: `required_fields: [contentId, suggestedOutline]`
124
125
 
125
- ### Step 6: Compose Frontmatter
126
+ ### Step 6: Compose Frontmatter (v0.7.0)
126
127
 
127
128
  **CRITICAL: If `--name` flag was provided, use that exact name. Do not derive or modify it.**
128
129
 
@@ -132,15 +133,26 @@ name: {explicit-name OR derived-from-description}
132
133
  version: 1.0.0
133
134
  description: {user's original description, cleaned up}
134
135
 
136
+ # v0.7.0: Explicit skills declaration for selective plugin loading
137
+ skills:
138
+ - {skill-name-1}
139
+ - {skill-name-2}
140
+ - ...
141
+
135
142
  steps:
136
143
  - id: ...
137
144
  ---
138
145
  ```
139
146
 
147
+ **Skills Declaration (v0.7.0):**
148
+ Extract unique skill names from all step recommendations and list them in the `skills:` field.
149
+ This enables selective plugin loading at runtime - only required skills are loaded.
150
+
140
151
  Naming rules:
141
152
  1. If `--name article-summary` was provided → use `article-summary` exactly
142
153
  2. If no `--name` → derive from description (e.g., "analyze videos" → "video-analyzer")
143
154
  3. Always use kebab-case for names
155
+ 4. Always include `skills:` field with all unique skills from steps
144
156
 
145
157
  ### Step 7: Generate Markdown Body
146
158
 
@@ -216,6 +228,12 @@ name: video-to-blog
216
228
  version: 1.0.0
217
229
  description: Analyze YouTube videos and create blog outlines
218
230
 
231
+ # v0.7.0: Explicit skills declaration for selective plugin loading
232
+ skills:
233
+ - media-reviewer
234
+ - idea-synthesis
235
+ - writing-kit-assembler
236
+
219
237
  steps:
220
238
  - id: analyze-content
221
239
  skill: media-reviewer
@@ -281,6 +299,7 @@ looplia run video-to-blog --file <transcript.md>
281
299
  6. **Respect --name flag** - If `--name X` is provided, the workflow MUST be named `X` and saved as `X.md`
282
300
  7. **Detect input-less workflows** - If first step uses `search` skill, OMIT input field
283
301
  8. **Incorporate user preferences (v0.6.4)** - Extract preferences from "User clarifications" and inject into step missions. Each preference MUST appear in at least one mission.
302
+ 9. **Include skills declaration (v0.7.0)** - Always add `skills:` field listing all unique skill names from steps. This enables selective plugin loading at runtime.
284
303
 
285
304
  ## Example: Input-Less Workflow (v0.6.3)
286
305
 
@@ -292,6 +311,11 @@ name: daily-news-digest
292
311
  version: 1.0.0
293
312
  description: Fetch trending news and compile a digest report
294
313
 
314
+ # v0.7.0: Explicit skills declaration
315
+ skills:
316
+ - search
317
+ - content-documenter
318
+
295
319
  steps:
296
320
  - id: fetch-news
297
321
  skill: search