@rune-kit/rune 2.1.1 → 2.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +40 -34
- package/compiler/__tests__/pack-split.test.js +145 -0
- package/compiler/adapters/antigravity.js +1 -1
- package/compiler/adapters/codex.js +77 -0
- package/compiler/adapters/cursor.js +1 -1
- package/compiler/adapters/generic.js +1 -1
- package/compiler/adapters/index.js +4 -0
- package/compiler/adapters/opencode.js +86 -0
- package/compiler/adapters/windsurf.js +1 -1
- package/compiler/bin/rune.js +10 -7
- package/compiler/doctor.js +42 -0
- package/compiler/emitter.js +64 -10
- package/compiler/parser.js +42 -3
- package/compiler/transformer.js +10 -6
- package/compiler/transforms/branding.js +1 -1
- package/compiler/transforms/compliance.js +40 -0
- package/extensions/ai-ml/PACK.md +38 -474
- package/extensions/ai-ml/skills/ai-agents.md +172 -0
- package/extensions/ai-ml/skills/code-sandbox.md +187 -0
- package/extensions/ai-ml/skills/deep-research.md +146 -0
- package/extensions/ai-ml/skills/embedding-search.md +66 -0
- package/extensions/ai-ml/skills/fine-tuning-guide.md +74 -0
- package/extensions/ai-ml/skills/llm-architect.md +125 -0
- package/extensions/ai-ml/skills/llm-integration.md +64 -0
- package/extensions/ai-ml/skills/prompt-patterns.md +72 -0
- package/extensions/ai-ml/skills/rag-patterns.md +66 -0
- package/extensions/ai-ml/skills/web-extraction.md +114 -0
- package/extensions/analytics/PACK.md +19 -484
- package/extensions/analytics/skills/ab-testing.md +72 -0
- package/extensions/analytics/skills/dashboard-patterns.md +83 -0
- package/extensions/analytics/skills/data-validation.md +68 -0
- package/extensions/analytics/skills/funnel-analysis.md +81 -0
- package/extensions/analytics/skills/sql-patterns.md +57 -0
- package/extensions/analytics/skills/statistical-analysis.md +79 -0
- package/extensions/analytics/skills/tracking-setup.md +71 -0
- package/extensions/backend/PACK.md +44 -618
- package/extensions/backend/skills/api-patterns.md +84 -0
- package/extensions/backend/skills/async-pipeline.md +193 -0
- package/extensions/backend/skills/auth-patterns.md +97 -0
- package/extensions/backend/skills/background-jobs.md +133 -0
- package/extensions/backend/skills/caching-patterns.md +108 -0
- package/extensions/backend/skills/cli-generation.md +133 -0
- package/extensions/backend/skills/database-patterns.md +87 -0
- package/extensions/backend/skills/middleware-patterns.md +104 -0
- package/extensions/chrome-ext/PACK.md +19 -921
- package/extensions/chrome-ext/skills/cws-preflight.md +143 -0
- package/extensions/chrome-ext/skills/cws-publish.md +104 -0
- package/extensions/chrome-ext/skills/ext-ai-integration.md +251 -0
- package/extensions/chrome-ext/skills/ext-messaging.md +139 -0
- package/extensions/chrome-ext/skills/ext-storage.md +133 -0
- package/extensions/chrome-ext/skills/mv3-scaffold.md +164 -0
- package/extensions/content/PACK.md +43 -335
- package/extensions/content/skills/blog-patterns.md +88 -0
- package/extensions/content/skills/cms-integration.md +131 -0
- package/extensions/content/skills/content-scoring.md +107 -0
- package/extensions/content/skills/i18n.md +83 -0
- package/extensions/content/skills/mdx-authoring.md +137 -0
- package/extensions/content/skills/reference.md +1014 -0
- package/extensions/content/skills/seo-patterns.md +67 -0
- package/extensions/content/skills/video-repurpose.md +153 -0
- package/extensions/devops/PACK.md +38 -457
- package/extensions/devops/skills/chaos-testing.md +67 -0
- package/extensions/devops/skills/ci-cd.md +75 -0
- package/extensions/devops/skills/docker.md +58 -0
- package/extensions/devops/skills/edge-serverless.md +163 -0
- package/extensions/devops/skills/infra-as-code.md +158 -0
- package/extensions/devops/skills/kubernetes.md +110 -0
- package/extensions/devops/skills/monitoring.md +57 -0
- package/extensions/devops/skills/server-setup.md +64 -0
- package/extensions/devops/skills/ssl-domain.md +42 -0
- package/extensions/ecommerce/PACK.md +62 -226
- package/extensions/ecommerce/skills/cart-system.md +79 -0
- package/extensions/ecommerce/skills/inventory-mgmt.md +102 -0
- package/extensions/ecommerce/skills/order-management.md +126 -0
- package/extensions/ecommerce/skills/payment-integration.md +472 -0
- package/extensions/ecommerce/skills/shopify-dev.md +69 -0
- package/extensions/ecommerce/skills/subscription-billing.md +93 -0
- package/extensions/ecommerce/skills/tax-compliance.md +117 -0
- package/extensions/gamedev/PACK.md +66 -317
- package/extensions/gamedev/skills/asset-pipeline.md +74 -0
- package/extensions/gamedev/skills/audio-system.md +129 -0
- package/extensions/gamedev/skills/camera-system.md +87 -0
- package/extensions/gamedev/skills/ecs.md +98 -0
- package/extensions/gamedev/skills/game-loops.md +72 -0
- package/extensions/gamedev/skills/input-system.md +199 -0
- package/extensions/gamedev/skills/multiplayer.md +180 -0
- package/extensions/gamedev/skills/particles.md +105 -0
- package/extensions/gamedev/skills/physics-engine.md +89 -0
- package/extensions/gamedev/skills/scene-management.md +146 -0
- package/extensions/gamedev/skills/threejs-patterns.md +90 -0
- package/extensions/gamedev/skills/webgl.md +71 -0
- package/extensions/mobile/PACK.md +56 -223
- package/extensions/mobile/skills/app-store-connect.md +152 -0
- package/extensions/mobile/skills/app-store-prep.md +66 -0
- package/extensions/mobile/skills/deep-linking.md +109 -0
- package/extensions/mobile/skills/flutter.md +60 -0
- package/extensions/mobile/skills/ios-build-pipeline.md +142 -0
- package/extensions/mobile/skills/native-bridge.md +66 -0
- package/extensions/mobile/skills/ota-updates.md +97 -0
- package/extensions/mobile/skills/push-notifications.md +111 -0
- package/extensions/mobile/skills/react-native.md +82 -0
- package/extensions/saas/PACK.md +26 -720
- package/extensions/saas/skills/billing-integration.md +121 -0
- package/extensions/saas/skills/feature-flags.md +130 -0
- package/extensions/saas/skills/multi-tenant.md +103 -0
- package/extensions/saas/skills/onboarding-flow.md +139 -0
- package/extensions/saas/skills/subscription-flow.md +95 -0
- package/extensions/saas/skills/team-management.md +144 -0
- package/extensions/security/PACK.md +10 -448
- package/extensions/security/skills/api-security.md +140 -0
- package/extensions/security/skills/compliance.md +68 -0
- package/extensions/security/skills/owasp-audit.md +64 -0
- package/extensions/security/skills/pentest-patterns.md +77 -0
- package/extensions/security/skills/secret-mgmt.md +65 -0
- package/extensions/security/skills/supply-chain.md +65 -0
- package/extensions/trading/PACK.md +18 -535
- package/extensions/trading/skills/chart-components.md +55 -0
- package/extensions/trading/skills/experiment-loop.md +125 -0
- package/extensions/trading/skills/fintech-patterns.md +47 -0
- package/extensions/trading/skills/indicator-library.md +58 -0
- package/extensions/trading/skills/quant-analysis.md +111 -0
- package/extensions/trading/skills/realtime-data.md +58 -0
- package/extensions/trading/skills/trade-logic.md +104 -0
- package/extensions/ui/PACK.md +34 -853
- package/extensions/ui/skills/a11y-audit.md +91 -0
- package/extensions/ui/skills/animation-patterns.md +106 -0
- package/extensions/ui/skills/component-patterns.md +75 -0
- package/extensions/ui/skills/design-decision.md +98 -0
- package/extensions/ui/skills/design-system.md +68 -0
- package/extensions/ui/skills/landing-patterns.md +155 -0
- package/extensions/ui/skills/palette-picker.md +162 -0
- package/extensions/ui/skills/react-health.md +90 -0
- package/extensions/ui/skills/type-system.md +125 -0
- package/extensions/ui/skills/web-vitals.md +153 -0
- package/extensions/zalo/PACK.md +117 -0
- package/extensions/zalo/skills/zalo-oa-mcp.md +317 -0
- package/extensions/zalo/skills/zalo-oa-messaging.md +429 -0
- package/extensions/zalo/skills/zalo-oa-setup.md +236 -0
- package/extensions/zalo/skills/zalo-oa-webhook.md +189 -0
- package/extensions/zalo/skills/zalo-personal-messaging.md +194 -0
- package/extensions/zalo/skills/zalo-personal-setup.md +153 -0
- package/extensions/zalo/skills/zalo-rate-guard.md +219 -0
- package/package.json +5 -2
- package/skills/brainstorm/SKILL.md +63 -1
- package/skills/cook/SKILL.md +89 -6
- package/skills/debug/SKILL.md +5 -0
- package/skills/fix/SKILL.md +5 -0
- package/skills/mcp-builder/SKILL.md +48 -1
- package/skills/neural-memory/SKILL.md +362 -0
- package/skills/plan/SKILL.md +3 -0
- package/skills/rescue/SKILL.md +5 -0
- package/skills/review/SKILL.md +44 -5
- package/skills/review-intake/SKILL.md +17 -1
- package/skills/skill-router/SKILL.md +106 -8
- package/skills/team/SKILL.md +24 -1
- package/skills/test/SKILL.md +18 -0
- package/skills/verification/SKILL.md +40 -1
package/README.md
CHANGED
|
@@ -2,15 +2,15 @@
|
|
|
2
2
|
|
|
3
3
|
**Less skills. Deeper connections.**
|
|
4
4
|
|
|
5
|
-
A lean, interconnected skill ecosystem for AI coding assistants.
|
|
5
|
+
A lean, interconnected skill ecosystem for AI coding assistants. 58 skills, 200+ mesh connections, full project lifecycle — from idea to production.
|
|
6
6
|
|
|
7
|
-
Works on **Claude Code** (native plugin) · **Cursor** · **Windsurf** · **Google Antigravity** · any AI IDE
|
|
7
|
+
Works on **Claude Code** (native plugin) · **Cursor** · **Windsurf** · **Google Antigravity** · **OpenAI Codex** · **OpenCode** · any AI IDE
|
|
8
8
|
|
|
9
9
|
## Why Rune?
|
|
10
10
|
|
|
11
11
|
Most skill ecosystems are either **too many isolated skills** (540+ that don't talk to each other) or **rigid pipelines** (A → B → C, if B fails everything stops).
|
|
12
12
|
|
|
13
|
-
Rune is a **mesh** —
|
|
13
|
+
Rune is a **mesh** — 58 skills with 200+ connections across a 5-layer architecture. Skills call each other bidirectionally, forming resilient workflows that adapt when things go wrong.
|
|
14
14
|
|
|
15
15
|
```
|
|
16
16
|
Pipeline: A → B → C → D (B fails = stuck)
|
|
@@ -20,24 +20,23 @@ Mesh: A ↔ B ↔ C (B fails = A reaches C via D→E)
|
|
|
20
20
|
D ↔ E ↔ F
|
|
21
21
|
```
|
|
22
22
|
|
|
23
|
-
## What's New (v2.1
|
|
23
|
+
## What's New (v2.2.1)
|
|
24
24
|
|
|
25
|
-
- **
|
|
26
|
-
- **
|
|
27
|
-
- **
|
|
28
|
-
- **
|
|
29
|
-
- **
|
|
30
|
-
- **Multi-Platform Compiler** — all 55 skills compile to Cursor, Windsurf, Antigravity, and generic formats with zero knowledge loss
|
|
25
|
+
- **Enforcement Upgrade** — Antigravity-level IDE compliance: 5-type Request Classifier, File Ownership Matrix, Self-Verification HARD-GATE, Routing Proof, Clarification Gate, Phase Transition Protocol. Distributed via compiler — every skill file gets compliance preamble on non-Claude platforms
|
|
26
|
+
- **All 14 Free Packs Deep** — every L4 extension pack now exceeds 500 lines of production-ready patterns and code examples
|
|
27
|
+
- **8 Platform Adapters** — Claude Code, Cursor, Windsurf, Google Antigravity, OpenAI Codex, OpenCode, OpenClaw, Generic
|
|
28
|
+
- **58 Core Skills** — +3 since v2.1.0: adversary (red team), sentinel-env (env validation), chrome-ext pack
|
|
29
|
+
- **Rune Pro** — 4 premium packs (product, sales, data-science, support) in private repo. $49 lifetime
|
|
31
30
|
|
|
32
31
|
## What Rune Is (and Isn't)
|
|
33
32
|
|
|
34
|
-
Rune started as a **Claude Code plugin** and now compiles to **every major AI IDE**. Same
|
|
33
|
+
Rune started as a **Claude Code plugin** and now compiles to **every major AI IDE**. Same 58 skills, same mesh connections, same workflows — zero knowledge loss across platforms.
|
|
35
34
|
|
|
36
35
|
| | Rune Provides | Claude Code Provides |
|
|
37
36
|
|---|---|---|
|
|
38
37
|
| **Workflows** | 8-phase TDD cycle (cook), parallel DAG execution (team), rescue pipelines | Basic tool calling |
|
|
39
38
|
| **Quality Gates** | preflight + sentinel + review + completion-gate (parallel) | None built-in |
|
|
40
|
-
| **Domain Knowledge** |
|
|
39
|
+
| **Domain Knowledge** | 14 extension packs (trading, SaaS, mobile, etc.) | General-purpose |
|
|
41
40
|
| **Cross-Session State** | .rune/ directory (decisions, conventions, progress) | Conversation only |
|
|
42
41
|
| **Mesh Resilience** | 200+ skill connections, fail-loud-route-around | Linear execution |
|
|
43
42
|
| **Cost Optimization** | Auto model selection (haiku/sonnet/opus per task) | Single model |
|
|
@@ -55,7 +54,7 @@ Rune started as a **Claude Code plugin** and now compiles to **every major AI ID
|
|
|
55
54
|
| CI quality gates | `verification` skill: lint + typecheck + tests + build (actual commands, not LLM review) |
|
|
56
55
|
| Memory / state | `session-bridge` + `journal`: cross-session decisions, conventions, ADRs, module health |
|
|
57
56
|
| Multi-model strategy | Every skill has assigned model: haiku (scan), sonnet (code), opus (architecture) |
|
|
58
|
-
| Agent specialization |
|
|
57
|
+
| Agent specialization | 58 specialized skills with dedicated roles (architect, coder, reviewer, scanner, researcher, BA, scaffolder) — each runs as a Task agent via Claude Code |
|
|
59
58
|
| Security scanning | `sentinel`: OWASP patterns, secret scanning, dependency audit. `sast`: static analysis |
|
|
60
59
|
|
|
61
60
|
## Install
|
|
@@ -82,16 +81,16 @@ npx @rune-kit/rune init --platform windsurf
|
|
|
82
81
|
npx @rune-kit/rune init --platform antigravity
|
|
83
82
|
```
|
|
84
83
|
|
|
85
|
-
This compiles all
|
|
84
|
+
This compiles all 58 skills into your IDE's rules format. Same knowledge, same workflows.
|
|
86
85
|
|
|
87
86
|
### Platform Comparison
|
|
88
87
|
|
|
89
88
|
| Feature | Claude Code | Cursor / Windsurf / Others |
|
|
90
89
|
|---------|-------------|---------------------------|
|
|
91
|
-
| Skills available |
|
|
90
|
+
| Skills available | 58/58 | 58/58 |
|
|
92
91
|
| Mesh connections | 200+ (programmatic) | 200+ (rule references) |
|
|
93
92
|
| Workflows & HARD-GATEs | Full | Full |
|
|
94
|
-
| Extension packs |
|
|
93
|
+
| Extension packs | 14 | 14 |
|
|
95
94
|
| Subagent parallelism | Native | Sequential fallback |
|
|
96
95
|
| Lifecycle hooks | 8 hooks (JS runtime) | Inline MUST/NEVER constraints |
|
|
97
96
|
| Adaptive model routing | haiku/sonnet/opus | Single model |
|
|
@@ -153,7 +152,7 @@ This compiles all 55 skills into your IDE's rules format. Same knowledge, same w
|
|
|
153
152
|
║ Full lifecycle workflows ║
|
|
154
153
|
║ cook │ team │ launch │ rescue │ scaffold ║
|
|
155
154
|
╠══════════════════════════════════════════════════════╣
|
|
156
|
-
║ L2: WORKFLOW HUBS (
|
|
155
|
+
║ L2: WORKFLOW HUBS (27) ║
|
|
157
156
|
║ Cross-hub mesh — the key differentiator ║
|
|
158
157
|
║ ║
|
|
159
158
|
║ Creation: plan │ scout │ brainstorm │ design │ ║
|
|
@@ -164,8 +163,9 @@ This compiles all 55 skills into your IDE's rules format. Same knowledge, same w
|
|
|
164
163
|
║ logic-guardian ║
|
|
165
164
|
║ Delivery: deploy │ marketing │ incident │ docs ║
|
|
166
165
|
║ Rescue: autopsy │ safeguard │ surgeon ║
|
|
166
|
+
║ Security: adversary ║
|
|
167
167
|
╠══════════════════════════════════════════════════════╣
|
|
168
|
-
║ L3: UTILITIES (
|
|
168
|
+
║ L3: UTILITIES (25) ║
|
|
169
169
|
║ Stateless, pure capabilities ║
|
|
170
170
|
║ ║
|
|
171
171
|
║ Knowledge: research │ docs-seeker │ trend-scout ║
|
|
@@ -182,14 +182,17 @@ This compiles all 55 skills into your IDE's rules format. Same knowledge, same w
|
|
|
182
182
|
║ Workspace: worktree ║
|
|
183
183
|
║ Git: git ║
|
|
184
184
|
║ Documents: doc-processor ║
|
|
185
|
+
║ Security: sentinel-env ║
|
|
186
|
+
║ Memory: neural-memory ║
|
|
185
187
|
╠══════════════════════════════════════════════════════╣
|
|
186
|
-
║ L4: EXTENSION PACKS (
|
|
188
|
+
║ L4: EXTENSION PACKS (14) ║
|
|
187
189
|
║ Domain-specific, install what you need ║
|
|
188
190
|
║ ║
|
|
189
191
|
║ @rune/ui │ @rune/backend │ @rune/devops │ ║
|
|
190
192
|
║ @rune/mobile │ @rune/security │ @rune/trading │ ║
|
|
191
193
|
║ @rune/saas │ @rune/ecommerce │ @rune/ai-ml │ ║
|
|
192
|
-
║ @rune/gamedev │ @rune/content │ @rune/analytics
|
|
194
|
+
║ @rune/gamedev │ @rune/content │ @rune/analytics │ ║
|
|
195
|
+
║ @rune/chrome-ext │ @rune/zalo ║
|
|
193
196
|
╚══════════════════════════════════════════════════════╝
|
|
194
197
|
```
|
|
195
198
|
|
|
@@ -310,8 +313,9 @@ Business department packs for product, sales, and data teams. Same PACK.md forma
|
|
|
310
313
|
| @rune-pro/product | feature-spec, roadmap, metrics, release-comms, user-research, competitive | Product Management |
|
|
311
314
|
| @rune-pro/sales | account-research, call-prep, outreach, pipeline-review, competitive-intel | Sales Enablement |
|
|
312
315
|
| @rune-pro/data-science | data-exploration, sql-advanced, visualization, statistical-testing, dashboards | Data Science |
|
|
316
|
+
| @rune-pro/support | ticket-triage, response-drafting, knowledge-base, escalation, faq, metrics | Customer Support |
|
|
313
317
|
|
|
314
|
-
|
|
318
|
+
**$49 lifetime** (Pro) · **$149 lifetime** (Business). See [docs/plans/RUNE-PRO-PLAN.md](docs/plans/RUNE-PRO-PLAN.md).
|
|
315
319
|
|
|
316
320
|
## Multi-Platform Compiler
|
|
317
321
|
|
|
@@ -321,13 +325,14 @@ Rune includes a 3-stage compiler that transforms SKILL.md files into platform-na
|
|
|
321
325
|
skills/*.md → PARSE → TRANSFORM → EMIT → platform rules
|
|
322
326
|
```
|
|
323
327
|
|
|
324
|
-
**
|
|
325
|
-
1.
|
|
326
|
-
2.
|
|
327
|
-
3.
|
|
328
|
+
**8 transforms applied per platform:**
|
|
329
|
+
1. Frontmatter: strip Claude Code-specific directives
|
|
330
|
+
2. Cross-references: `rune:cook` → `@rune-cook.mdc` (Cursor) / prose ref (Windsurf)
|
|
331
|
+
3. Tool names: `Read`, `Edit`, `Bash` → generic language
|
|
328
332
|
4. Subagents: parallel → sequential workflow
|
|
329
|
-
5.
|
|
330
|
-
6.
|
|
333
|
+
5. Compliance: inject enforcement preamble (non-Claude platforms)
|
|
334
|
+
6. Hooks: runtime hooks → inline MUST/NEVER constraints
|
|
335
|
+
7. Branding: Rune attribution footer
|
|
331
336
|
|
|
332
337
|
```bash
|
|
333
338
|
# Build for any platform
|
|
@@ -343,13 +348,14 @@ See [docs/MULTI-PLATFORM.md](docs/MULTI-PLATFORM.md) for the full architecture.
|
|
|
343
348
|
## Numbers
|
|
344
349
|
|
|
345
350
|
```
|
|
346
|
-
Core Skills:
|
|
347
|
-
Extension Packs:
|
|
348
|
-
Mesh Connections:
|
|
349
|
-
Connections/Skill: 3.
|
|
350
|
-
Platforms:
|
|
351
|
-
Compiler: ~
|
|
352
|
-
Quality:
|
|
351
|
+
Core Skills: 58 (L0: 1 │ L1: 5 │ L2: 27 │ L3: 25)
|
|
352
|
+
Extension Packs: 14 free + 4 pro + 2 business
|
|
353
|
+
Mesh Connections: 200+ cross-references
|
|
354
|
+
Connections/Skill: 3.4 avg
|
|
355
|
+
Platforms: 8 (Claude Code, Cursor, Windsurf, Antigravity, Codex, OpenCode, OpenClaw, Generic)
|
|
356
|
+
Compiler: ~1400 LOC (parser + 8 transforms + 8 adapters + CLI)
|
|
357
|
+
Quality: 58/58 skills with Output Format, Sharp Edges, Done When, Cost Profile
|
|
358
|
+
Pack Depth: 20 packs total (14 free + 4 pro + 2 business, all free packs rated Deep)
|
|
353
359
|
```
|
|
354
360
|
|
|
355
361
|
## License
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
import { parsePack, parseSkill } from '../parser.js';
|
|
2
|
+
import { test } from 'node:test';
|
|
3
|
+
import assert from 'node:assert';
|
|
4
|
+
import { readFileSync, existsSync } from 'node:fs';
|
|
5
|
+
import path from 'node:path';
|
|
6
|
+
import { fileURLToPath } from 'node:url';
|
|
7
|
+
|
|
8
|
+
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
9
|
+
const EXTENSIONS_DIR = path.resolve(__dirname, '../../extensions');
|
|
10
|
+
|
|
11
|
+
// --- Monolith format (regression) ---
|
|
12
|
+
|
|
13
|
+
test('parsePack: monolith format has isSplit=false', () => {
|
|
14
|
+
const content = `---
|
|
15
|
+
name: "@rune/trading"
|
|
16
|
+
description: "Trading patterns"
|
|
17
|
+
metadata:
|
|
18
|
+
version: "0.2.0"
|
|
19
|
+
layer: L4
|
|
20
|
+
price: free
|
|
21
|
+
target: Traders
|
|
22
|
+
---
|
|
23
|
+
|
|
24
|
+
# @rune/trading
|
|
25
|
+
|
|
26
|
+
## Purpose
|
|
27
|
+
Trading pack.
|
|
28
|
+
|
|
29
|
+
## Skills Included
|
|
30
|
+
|
|
31
|
+
### risk-management
|
|
32
|
+
Risk management workflow.
|
|
33
|
+
`;
|
|
34
|
+
|
|
35
|
+
const parsed = parsePack(content, 'extensions/trading/PACK.md');
|
|
36
|
+
|
|
37
|
+
assert.strictEqual(parsed.isSplit, false);
|
|
38
|
+
assert.deepStrictEqual(parsed.skillManifest, []);
|
|
39
|
+
assert.strictEqual(parsed.name, '@rune/trading');
|
|
40
|
+
assert.strictEqual(parsed.version, '0.2.0');
|
|
41
|
+
assert.strictEqual(parsed.layer, 'L4');
|
|
42
|
+
assert.ok(parsed.body.includes('risk-management'));
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
test('parsePack: monolith without metadata block defaults correctly', () => {
|
|
46
|
+
const content = `---
|
|
47
|
+
name: "@rune/test"
|
|
48
|
+
description: "Test pack"
|
|
49
|
+
---
|
|
50
|
+
|
|
51
|
+
# @rune/test
|
|
52
|
+
Body here.
|
|
53
|
+
`;
|
|
54
|
+
|
|
55
|
+
const parsed = parsePack(content, 'test/PACK.md');
|
|
56
|
+
|
|
57
|
+
assert.strictEqual(parsed.isSplit, false);
|
|
58
|
+
assert.strictEqual(parsed.version, '1.0.0');
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
// --- Split format detection ---
|
|
62
|
+
|
|
63
|
+
test('parsePack: split format detected via metadata.format', () => {
|
|
64
|
+
const content = `---
|
|
65
|
+
name: "@rune/backend"
|
|
66
|
+
description: "Backend patterns"
|
|
67
|
+
metadata:
|
|
68
|
+
version: "0.3.0"
|
|
69
|
+
layer: L4
|
|
70
|
+
price: free
|
|
71
|
+
target: Backend developers
|
|
72
|
+
format: split
|
|
73
|
+
---
|
|
74
|
+
|
|
75
|
+
# @rune/backend
|
|
76
|
+
|
|
77
|
+
## Purpose
|
|
78
|
+
Backend pack index.
|
|
79
|
+
|
|
80
|
+
## Skills Included
|
|
81
|
+
| Skill | Model | Description |
|
|
82
|
+
|-------|-------|-------------|
|
|
83
|
+
| api-design | sonnet | API patterns |
|
|
84
|
+
| auth | sonnet | Auth patterns |
|
|
85
|
+
`;
|
|
86
|
+
|
|
87
|
+
const parsed = parsePack(content, 'extensions/backend/PACK.md');
|
|
88
|
+
|
|
89
|
+
assert.strictEqual(parsed.isSplit, true);
|
|
90
|
+
assert.strictEqual(parsed.version, '0.3.0');
|
|
91
|
+
assert.strictEqual(parsed.name, '@rune/backend');
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
test('parsePack: skill manifest parsed from string array', () => {
|
|
95
|
+
// Note: our YAML parser is simple — it handles nested objects but not arrays.
|
|
96
|
+
// This test validates the parseSkillManifest function directly with object skills.
|
|
97
|
+
const content = `---
|
|
98
|
+
name: "@rune/test"
|
|
99
|
+
description: "Test"
|
|
100
|
+
metadata:
|
|
101
|
+
format: split
|
|
102
|
+
---
|
|
103
|
+
|
|
104
|
+
Body.
|
|
105
|
+
`;
|
|
106
|
+
|
|
107
|
+
const parsed = parsePack(content, 'test/PACK.md');
|
|
108
|
+
assert.strictEqual(parsed.isSplit, true);
|
|
109
|
+
// With simple YAML parser, skills array won't parse — manifest will be empty
|
|
110
|
+
// Real usage will use the skills/ directory detection as fallback
|
|
111
|
+
assert.ok(Array.isArray(parsed.skillManifest));
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
// --- Real pack regression: existing monolith packs parse correctly ---
|
|
115
|
+
|
|
116
|
+
test('parsePack: real trading PACK.md parses as split', () => {
|
|
117
|
+
const tradingPath = path.join(EXTENSIONS_DIR, 'trading', 'PACK.md');
|
|
118
|
+
if (!existsSync(tradingPath)) {
|
|
119
|
+
console.log(' skip: trading PACK.md not found');
|
|
120
|
+
return;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
const content = readFileSync(tradingPath, 'utf-8');
|
|
124
|
+
const parsed = parsePack(content, tradingPath);
|
|
125
|
+
|
|
126
|
+
assert.strictEqual(parsed.isSplit, true);
|
|
127
|
+
assert.strictEqual(parsed.layer, 'L4');
|
|
128
|
+
assert.strictEqual(parsed.group, 'extension');
|
|
129
|
+
assert.ok(parsed.body.length > 50);
|
|
130
|
+
});
|
|
131
|
+
|
|
132
|
+
test('parsePack: real backend PACK.md parses as split (post-split)', () => {
|
|
133
|
+
const backendPath = path.join(EXTENSIONS_DIR, 'backend', 'PACK.md');
|
|
134
|
+
if (!existsSync(backendPath)) {
|
|
135
|
+
console.log(' skip: backend PACK.md not found');
|
|
136
|
+
return;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
const content = readFileSync(backendPath, 'utf-8');
|
|
140
|
+
const parsed = parsePack(content, backendPath);
|
|
141
|
+
|
|
142
|
+
assert.strictEqual(parsed.isSplit, true);
|
|
143
|
+
assert.strictEqual(parsed.layer, 'L4');
|
|
144
|
+
assert.ok(parsed.sections.size > 0);
|
|
145
|
+
});
|
|
@@ -41,7 +41,7 @@ export default {
|
|
|
41
41
|
return [
|
|
42
42
|
'',
|
|
43
43
|
'---',
|
|
44
|
-
'> **Rune Skill Mesh** —
|
|
44
|
+
'> **Rune Skill Mesh** — 58 skills, 200+ connections',
|
|
45
45
|
'> Source: https://github.com/rune-kit/rune',
|
|
46
46
|
'> Full experience with subagents, hooks, adaptive routing → use Rune on Claude Code.',
|
|
47
47
|
].join('\n');
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OpenAI Codex Adapter
|
|
3
|
+
*
|
|
4
|
+
* Emits SKILL.md files into .codex/skills/{name}/ directories.
|
|
5
|
+
* Codex uses the same SKILL.md frontmatter format (name, description)
|
|
6
|
+
* with markdown body — very close to Rune's native format.
|
|
7
|
+
*
|
|
8
|
+
* Codex project context: AGENTS.md (equivalent to CLAUDE.md)
|
|
9
|
+
* Codex skills dir: .codex/skills/
|
|
10
|
+
* Codex skill format: .codex/skills/{name}/SKILL.md
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
const TOOL_MAP = {
|
|
14
|
+
Read: 'read the file',
|
|
15
|
+
Write: 'write/create the file',
|
|
16
|
+
Edit: 'edit the file',
|
|
17
|
+
Glob: 'find files by pattern',
|
|
18
|
+
Grep: 'search file contents',
|
|
19
|
+
Bash: 'run a shell command',
|
|
20
|
+
TodoWrite: 'track task progress',
|
|
21
|
+
Skill: 'follow the referenced skill',
|
|
22
|
+
Agent: 'execute the workflow',
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
export default {
|
|
26
|
+
name: 'codex',
|
|
27
|
+
outputDir: '.codex/skills',
|
|
28
|
+
fileExtension: '.md',
|
|
29
|
+
skillPrefix: 'rune-',
|
|
30
|
+
skillSuffix: '',
|
|
31
|
+
|
|
32
|
+
// Codex uses directory-per-skill: .codex/skills/{name}/SKILL.md
|
|
33
|
+
useSkillDirectories: true,
|
|
34
|
+
skillFileName: 'SKILL.md',
|
|
35
|
+
|
|
36
|
+
transformReference(skillName, raw) {
|
|
37
|
+
const isBackticked = raw.startsWith('`') && raw.endsWith('`');
|
|
38
|
+
const ref = `the rune-${skillName} skill`;
|
|
39
|
+
return isBackticked ? `\`${ref}\`` : ref;
|
|
40
|
+
},
|
|
41
|
+
|
|
42
|
+
transformToolName(toolName) {
|
|
43
|
+
return TOOL_MAP[toolName] || toolName;
|
|
44
|
+
},
|
|
45
|
+
|
|
46
|
+
generateHeader(skill) {
|
|
47
|
+
const desc = (skill.description || '').replace(/"/g, '\\"');
|
|
48
|
+
return [
|
|
49
|
+
'---',
|
|
50
|
+
`name: rune-${skill.name}`,
|
|
51
|
+
`description: "${desc}"`,
|
|
52
|
+
'---',
|
|
53
|
+
'',
|
|
54
|
+
'',
|
|
55
|
+
].join('\n');
|
|
56
|
+
},
|
|
57
|
+
|
|
58
|
+
generateFooter() {
|
|
59
|
+
return [
|
|
60
|
+
'',
|
|
61
|
+
'---',
|
|
62
|
+
'> **Rune Skill Mesh** — 58 skills, 200+ connections',
|
|
63
|
+
'> Source: https://github.com/rune-kit/rune',
|
|
64
|
+
'> Full experience with subagents, hooks, adaptive routing → use Rune on Claude Code.',
|
|
65
|
+
].join('\n');
|
|
66
|
+
},
|
|
67
|
+
|
|
68
|
+
transformSubagentInstruction(text) {
|
|
69
|
+
return text;
|
|
70
|
+
},
|
|
71
|
+
|
|
72
|
+
postProcess(content) {
|
|
73
|
+
return content
|
|
74
|
+
.replace(/^context: fork\n/gm, '')
|
|
75
|
+
.replace(/^agent: general-purpose\n/gm, '');
|
|
76
|
+
},
|
|
77
|
+
};
|
|
@@ -49,7 +49,7 @@ export default {
|
|
|
49
49
|
return [
|
|
50
50
|
'',
|
|
51
51
|
'---',
|
|
52
|
-
'> **Rune Skill Mesh** —
|
|
52
|
+
'> **Rune Skill Mesh** — 58 skills, 200+ connections',
|
|
53
53
|
'> Source: https://github.com/rune-kit/rune',
|
|
54
54
|
'> Full experience with subagents, hooks, adaptive routing → use Rune on Claude Code.',
|
|
55
55
|
].join('\n');
|
|
@@ -42,7 +42,7 @@ export default {
|
|
|
42
42
|
return [
|
|
43
43
|
'',
|
|
44
44
|
'---',
|
|
45
|
-
'> **Rune Skill Mesh** —
|
|
45
|
+
'> **Rune Skill Mesh** — 58 skills, 200+ connections',
|
|
46
46
|
'> Source: https://github.com/rune-kit/rune',
|
|
47
47
|
'> Full experience with subagents, hooks, adaptive routing → use Rune on Claude Code.',
|
|
48
48
|
].join('\n');
|
|
@@ -10,6 +10,8 @@ import windsurf from './windsurf.js';
|
|
|
10
10
|
import antigravity from './antigravity.js';
|
|
11
11
|
import generic from './generic.js';
|
|
12
12
|
import openclaw from './openclaw.js';
|
|
13
|
+
import codex from './codex.js';
|
|
14
|
+
import opencode from './opencode.js';
|
|
13
15
|
|
|
14
16
|
const adapters = {
|
|
15
17
|
claude,
|
|
@@ -18,6 +20,8 @@ const adapters = {
|
|
|
18
20
|
antigravity,
|
|
19
21
|
generic,
|
|
20
22
|
openclaw,
|
|
23
|
+
codex,
|
|
24
|
+
opencode,
|
|
21
25
|
};
|
|
22
26
|
|
|
23
27
|
/**
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OpenCode Adapter
|
|
3
|
+
*
|
|
4
|
+
* Emits SKILL.md files into .opencode/skills/{name}/ directories.
|
|
5
|
+
* OpenCode uses the same SKILL.md frontmatter format (name, description)
|
|
6
|
+
* with markdown body — identical to Codex pattern.
|
|
7
|
+
*
|
|
8
|
+
* OpenCode project context: AGENTS.md (+ CLAUDE.md fallback)
|
|
9
|
+
* OpenCode skills dir: .opencode/skills/
|
|
10
|
+
* OpenCode skill format: .opencode/skills/{name}/SKILL.md
|
|
11
|
+
* OpenCode agents dir: .opencode/agents/
|
|
12
|
+
*
|
|
13
|
+
* OpenCode also searches:
|
|
14
|
+
* .claude/skills/{name}/SKILL.md (Claude-compatible)
|
|
15
|
+
* .agents/skills/{name}/SKILL.md (agent-compatible)
|
|
16
|
+
*
|
|
17
|
+
* @see https://opencode.ai/docs/skills/
|
|
18
|
+
* @see https://opencode.ai/docs/agents/
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
const TOOL_MAP = {
|
|
22
|
+
Read: 'read the file',
|
|
23
|
+
Write: 'write/create the file',
|
|
24
|
+
Edit: 'edit the file',
|
|
25
|
+
Glob: 'find files by pattern',
|
|
26
|
+
Grep: 'search file contents',
|
|
27
|
+
Bash: 'run a shell command',
|
|
28
|
+
TodoWrite: 'track task progress',
|
|
29
|
+
Skill: 'invoke the named skill',
|
|
30
|
+
Agent: 'delegate to a subagent',
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
export default {
|
|
34
|
+
name: 'opencode',
|
|
35
|
+
outputDir: '.opencode/skills',
|
|
36
|
+
fileExtension: '.md',
|
|
37
|
+
skillPrefix: 'rune-',
|
|
38
|
+
skillSuffix: '',
|
|
39
|
+
|
|
40
|
+
// OpenCode uses directory-per-skill: .opencode/skills/{name}/SKILL.md
|
|
41
|
+
useSkillDirectories: true,
|
|
42
|
+
skillFileName: 'SKILL.md',
|
|
43
|
+
|
|
44
|
+
transformReference(skillName, raw) {
|
|
45
|
+
const isBackticked = raw.startsWith('`') && raw.endsWith('`');
|
|
46
|
+
const ref = `the rune-${skillName} skill`;
|
|
47
|
+
return isBackticked ? `\`${ref}\`` : ref;
|
|
48
|
+
},
|
|
49
|
+
|
|
50
|
+
transformToolName(toolName) {
|
|
51
|
+
return TOOL_MAP[toolName] || toolName;
|
|
52
|
+
},
|
|
53
|
+
|
|
54
|
+
generateHeader(skill) {
|
|
55
|
+
const desc = (skill.description || '').replace(/"/g, '\\"');
|
|
56
|
+
return [
|
|
57
|
+
'---',
|
|
58
|
+
`name: rune-${skill.name}`,
|
|
59
|
+
`description: "${desc}"`,
|
|
60
|
+
'---',
|
|
61
|
+
'',
|
|
62
|
+
'',
|
|
63
|
+
].join('\n');
|
|
64
|
+
},
|
|
65
|
+
|
|
66
|
+
generateFooter() {
|
|
67
|
+
return [
|
|
68
|
+
'',
|
|
69
|
+
'---',
|
|
70
|
+
'> **Rune Skill Mesh** — 58 skills, 200+ connections',
|
|
71
|
+
'> Source: https://github.com/rune-kit/rune',
|
|
72
|
+
'> Full experience with subagents, hooks, adaptive routing → use Rune on Claude Code.',
|
|
73
|
+
].join('\n');
|
|
74
|
+
},
|
|
75
|
+
|
|
76
|
+
transformSubagentInstruction(text) {
|
|
77
|
+
// OpenCode has native subagent support — preserve parallel agent instructions
|
|
78
|
+
return text;
|
|
79
|
+
},
|
|
80
|
+
|
|
81
|
+
postProcess(content) {
|
|
82
|
+
return content
|
|
83
|
+
.replace(/^context: fork\n/gm, '')
|
|
84
|
+
.replace(/^agent: general-purpose\n/gm, '');
|
|
85
|
+
},
|
|
86
|
+
};
|
|
@@ -42,7 +42,7 @@ export default {
|
|
|
42
42
|
return [
|
|
43
43
|
'',
|
|
44
44
|
'---',
|
|
45
|
-
'> **Rune Skill Mesh** —
|
|
45
|
+
'> **Rune Skill Mesh** — 58 skills, 200+ connections',
|
|
46
46
|
'> Source: https://github.com/rune-kit/rune',
|
|
47
47
|
'> Full experience with subagents, hooks, adaptive routing → use Rune on Claude Code.',
|
|
48
48
|
].join('\n');
|
package/compiler/bin/rune.js
CHANGED
|
@@ -46,14 +46,11 @@ function detectPlatform(projectRoot) {
|
|
|
46
46
|
if (existsSync(path.join(projectRoot, '.windsurf'))) return 'windsurf';
|
|
47
47
|
if (existsSync(path.join(projectRoot, '.agent'))) return 'antigravity';
|
|
48
48
|
if (existsSync(path.join(projectRoot, '.openclaw'))) return 'openclaw';
|
|
49
|
+
if (existsSync(path.join(projectRoot, '.codex'))) return 'codex';
|
|
50
|
+
if (existsSync(path.join(projectRoot, '.opencode'))) return 'opencode';
|
|
49
51
|
return null;
|
|
50
52
|
}
|
|
51
53
|
|
|
52
|
-
function discoverExtensions() {
|
|
53
|
-
const extDir = path.join(RUNE_ROOT, 'extensions');
|
|
54
|
-
if (!existsSync(extDir)) return [];
|
|
55
|
-
return [];
|
|
56
|
-
}
|
|
57
54
|
|
|
58
55
|
async function prompt(question) {
|
|
59
56
|
const rl = createInterface({ input: process.stdin, output: process.stdout });
|
|
@@ -159,7 +156,7 @@ async function cmdBuild(projectRoot, args) {
|
|
|
159
156
|
|
|
160
157
|
const adapter = getAdapter(platform);
|
|
161
158
|
const runeRoot = config?.source || RUNE_ROOT;
|
|
162
|
-
const outputRoot = args.output
|
|
159
|
+
const outputRoot = typeof args.output === 'string' ? args.output : projectRoot;
|
|
163
160
|
const disabledSkills = config?.skills?.disabled || [];
|
|
164
161
|
const enabledPacks = config?.extensions?.enabled || null;
|
|
165
162
|
|
|
@@ -220,6 +217,9 @@ async function cmdDoctor(projectRoot, args) {
|
|
|
220
217
|
|
|
221
218
|
// ─── Arg Parsing ───
|
|
222
219
|
|
|
220
|
+
// Flags that require a string value (not boolean)
|
|
221
|
+
const VALUE_REQUIRED_FLAGS = new Set(['platform', 'output', 'disable', 'extensions']);
|
|
222
|
+
|
|
223
223
|
function parseArgs(argv) {
|
|
224
224
|
const args = {};
|
|
225
225
|
const positional = [];
|
|
@@ -232,6 +232,9 @@ function parseArgs(argv) {
|
|
|
232
232
|
if (next && !next.startsWith('--')) {
|
|
233
233
|
args[key] = next;
|
|
234
234
|
i++;
|
|
235
|
+
} else if (VALUE_REQUIRED_FLAGS.has(key)) {
|
|
236
|
+
log(` ✗ Flag --${key} requires a value. Example: --${key} <value>`);
|
|
237
|
+
process.exit(1);
|
|
235
238
|
} else {
|
|
236
239
|
args[key] = true;
|
|
237
240
|
}
|
|
@@ -271,7 +274,7 @@ async function main() {
|
|
|
271
274
|
log(' doctor Validate compiled output');
|
|
272
275
|
log('');
|
|
273
276
|
log(' Options:');
|
|
274
|
-
log(' --platform <name> Override platform (cursor, windsurf, antigravity, openclaw, generic)');
|
|
277
|
+
log(' --platform <name> Override platform (cursor, windsurf, antigravity, codex, openclaw, opencode, generic)');
|
|
275
278
|
log(' --output <dir> Override output directory');
|
|
276
279
|
log(' --disable <skills> Comma-separated skills to disable');
|
|
277
280
|
log('');
|
package/compiler/doctor.js
CHANGED
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
import { readdir, readFile, stat } from 'node:fs/promises';
|
|
8
8
|
import { existsSync } from 'node:fs';
|
|
9
9
|
import path from 'node:path';
|
|
10
|
+
import { parsePack } from './parser.js';
|
|
10
11
|
|
|
11
12
|
/**
|
|
12
13
|
* Run doctor checks on compiled output
|
|
@@ -89,6 +90,18 @@ export async function runDoctor({ outputRoot, adapter, config, runeRoot }) {
|
|
|
89
90
|
results.warnings.push(`${disabled.length} skills disabled: ${disabled.join(', ')}`);
|
|
90
91
|
}
|
|
91
92
|
|
|
93
|
+
// Check 7: Split pack integrity (validate skill manifest files exist)
|
|
94
|
+
const extensionsDir = path.join(runeRoot, 'extensions');
|
|
95
|
+
if (existsSync(extensionsDir)) {
|
|
96
|
+
const splitPackErrors = await checkSplitPacks(extensionsDir);
|
|
97
|
+
if (splitPackErrors.length === 0) {
|
|
98
|
+
results.checks.push({ name: 'Split packs', status: 'pass' });
|
|
99
|
+
} else {
|
|
100
|
+
results.checks.push({ name: 'Split packs', status: 'fail', detail: `${splitPackErrors.length} missing skill files` });
|
|
101
|
+
results.errors.push(...splitPackErrors);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
92
105
|
if (results.errors.length > 0) results.healthy = false;
|
|
93
106
|
|
|
94
107
|
return results;
|
|
@@ -119,6 +132,35 @@ async function checkCrossRefs(outputDir, files, adapter) {
|
|
|
119
132
|
return [...new Set(errors)]; // deduplicate
|
|
120
133
|
}
|
|
121
134
|
|
|
135
|
+
/**
|
|
136
|
+
* Check that all split packs have their declared skill files present
|
|
137
|
+
*/
|
|
138
|
+
async function checkSplitPacks(extensionsDir) {
|
|
139
|
+
const errors = [];
|
|
140
|
+
const entries = await readdir(extensionsDir, { withFileTypes: true });
|
|
141
|
+
|
|
142
|
+
for (const entry of entries) {
|
|
143
|
+
if (!entry.isDirectory()) continue;
|
|
144
|
+
const packFile = path.join(extensionsDir, entry.name, 'PACK.md');
|
|
145
|
+
if (!existsSync(packFile)) continue;
|
|
146
|
+
|
|
147
|
+
const content = await readFile(packFile, 'utf-8');
|
|
148
|
+
const parsed = parsePack(content, packFile);
|
|
149
|
+
|
|
150
|
+
if (!parsed.isSplit) continue;
|
|
151
|
+
|
|
152
|
+
const packDir = path.dirname(packFile);
|
|
153
|
+
for (const skill of parsed.skillManifest) {
|
|
154
|
+
const skillPath = path.join(packDir, skill.file);
|
|
155
|
+
if (!existsSync(skillPath)) {
|
|
156
|
+
errors.push(`@rune/${entry.name}: skill file "${skill.file}" declared in manifest but not found`);
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
return errors;
|
|
162
|
+
}
|
|
163
|
+
|
|
122
164
|
/**
|
|
123
165
|
* Format doctor results for console output
|
|
124
166
|
*/
|