@untitled-devs/wasla 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (110) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +431 -0
  3. package/dist/adapters/base.d.ts +27 -0
  4. package/dist/adapters/base.d.ts.map +1 -0
  5. package/dist/adapters/base.js +9 -0
  6. package/dist/adapters/base.js.map +1 -0
  7. package/dist/adapters/claude.d.ts +31 -0
  8. package/dist/adapters/claude.d.ts.map +1 -0
  9. package/dist/adapters/claude.js +96 -0
  10. package/dist/adapters/claude.js.map +1 -0
  11. package/dist/adapters/cursor.d.ts +30 -0
  12. package/dist/adapters/cursor.d.ts.map +1 -0
  13. package/dist/adapters/cursor.js +60 -0
  14. package/dist/adapters/cursor.js.map +1 -0
  15. package/dist/adapters/factory.d.ts +5 -0
  16. package/dist/adapters/factory.d.ts.map +1 -0
  17. package/dist/adapters/factory.js +40 -0
  18. package/dist/adapters/factory.js.map +1 -0
  19. package/dist/adapters/gemini.d.ts +31 -0
  20. package/dist/adapters/gemini.d.ts.map +1 -0
  21. package/dist/adapters/gemini.js +99 -0
  22. package/dist/adapters/gemini.js.map +1 -0
  23. package/dist/adapters/github-copilot-cli.d.ts +30 -0
  24. package/dist/adapters/github-copilot-cli.d.ts.map +1 -0
  25. package/dist/adapters/github-copilot-cli.js +65 -0
  26. package/dist/adapters/github-copilot-cli.js.map +1 -0
  27. package/dist/adapters/github-copilot.d.ts +32 -0
  28. package/dist/adapters/github-copilot.d.ts.map +1 -0
  29. package/dist/adapters/github-copilot.js +86 -0
  30. package/dist/adapters/github-copilot.js.map +1 -0
  31. package/dist/adapters/openclaw.d.ts +28 -0
  32. package/dist/adapters/openclaw.d.ts.map +1 -0
  33. package/dist/adapters/openclaw.js +62 -0
  34. package/dist/adapters/openclaw.js.map +1 -0
  35. package/dist/adapters/opencode.d.ts +32 -0
  36. package/dist/adapters/opencode.d.ts.map +1 -0
  37. package/dist/adapters/opencode.js +102 -0
  38. package/dist/adapters/opencode.js.map +1 -0
  39. package/dist/cli/commands/config.d.ts +7 -0
  40. package/dist/cli/commands/config.d.ts.map +1 -0
  41. package/dist/cli/commands/config.js +66 -0
  42. package/dist/cli/commands/config.js.map +1 -0
  43. package/dist/cli/commands/install.d.ts +2 -0
  44. package/dist/cli/commands/install.d.ts.map +1 -0
  45. package/dist/cli/commands/install.js +27 -0
  46. package/dist/cli/commands/install.js.map +1 -0
  47. package/dist/cli/commands/register.d.ts +6 -0
  48. package/dist/cli/commands/register.d.ts.map +1 -0
  49. package/dist/cli/commands/register.js +56 -0
  50. package/dist/cli/commands/register.js.map +1 -0
  51. package/dist/cli/commands/status.d.ts +6 -0
  52. package/dist/cli/commands/status.d.ts.map +1 -0
  53. package/dist/cli/commands/status.js +37 -0
  54. package/dist/cli/commands/status.js.map +1 -0
  55. package/dist/cli/commands/sync-to.d.ts +8 -0
  56. package/dist/cli/commands/sync-to.d.ts.map +1 -0
  57. package/dist/cli/commands/sync-to.js +35 -0
  58. package/dist/cli/commands/sync-to.js.map +1 -0
  59. package/dist/cli/commands/sync.d.ts +6 -0
  60. package/dist/cli/commands/sync.d.ts.map +1 -0
  61. package/dist/cli/commands/sync.js +27 -0
  62. package/dist/cli/commands/sync.js.map +1 -0
  63. package/dist/cli/commands/visualizer.d.ts +11 -0
  64. package/dist/cli/commands/visualizer.d.ts.map +1 -0
  65. package/dist/cli/commands/visualizer.js +241 -0
  66. package/dist/cli/commands/visualizer.js.map +1 -0
  67. package/dist/cli/commands/watch.d.ts +6 -0
  68. package/dist/cli/commands/watch.d.ts.map +1 -0
  69. package/dist/cli/commands/watch.js +86 -0
  70. package/dist/cli/commands/watch.js.map +1 -0
  71. package/dist/cli/index.d.ts +3 -0
  72. package/dist/cli/index.d.ts.map +1 -0
  73. package/dist/cli/index.js +59 -0
  74. package/dist/cli/index.js.map +1 -0
  75. package/dist/core/registry.d.ts +20 -0
  76. package/dist/core/registry.d.ts.map +1 -0
  77. package/dist/core/registry.js +103 -0
  78. package/dist/core/registry.js.map +1 -0
  79. package/dist/core/scanner.d.ts +17 -0
  80. package/dist/core/scanner.d.ts.map +1 -0
  81. package/dist/core/scanner.js +227 -0
  82. package/dist/core/scanner.js.map +1 -0
  83. package/dist/core/types.d.ts +78 -0
  84. package/dist/core/types.d.ts.map +1 -0
  85. package/dist/core/types.js +2 -0
  86. package/dist/core/types.js.map +1 -0
  87. package/dist/core/visualizer-types.d.ts +39 -0
  88. package/dist/core/visualizer-types.d.ts.map +1 -0
  89. package/dist/core/visualizer-types.js +2 -0
  90. package/dist/core/visualizer-types.js.map +1 -0
  91. package/dist/syncer/index.d.ts +31 -0
  92. package/dist/syncer/index.d.ts.map +1 -0
  93. package/dist/syncer/index.js +544 -0
  94. package/dist/syncer/index.js.map +1 -0
  95. package/dist/utils/cli-output.d.ts +12 -0
  96. package/dist/utils/cli-output.d.ts.map +1 -0
  97. package/dist/utils/cli-output.js +45 -0
  98. package/dist/utils/cli-output.js.map +1 -0
  99. package/dist/utils/fs.d.ts +14 -0
  100. package/dist/utils/fs.d.ts.map +1 -0
  101. package/dist/utils/fs.js +74 -0
  102. package/dist/utils/fs.js.map +1 -0
  103. package/dist/utils/paths.d.ts +7 -0
  104. package/dist/utils/paths.d.ts.map +1 -0
  105. package/dist/utils/paths.js +84 -0
  106. package/dist/utils/paths.js.map +1 -0
  107. package/package.json +122 -0
  108. package/src/visualizer/dist/assets/index-BRmeXR7T.js +144 -0
  109. package/src/visualizer/dist/index.html +12 -0
  110. package/src/visualizer/dist/logo.png +0 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Mohamed SAEED HAMMAD
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,431 @@
1
+
2
+ ```
3
+ ██╗ ██╗ █████╗ ███████╗██╗ █████╗ ██████╗ ███████╗███╗ ██╗██╗███████╗
4
+ ██║ ██║██╔══██╗██╔════╝██║ ██╔══██╗ ██╔════╝ ██╔════╝████╗ ██║██║██╔════╝
5
+ ██║ █╗ ██║███████║███████╗██║ ███████║ ██║ ███╗█████╗ ██╔██╗ ██║██║█████╗
6
+ ██║███╗██║██╔══██║╚════██║██║ ██╔══██║ ██║ ██║██╔══╝ ██║╚██╗██║██║██╔══╝
7
+ ╚███╔███╔╝██║ ██║███████║███████╗██║ ██║ ╚██████╔╝███████╗██║ ╚████║██║███████╗
8
+ ╚══╝╚══╝ ╚═╝ ╚═╝╚══════╝╚══════╝╚═╝ ╚═╝ ╚═════╝ ╚══════╝╚═╝ ╚═══╝╚═╝╚══════╝
9
+ ```
10
+ <div align="center">
11
+
12
+ **وصل جيني** — *One skill layer. Every AI orchestrator. Zero duplication.*
13
+
14
+ [![MIT License](https://img.shields.io/badge/license-MIT-00C896?style=flat-square)](LICENSE)
15
+ [![GitHub](https://img.shields.io/badge/github-The--Untitled--Org-00C896?style=flat-square&logo=github)](https://github.com/The-Untitled-Org/wasla-genie)
16
+ [![CI & Docs Deployment](https://github.com/The-Untitled-Org/wasla-genie/actions/workflows/ci-docs.yml/badge.svg)](https://github.com/The-Untitled-Org/wasla-genie/actions/workflows/ci-docs.yml)
17
+ [![Coverage](https://codecov.io/gh/The-Untitled-Org/wasla-genie/branch/main/graph/badge.svg)](https://codecov.io/gh/The-Untitled-Org/wasla-genie)
18
+ [![Status](https://img.shields.io/badge/status-alpha-orange?style=flat-square)]()
19
+ [![Contributors](https://img.shields.io/github/contributors/The-Untitled-Org/wasla-genie?style=flat-square&color=00C896)](https://github.com/The-Untitled-Org/wasla-genie/graphs/contributors)
20
+
21
+ </div>
22
+
23
+ ---
24
+
25
+ ## ❗ The Problem
26
+
27
+ You work across multiple AI orchestrators — **Claude Code**, **Gemini CLI**, and **OpenClaw**.
28
+
29
+ Each one is its own universe.
30
+
31
+ ```
32
+ You build an agent in Gemini CLI.
33
+ You open Claude Code.
34
+ It knows nothing about it.
35
+
36
+ You configure an MCP in Claude Code.
37
+ You open Codex.
38
+ Gone.
39
+
40
+ You write a skill, a command, a cron job — in one tool.
41
+ Every other tool: blank slate.
42
+ ```
43
+
44
+ There is no shared layer. Every orchestrator hoards what lives inside it.
45
+ You end up **copy-pasting configs, duplicating agent definitions, and maintaining the same thing in five places** — and the moment one changes, everything else is out of date.
46
+
47
+ ---
48
+
49
+ ## ✨ What WaslaGenie Does
50
+
51
+ WaslaGenie syncs assets across orchestrators from the CLI. Helper skill registration is optional.
52
+
53
+ When sync is triggered — manually (`sync`) or continuously (`watch`) — WaslaGenie:
54
+
55
+ 1. **Scans** the known config directories of every supported orchestrator on your machine
56
+ (`~/.claude/`, `~/.gemini/`, `~/.openclaw/`)
57
+ 2. **Discovers** all agents and MCPs — wherever they were originally created
58
+ 3. **Mirrors the full content** into every other tool's equivalent directory using the **"Latest is Greatest"** strategy.
59
+ 4. **No more duplication.** Whichever tool you used most recently to edit the asset becomes the source of truth for the next sync.
60
+
61
+ > Full content mirroring. No complex imports. No duplication.
62
+ > Just seamless synchronization that lets each tool use what the other built.
63
+
64
+ ---
65
+
66
+ ## 🔬 How Cross-Referencing Works
67
+
68
+ Say you create an agent inside Gemini CLI:
69
+
70
+ ```
71
+ ~/.gemini/agents/researcher.md ← original, owned by Gemini
72
+ ```
73
+
74
+ After `waslagenie sync`, WaslaGenie writes a minimal stub into every other tool:
75
+
76
+ ```
77
+ ~/.claude/agents/researcher.md ← stub, written by WaslaGenie
78
+ ~/.codex/agents/researcher.md ← stub, written by WaslaGenie
79
+ ~/.openclaw/agents/researcher.md ← stub, written by WaslaGenie
80
+ ```
81
+
82
+ Each stub contains only the minimum that native tool needs to load the original:
83
+
84
+ ```markdown
85
+ ---
86
+ # researcher
87
+ waslagenie_ref: ~/.gemini/agents/researcher.md
88
+ origin: gemini
89
+ ---
90
+ Refer to source definition at ~/.gemini/agents/researcher.md
91
+ ```
92
+
93
+ Claude Code reads its stub → loads the Gemini original → agent is live.
94
+ **Zero bytes duplicated. Zero maintenance.**
95
+
96
+ The same pattern applies across every asset type:
97
+
98
+ ```
99
+ ~/.gemini/agents/ → stubs written to .claude .codex .openclaw .hermes
100
+ ~/.claude/mcp/ → stubs written to .gemini .codex .openclaw .hermes
101
+ ~/.codex/skills/ → stubs written to .claude .gemini .openclaw .hermes
102
+ ~/.openclaw/commands/ → stubs written to .claude .gemini .codex .hermes
103
+ ~/.hermes/crons/ → stubs written to .claude .gemini .codex .openclaw
104
+ ```
105
+
106
+ **Source of truth = the tool that created it first. Always. Forever.**
107
+
108
+ ---
109
+
110
+ ## 🗂️ What Gets Synced
111
+
112
+ | Asset | Scanned From | Synced To |
113
+ |---|---|---|
114
+ | **Agents / Sub-agents** | `~/.{tool}/agents/` | All other tools' agent dirs |
115
+ | **MCP Servers** | `~/.{tool}/mcp/` | All other tools' MCP configs |
116
+
117
+ ---
118
+
119
+ ## 🚀 Installation
120
+
121
+ WaslaGenie is cross-platform via `npx` — no global install required:
122
+
123
+ ```bash
124
+ npx wasla-genie sync
125
+ ```
126
+
127
+ This runs the CLI directly. It does not register helper skills inside Claude, Gemini, or other tools.
128
+
129
+ **Or install globally:**
130
+
131
+ ```bash
132
+ npm install -g wasla-genie
133
+ waslagenie sync
134
+ ```
135
+
136
+ Optional helper registration:
137
+
138
+ ```bash
139
+ waslagenie register
140
+ ```
141
+
142
+ `register` detects supported orchestrators and adds the WaslaGenie helper skill inside each one.
143
+ Use `waslagenie register --to claude` (or comma-separated targets) to install only specific providers.
144
+
145
+ ---
146
+
147
+ ## 🧭 Which Command When
148
+
149
+ ### End users (installed package)
150
+
151
+ ```bash
152
+ # Run once on demand
153
+ waslagenie sync
154
+
155
+ # Keep syncing while you work
156
+ waslagenie watch
157
+
158
+ # Optional: install helper skill in all detected providers
159
+ waslagenie register
160
+
161
+ # Optional: install helper skill in specific providers only
162
+ waslagenie register --to claude,gemini
163
+ ```
164
+
165
+ You can also run without global install:
166
+
167
+ ```bash
168
+ npx wasla-genie sync
169
+ ```
170
+
171
+ ### You (developing this repo)
172
+
173
+ ```bash
174
+ # Build + run sync (workspace scope) using your local source
175
+ npm run sync
176
+
177
+ # Build + run watch (workspace scope)
178
+ npm run watch
179
+ ```
180
+
181
+ Use `npm run ...` while developing because it runs your local code (`dist`) after build.
182
+
183
+ ### Do I need to reinstall after code changes?
184
+
185
+ If you run through `npm run ...` in this repo: **No reinstall needed**. Just run the script again; it rebuilds.
186
+
187
+ If you installed globally with `npm install -g wasla-genie`: **Yes**, reinstall (or relink) to test your latest local changes.
188
+
189
+ For local development without repeated global installs:
190
+
191
+ ```bash
192
+ npm link
193
+ waslagenie sync
194
+ ```
195
+
196
+ Then after code changes, run `npm run build` (or any script that builds) and use `waslagenie` again.
197
+
198
+ ---
199
+
200
+ ## ⚡ Usage
201
+
202
+ ### One-time sync
203
+
204
+ ```bash
205
+ waslagenie sync
206
+ ```
207
+
208
+ ```
209
+ 🔍 Scanning ~/.claude/ → 3 agents, 2 MCPs, 4 commands
210
+ 🔍 Scanning ~/.gemini/ → 5 agents, 1 MCP, 2 skills
211
+ 🔍 Scanning ~/.codex/ → 1 agent, 3 commands
212
+ 🔍 Scanning ~/.openclaw/ → 2 agents, 2 crons
213
+ 🔍 Scanning ~/.hermes/ → 1 agent, 1 skill
214
+
215
+ ✔ Stubs written to ~/.claude/ → 6 new references
216
+ ✔ Stubs written to ~/.gemini/ → 4 new references
217
+ ✔ Stubs written to ~/.codex/ → 7 new references
218
+ ✔ Stubs written to ~/.openclaw/ → 5 new references
219
+ ✔ Stubs written to ~/.hermes/ → 8 new references
220
+
221
+ ✨ Sync complete — 30 cross-references written, 0 files duplicated
222
+ ```
223
+
224
+ ---
225
+
226
+ ### Automatic background sync — watch mode
227
+
228
+ `waslagenie watch` is the background sync process. It watches for file changes across all tool directories while the command is running.
229
+
230
+ ```
231
+ [watch starts] → WaslaGenie process launched
232
+ [File changes] → WaslaGenie detects change and syncs immediately
233
+ [watch stops] → WaslaGenie process exits cleanly
234
+ ```
235
+
236
+ ```
237
+ 👁 WaslaGenie active (session: Claude Code)
238
+ Monitoring: ~/.claude ~/.gemini ~/.codex ~/.openclaw
239
+
240
+ [14:32:01] New agent detected → ~/.gemini/agents/planner.md
241
+ [14:32:01] Syncing stubs → .claude ✔ .codex ✔ .openclaw ✔
242
+
243
+ [15:10:44] Agent updated → ~/.claude/agents/researcher.md (Latest is Greatest)
244
+ [15:10:44] Syncing stubs → .gemini ✔ .codex ✔ .openclaw ✔
245
+ ```
246
+
247
+ No restart. No manual trigger. The moment something changes — it's everywhere.
248
+
249
+ ---
250
+
251
+ ### Scope — workspace or user level
252
+
253
+ ```bash
254
+ # Sync only within current project workspace
255
+ waslagenie sync --scope workspace
256
+
257
+ # Sync across your entire user space (default)
258
+ waslagenie sync --scope user
259
+ ```
260
+
261
+ ---
262
+
263
+ ### Status — see everything and where it lives
264
+
265
+ ```bash
266
+ waslagenie status
267
+ ```
268
+
269
+ ```
270
+ ASSET TYPE ORIGIN SYNCED TO
271
+ researcher agent gemini claude ✔ codex ✔ openclaw ✔ hermes ✔
272
+ planner agent claude gemini ✔ codex ✔ openclaw ✔ hermes ✔
273
+ notion-mcp mcp claude gemini ✔ codex ✔ openclaw ✔
274
+ web-scraper skill codex claude ✔ gemini ✔ openclaw ✔ hermes ✔
275
+ daily-standup cron gemini claude ✔ codex ✔
276
+ review-pr command openclaw claude ✔ gemini ✔ codex ✔ hermes ✔
277
+ ```
278
+
279
+ ---
280
+
281
+ ## 🧩 Supported Orchestrators
282
+
283
+ ### CLI / Terminal Agents
284
+
285
+ | Tool | Auto-detect | Scan | Sync | Skill Install | Daemon |
286
+ |---|---|---|---|---|---|
287
+ | **Claude Code** | ✅ | ✅ | ✅ | ✅ | ✅ |
288
+ | **Gemini CLI** | ✅ | ✅ | ✅ | ✅ | ✅ |
289
+ | **OpenAI Codex CLI** | ✅ | ✅ | ✅ | ✅ | ✅ |
290
+ | **OpenClaw** | ✅ | ✅ | ✅ | ✅ | ✅ |
291
+ | **Hermes** | 🔧 | 🔧 | 🔧 | 🔧 | 🔧 |
292
+ | **Custom / BYO** | 🔧 | 🔧 | 🔧 | 🔧 | 🔧 |
293
+
294
+ ### IDE-based Agents
295
+
296
+ | Tool | Auto-detect | Scan | Sync | Skill Install | Daemon |
297
+ |---|---|---|---|---|---|
298
+ | **Cursor** | 🔜 | 🔜 | 🔜 | 🔜 | 🔜 |
299
+ | **GitHub Copilot** | 🔜 | 🔜 | 🔜 | 🔜 | 🔜 |
300
+
301
+ > ✅ Supported &nbsp;·&nbsp; 🔜 Planned &nbsp;·&nbsp; 🔧 Custom adapter required
302
+ > Adding a new tool? See [Writing an Adapter](docs/adapters.md).
303
+
304
+ ---
305
+
306
+ ## 🗃️ Registry Storage
307
+
308
+ WaslaGenie keeps its own state separately from all orchestrators. You choose the scope at install time:
309
+
310
+ **User-level** (default — available across all your projects):
311
+ ```
312
+ ~/.waslagenie/
313
+ ├── registry.json ← every discovered asset + origin tool + stub locations
314
+ ├── stubs/ ← log of every stub written and when
315
+ └── config.json ← your scope and preferences
316
+ ```
317
+
318
+ **Workspace-level** (scoped to current project only):
319
+ ```
320
+ .waslagenie/
321
+ ├── registry.json
322
+ ├── stubs/
323
+ └── config.json
324
+ ```
325
+
326
+ Switch anytime:
327
+ ```bash
328
+ waslagenie config --scope workspace
329
+ waslagenie config --scope user
330
+ ```
331
+
332
+ ---
333
+
334
+ ## 🌱 Gradual Centralization
335
+
336
+ WaslaGenie respects the **zero-friction promise**: your agents live where they were born. You don't need to learn a new canonical location on day one.
337
+
338
+ But over time, WaslaGenie offers a path toward centralization — for portability, backup, and eventually team sharing.
339
+
340
+ ```
341
+ Day 1 — Agents live in ~/.claude/, ~/.gemini/, ~/.codex/
342
+ WaslaGenie syncs them via stubs. You don't change anything.
343
+
344
+ Over time — You discover agents scattered across 5 tool directories.
345
+ You run: waslagenie migrate researcher --to ~/.waslagenie/
346
+ Now researcher lives in ~/.waslagenie/ and stubs point there.
347
+
348
+ Later — All your agents are in ~/.waslagenie/.
349
+ Backup is: waslagenie export
350
+ New machine is: waslagenie import backup.tar
351
+ ```
352
+
353
+ **Commands:**
354
+
355
+ ```bash
356
+ waslagenie status # see where every asset lives today
357
+ waslagenie migrate <name> --to ~/.waslagenie/ # optionally move an asset to central location
358
+ waslagenie export # bundle everything for backup or new machine
359
+ waslagenie import backup.tar # restore on a new machine
360
+ ```
361
+
362
+ Nothing is forced. Centralization is a convenience, not a requirement.
363
+
364
+ ---
365
+
366
+ ## 🏗️ Project Structure
367
+
368
+ ```
369
+ wasla-genie/
370
+ ├── src/
371
+ │ ├── cli/ # CLI entry point and commands
372
+ │ ├── scanner/ # Scans known tool config directories
373
+ │ ├── registry/ # Builds and maintains the asset registry
374
+ │ ├── syncer/ # Writes and tracks stub files
375
+ │ ├── watcher/ # Daemon / filesystem watcher
376
+ │ └── adapters/ # Per-tool directory knowledge + stub format
377
+ │ ├── claude.js
378
+ │ ├── gemini.js
379
+ │ ├── codex.js
380
+ │ ├── openclaw.js
381
+ │ └── hermes.js
382
+ ├── docs/
383
+ │ ├── how-stubs-work.md
384
+ │ ├── adapters.md
385
+ │ └── roadmap.md
386
+ ├── package.json
387
+ └── README.md
388
+ ```
389
+
390
+ ---
391
+
392
+ ## 🌍 Why "WaslaGenie"?
393
+
394
+ **Wasla (وصلة)** is Arabic for *connection* — the act of joining what was always separate.
395
+
396
+ **Genie** — it appears when summoned, connects what you need, and watches quietly in the background until called again.
397
+
398
+ Your agents live where they were born.
399
+ Your tools see everything.
400
+ Nothing is ever duplicated.
401
+
402
+ ---
403
+
404
+ ## 🤝 Contributing
405
+
406
+ ```bash
407
+ git clone https://github.com/The-Untitled-Org/wasla-genie
408
+ cd wasla-genie
409
+ npm install
410
+ npm run dev
411
+ ```
412
+
413
+ - [Contributing Guide](CONTRIBUTING.md)
414
+ - [Architecture Docs](docs/docs/architecture/index.md)
415
+
416
+ ---
417
+
418
+ ## 📄 License
419
+
420
+ MIT © [The Untitled Org](https://github.com/The-Untitled-Org)
421
+
422
+ ---
423
+
424
+ <div align="center">
425
+
426
+ **Your agents live where they were born.**
427
+ **WaslaGenie makes sure every tool can find them.**
428
+
429
+ ⭐ Star this repo if you are tired of copy-pasting the same config into five different tools.
430
+
431
+ </div>
@@ -0,0 +1,27 @@
1
+ import { WaslaGenieAdapter, Asset, AssetFormat } from '../core/types.js';
2
+ export declare abstract class BaseAdapter implements WaslaGenieAdapter {
3
+ abstract name: string;
4
+ abstract displayName: string;
5
+ abstract mcpKey: string;
6
+ abstract contextFile: string;
7
+ abstract skillDirs: string[];
8
+ abstract paths: {
9
+ agent?: string;
10
+ skill?: string;
11
+ mcp?: string;
12
+ context?: string;
13
+ };
14
+ abstract formats: {
15
+ agent?: AssetFormat;
16
+ skill?: AssetFormat;
17
+ mcp?: AssetFormat;
18
+ context?: AssetFormat;
19
+ };
20
+ abstract isInstalled(): Promise<boolean>;
21
+ mcpFromNative(server: Record<string, unknown>): Record<string, unknown>;
22
+ mcpToNative(server: Record<string, unknown>): Record<string, unknown>;
23
+ abstract writeStub(asset: Asset, content: string, targetPath: string): Promise<void>;
24
+ abstract installSkill(): Promise<void>;
25
+ abstract getRootConfigAppend(): string | null;
26
+ }
27
+ //# sourceMappingURL=base.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"base.d.ts","sourceRoot":"","sources":["../../src/adapters/base.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,KAAK,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAEzE,8BAAsB,WAAY,YAAW,iBAAiB;IAC5D,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,SAAS,EAAE,MAAM,EAAE,CAAC;IAE7B,QAAQ,CAAC,KAAK,EAAE;QACd,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,GAAG,CAAC,EAAE,MAAM,CAAC;QACb,OAAO,CAAC,EAAE,MAAM,CAAC;KAClB,CAAC;IACF,QAAQ,CAAC,OAAO,EAAE;QAChB,KAAK,CAAC,EAAE,WAAW,CAAC;QACpB,KAAK,CAAC,EAAE,WAAW,CAAC;QACpB,GAAG,CAAC,EAAE,WAAW,CAAC;QAClB,OAAO,CAAC,EAAE,WAAW,CAAC;KACvB,CAAC;IAEF,QAAQ,CAAC,WAAW,IAAI,OAAO,CAAC,OAAO,CAAC;IAExC,aAAa,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IAIvE,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IAIrE,QAAQ,CAAC,SAAS,CAAC,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IACpF,QAAQ,CAAC,YAAY,IAAI,OAAO,CAAC,IAAI,CAAC;IACtC,QAAQ,CAAC,mBAAmB,IAAI,MAAM,GAAG,IAAI;CAC9C"}
@@ -0,0 +1,9 @@
1
+ export class BaseAdapter {
2
+ mcpFromNative(server) {
3
+ return server;
4
+ }
5
+ mcpToNative(server) {
6
+ return server;
7
+ }
8
+ }
9
+ //# sourceMappingURL=base.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"base.js","sourceRoot":"","sources":["../../src/adapters/base.ts"],"names":[],"mappings":"AAEA,MAAM,OAAgB,WAAW;IAsB/B,aAAa,CAAC,MAA+B;QAC3C,OAAO,MAAM,CAAC;IAChB,CAAC;IAED,WAAW,CAAC,MAA+B;QACzC,OAAO,MAAM,CAAC;IAChB,CAAC;CAKF"}
@@ -0,0 +1,31 @@
1
+ import { BaseAdapter } from './base.js';
2
+ import { Asset } from '../core/types.js';
3
+ export declare class ClaudeAdapter extends BaseAdapter {
4
+ name: string;
5
+ displayName: string;
6
+ private scope;
7
+ constructor(scope?: 'user' | 'workspace');
8
+ get paths(): {
9
+ agent: string;
10
+ skill: string;
11
+ mcp: string;
12
+ context: string;
13
+ };
14
+ mcpKey: string;
15
+ contextFile: string;
16
+ formats: {
17
+ agent: "md";
18
+ skill: "md";
19
+ mcp: "json";
20
+ context: "md";
21
+ };
22
+ get skillDirs(): string[];
23
+ isInstalled(): Promise<boolean>;
24
+ writeStub(asset: Asset, content: string, targetPath: string): Promise<void>;
25
+ private writeAgentStub;
26
+ private writeSkillStub;
27
+ private writeMcpStub;
28
+ installSkill(): Promise<void>;
29
+ getRootConfigAppend(): string | null;
30
+ }
31
+ //# sourceMappingURL=claude.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"claude.d.ts","sourceRoot":"","sources":["../../src/adapters/claude.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AACxC,OAAO,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAC;AAKzC,qBAAa,aAAc,SAAQ,WAAW;IAC5C,IAAI,SAAY;IAChB,WAAW,SAAiB;IAC5B,OAAO,CAAC,KAAK,CAAuB;gBAExB,KAAK,GAAE,MAAM,GAAG,WAAyB;IAKrD,IAAI,KAAK;;;;;MAWR;IAED,MAAM,SAAgB;IACtB,WAAW,SAAe;IAE1B,OAAO;;;;;MAKL;IAEF,IAAI,SAAS,aAEZ;IAEK,WAAW,IAAI,OAAO,CAAC,OAAO,CAAC;IAK/B,SAAS,CAAC,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;YAUnE,cAAc;YAMd,cAAc;YAMd,YAAY;IAMpB,YAAY,IAAI,OAAO,CAAC,IAAI,CAAC;IAgCnC,mBAAmB,IAAI,MAAM,GAAG,IAAI;CAGrC"}
@@ -0,0 +1,96 @@
1
+ import { BaseAdapter } from './base.js';
2
+ import { fileExists, writeText, ensureDir } from '../utils/fs.js';
3
+ import { join } from 'path';
4
+ import { getToolMarkers } from '../utils/paths.js';
5
+ export class ClaudeAdapter extends BaseAdapter {
6
+ constructor(scope = 'workspace') {
7
+ super();
8
+ this.name = 'claude';
9
+ this.displayName = 'Claude Code';
10
+ this.mcpKey = 'mcpServers';
11
+ this.contextFile = 'CLAUDE.md';
12
+ this.formats = {
13
+ agent: 'md',
14
+ skill: 'md',
15
+ mcp: 'json',
16
+ context: 'md',
17
+ };
18
+ this.scope = scope;
19
+ }
20
+ get paths() {
21
+ const markers = getToolMarkers(this.scope);
22
+ return {
23
+ agent: join(markers.claude, 'agents'),
24
+ skill: join(markers.claude, 'skills'),
25
+ mcp: this.scope === 'workspace'
26
+ ? join(markers.claude, 'mcp.json')
27
+ : join(markers.claude, 'settings.json'),
28
+ context: join(markers.claude, 'CLAUDE.md'),
29
+ };
30
+ }
31
+ get skillDirs() {
32
+ return [this.paths.skill];
33
+ }
34
+ async isInstalled() {
35
+ const markers = getToolMarkers(this.scope);
36
+ return fileExists(markers.claude);
37
+ }
38
+ async writeStub(asset, content, targetPath) {
39
+ if (asset.type === 'agent') {
40
+ await this.writeAgentStub(targetPath, content);
41
+ }
42
+ else if (asset.type === 'skill') {
43
+ await this.writeSkillStub(targetPath, content);
44
+ }
45
+ else {
46
+ await this.writeMcpStub(targetPath, content);
47
+ }
48
+ }
49
+ async writeAgentStub(targetPath, content) {
50
+ const { dirname } = await import('path');
51
+ await ensureDir(dirname(targetPath));
52
+ await writeText(targetPath, content);
53
+ }
54
+ async writeSkillStub(targetPath, content) {
55
+ const { dirname } = await import('path');
56
+ await ensureDir(dirname(targetPath));
57
+ await writeText(targetPath, content);
58
+ }
59
+ async writeMcpStub(targetPath, content) {
60
+ const { dirname } = await import('path');
61
+ await ensureDir(dirname(targetPath));
62
+ await writeText(targetPath, content);
63
+ }
64
+ async installSkill() {
65
+ // Write a WaslaGenie skill into Claude's native skills directory.
66
+ // We do NOT touch CLAUDE.md — that file belongs to the user.
67
+ const skillDir = join(this.paths.skill, 'waslagenie');
68
+ await ensureDir(skillDir);
69
+ const skillPath = join(skillDir, 'SKILL.md');
70
+ if (await fileExists(skillPath)) {
71
+ return; // already installed, idempotent
72
+ }
73
+ const skillContent = `---
74
+ description: >
75
+ Runs WaslaGenie CLI commands to sync, inspect, or manage agents and MCPs
76
+ across AI orchestrators. Use when asked to sync tools, check sync status,
77
+ install WaslaGenie, or troubleshoot why an agent isn't appearing in a tool.
78
+ ---
79
+
80
+ # WaslaGenie Operator
81
+
82
+ Use the \`waslagenie\` CLI to sync agents and MCPs across all installed AI tools.
83
+
84
+ \`\`\`bash
85
+ waslagenie sync # Mirror agents across all tools
86
+ waslagenie status # Show registry state
87
+ waslagenie watch # Auto-sync on file changes
88
+ \`\`\`
89
+ `;
90
+ await writeText(skillPath, skillContent);
91
+ }
92
+ getRootConfigAppend() {
93
+ return null;
94
+ }
95
+ }
96
+ //# sourceMappingURL=claude.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"claude.js","sourceRoot":"","sources":["../../src/adapters/claude.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,30 @@
1
+ import { BaseAdapter } from './base.js';
2
+ import { Asset } from '../core/types.js';
3
+ export declare class CursorAdapter extends BaseAdapter {
4
+ name: string;
5
+ displayName: string;
6
+ protected scope: 'user' | 'workspace';
7
+ constructor(scope?: 'user' | 'workspace');
8
+ get paths(): {
9
+ agent: string;
10
+ skill: string;
11
+ mcp: string;
12
+ context: string | undefined;
13
+ };
14
+ mcpKey: string;
15
+ contextFile: string;
16
+ get skillDirs(): string[];
17
+ formats: {
18
+ agent: "md";
19
+ skill: "md";
20
+ mcp: "json";
21
+ context: "md";
22
+ };
23
+ isInstalled(): Promise<boolean>;
24
+ writeStub(asset: Asset, content: string, targetPath: string): Promise<void>;
25
+ private writeAgentStub;
26
+ private writeMcpStub;
27
+ installSkill(): Promise<void>;
28
+ getRootConfigAppend(): string | null;
29
+ }
30
+ //# sourceMappingURL=cursor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cursor.d.ts","sourceRoot":"","sources":["../../src/adapters/cursor.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AACxC,OAAO,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAC;AAKzC,qBAAa,aAAc,SAAQ,WAAW;IAC5C,IAAI,SAAY;IAChB,WAAW,SAAY;IACvB,SAAS,CAAC,KAAK,EAAE,MAAM,GAAG,WAAW,CAAC;gBAE1B,KAAK,GAAE,MAAM,GAAG,WAAyB;IAKrD,IAAI,KAAK;;;;;MASR;IAED,MAAM,SAAgB;IACtB,WAAW,SAAe;IAE1B,IAAI,SAAS,aAEZ;IAED,OAAO;;;;;MAKL;IAEI,WAAW,IAAI,OAAO,CAAC,OAAO,CAAC;IAK/B,SAAS,CAAC,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;YAQnE,cAAc;YAKd,YAAY;IAKpB,YAAY,IAAI,OAAO,CAAC,IAAI,CAAC;IAInC,mBAAmB,IAAI,MAAM,GAAG,IAAI;CAGrC"}