@untitled-devs/wasla 1.0.0 → 1.0.2
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 +65 -74
- package/dist/apps/cli/src/cli-output.js +5 -5
- package/dist/apps/cli/src/commands/config.js +1 -1
- package/dist/apps/cli/src/commands/install.js +6 -6
- package/dist/apps/cli/src/commands/register.js +1 -1
- package/dist/apps/cli/src/commands/status.js +1 -1
- package/dist/apps/cli/src/commands/sync-to.js +2 -2
- package/dist/apps/cli/src/commands/watch.js +1 -1
- package/dist/apps/cli/src/index.js +4 -4
- package/dist/apps/cli/src/server/visualizer-server.js +6 -7
- package/dist/packages/adapters/src/base.d.ts +2 -2
- package/dist/packages/adapters/src/claude.js +14 -11
- package/dist/packages/adapters/src/factory.d.ts +4 -4
- package/dist/packages/adapters/src/gemini.js +10 -10
- package/dist/packages/core/src/types.d.ts +1 -1
- package/dist/packages/shared/src/config.js +3 -3
- package/dist/packages/shared/src/paths.js +4 -4
- package/dist/packages/sync/src/index.d.ts +9 -0
- package/dist/packages/sync/src/index.js +56 -33
- package/dist/packages/sync/src/scanner.js +3 -3
- package/dist/visualizer/assets/{index-cU_xphSj.js → index-DF8-6vb2.js} +1 -1
- package/dist/visualizer/favicon.png +0 -0
- package/dist/visualizer/index.html +3 -2
- package/dist/visualizer/logo.png +0 -0
- package/package.json +7 -4
package/README.md
CHANGED
|
@@ -1,25 +1,19 @@
|
|
|
1
1
|
|
|
2
|
-
```
|
|
3
|
-
██╗ ██╗ █████╗ ███████╗██╗ █████╗ ██████╗ ███████╗███╗ ██╗██╗███████╗
|
|
4
|
-
██║ ██║██╔══██╗██╔════╝██║ ██╔══██╗ ██╔════╝ ██╔════╝████╗ ██║██║██╔════╝
|
|
5
|
-
██║ █╗ ██║███████║███████╗██║ ███████║ ██║ ███╗█████╗ ██╔██╗ ██║██║█████╗
|
|
6
|
-
██║███╗██║██╔══██║╚════██║██║ ██╔══██║ ██║ ██║██╔══╝ ██║╚██╗██║██║██╔══╝
|
|
7
|
-
╚███╔███╔╝██║ ██║███████║███████╗██║ ██║ ╚██████╔╝███████╗██║ ╚████║██║███████╗
|
|
8
|
-
╚══╝╚══╝ ╚═╝ ╚═╝╚══════╝╚══════╝╚═╝ ╚═╝ ╚═════╝ ╚══════╝╚═╝ ╚═══╝╚═╝╚══════╝
|
|
9
|
-
```
|
|
10
2
|
<div align="center">
|
|
11
3
|
|
|
4
|
+
<img src="docs/static/img/logo-wordmark.png" alt="Wasla" width="640" />
|
|
5
|
+
|
|
12
6
|
**وصل جيني** — *One skill layer. Every AI orchestrator. Zero duplication.*
|
|
13
7
|
|
|
14
8
|
[](LICENSE)
|
|
15
|
-
[](https://github.com/The-Untitled-Org/wasla
|
|
9
|
+
[](https://github.com/The-Untitled-Org/wasla)
|
|
16
10
|
[](https://www.npmjs.com/package/@untitled-devs/wasla)
|
|
17
11
|
[](https://www.npmjs.com/package/@untitled-devs/wasla)
|
|
18
|
-
[](https://github.com/The-Untitled-Org/wasla/releases)
|
|
13
|
+
[](https://github.com/The-Untitled-Org/wasla/actions/workflows/ci-docs.yml)
|
|
14
|
+
[](https://codecov.io/gh/The-Untitled-Org/wasla)
|
|
21
15
|
[]()
|
|
22
|
-
[](https://github.com/The-Untitled-Org/wasla/graphs/contributors)
|
|
23
17
|
|
|
24
18
|
</div>
|
|
25
19
|
|
|
@@ -49,11 +43,11 @@ You end up **copy-pasting configs, duplicating agent definitions, and maintainin
|
|
|
49
43
|
|
|
50
44
|
---
|
|
51
45
|
|
|
52
|
-
## ✨ What
|
|
46
|
+
## ✨ What Wasla Does
|
|
53
47
|
|
|
54
|
-
|
|
48
|
+
Wasla syncs assets across orchestrators from the CLI. Helper skill registration is optional.
|
|
55
49
|
|
|
56
|
-
When sync is triggered — manually (`sync`) or continuously (`watch`) —
|
|
50
|
+
When sync is triggered — manually (`sync`) or continuously (`watch`) — Wasla:
|
|
57
51
|
|
|
58
52
|
1. **Scans** the known config directories of every supported orchestrator on your machine
|
|
59
53
|
(`~/.claude/`, `~/.gemini/`, `~/.openclaw/`)
|
|
@@ -74,12 +68,12 @@ Say you create an agent inside Gemini CLI:
|
|
|
74
68
|
~/.gemini/agents/researcher.md ← original, owned by Gemini
|
|
75
69
|
```
|
|
76
70
|
|
|
77
|
-
After `
|
|
71
|
+
After `wasla sync`, Wasla writes a minimal stub into every other tool:
|
|
78
72
|
|
|
79
73
|
```
|
|
80
|
-
~/.claude/agents/researcher.md ← stub, written by
|
|
81
|
-
~/.codex/agents/researcher.md ← stub, written by
|
|
82
|
-
~/.openclaw/agents/researcher.md ← stub, written by
|
|
74
|
+
~/.claude/agents/researcher.md ← stub, written by Wasla
|
|
75
|
+
~/.codex/agents/researcher.md ← stub, written by Wasla
|
|
76
|
+
~/.openclaw/agents/researcher.md ← stub, written by Wasla
|
|
83
77
|
```
|
|
84
78
|
|
|
85
79
|
Each stub contains only the minimum that native tool needs to load the original:
|
|
@@ -87,7 +81,7 @@ Each stub contains only the minimum that native tool needs to load the original:
|
|
|
87
81
|
```markdown
|
|
88
82
|
---
|
|
89
83
|
# researcher
|
|
90
|
-
|
|
84
|
+
wasla_ref: ~/.gemini/agents/researcher.md
|
|
91
85
|
origin: gemini
|
|
92
86
|
---
|
|
93
87
|
Refer to source definition at ~/.gemini/agents/researcher.md
|
|
@@ -121,32 +115,31 @@ The same pattern applies across every asset type:
|
|
|
121
115
|
|
|
122
116
|
## 🚀 Installation
|
|
123
117
|
|
|
124
|
-
|
|
118
|
+
**Install globally:**
|
|
125
119
|
|
|
126
120
|
```bash
|
|
127
|
-
|
|
128
|
-
|
|
121
|
+
npm i -g @untitled-devs/wasla
|
|
122
|
+
wasla config --scope workspace
|
|
123
|
+
wasla sync
|
|
129
124
|
```
|
|
130
125
|
|
|
131
|
-
Choose `workspace` or `user` once before running operational commands.
|
|
132
|
-
It does not register helper skills inside Claude, Gemini, or other tools.
|
|
126
|
+
Choose `workspace` or `user` once before running operational commands.
|
|
133
127
|
|
|
134
|
-
**Or
|
|
128
|
+
**Or run via `npx` (no global installation required):**
|
|
135
129
|
|
|
136
130
|
```bash
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
waslagenie sync
|
|
131
|
+
npx @untitled-devs/wasla config --scope workspace
|
|
132
|
+
npx @untitled-devs/wasla sync
|
|
140
133
|
```
|
|
141
134
|
|
|
142
135
|
Optional helper registration:
|
|
143
136
|
|
|
144
137
|
```bash
|
|
145
|
-
|
|
138
|
+
wasla register
|
|
146
139
|
```
|
|
147
140
|
|
|
148
|
-
`register` detects supported orchestrators and adds the
|
|
149
|
-
Use `
|
|
141
|
+
`register` detects supported orchestrators and adds the Wasla helper skill inside each one.
|
|
142
|
+
Use `wasla register --to claude` (or comma-separated targets) to install only specific providers.
|
|
150
143
|
|
|
151
144
|
---
|
|
152
145
|
|
|
@@ -156,19 +149,19 @@ Use `waslagenie register --to claude` (or comma-separated targets) to install on
|
|
|
156
149
|
|
|
157
150
|
```bash
|
|
158
151
|
# Run once on demand
|
|
159
|
-
|
|
152
|
+
wasla sync
|
|
160
153
|
|
|
161
154
|
# Keep syncing while you work
|
|
162
|
-
|
|
155
|
+
wasla watch
|
|
163
156
|
|
|
164
157
|
# Open the visualizer dashboard
|
|
165
|
-
|
|
158
|
+
wasla visualizer
|
|
166
159
|
|
|
167
160
|
# Optional: install helper skill in all detected providers
|
|
168
|
-
|
|
161
|
+
wasla register
|
|
169
162
|
|
|
170
163
|
# Optional: install helper skill in specific providers only
|
|
171
|
-
|
|
164
|
+
wasla register --to claude,gemini
|
|
172
165
|
```
|
|
173
166
|
|
|
174
167
|
You can also run without global install:
|
|
@@ -197,16 +190,16 @@ Use `npm run ...` while developing because it runs your local code (`dist`) afte
|
|
|
197
190
|
|
|
198
191
|
If you run through `npm run ...` in this repo: **No reinstall needed**. Just run the script again; it rebuilds.
|
|
199
192
|
|
|
200
|
-
If you installed globally with `npm
|
|
193
|
+
If you installed globally with `npm i -g @untitled-devs/wasla`: **Yes**, reinstall (or relink) to test your latest local changes.
|
|
201
194
|
|
|
202
195
|
For local development without repeated global installs:
|
|
203
196
|
|
|
204
197
|
```bash
|
|
205
198
|
npm link
|
|
206
|
-
|
|
199
|
+
wasla sync
|
|
207
200
|
```
|
|
208
201
|
|
|
209
|
-
Then after code changes, run `npm run build` (or any script that builds) and use `
|
|
202
|
+
Then after code changes, run `npm run build` (or any script that builds) and use `wasla` again.
|
|
210
203
|
|
|
211
204
|
---
|
|
212
205
|
|
|
@@ -215,7 +208,7 @@ Then after code changes, run `npm run build` (or any script that builds) and use
|
|
|
215
208
|
### One-time sync
|
|
216
209
|
|
|
217
210
|
```bash
|
|
218
|
-
|
|
211
|
+
wasla sync
|
|
219
212
|
```
|
|
220
213
|
|
|
221
214
|
```
|
|
@@ -238,16 +231,16 @@ waslagenie sync
|
|
|
238
231
|
|
|
239
232
|
### Automatic background sync — watch mode
|
|
240
233
|
|
|
241
|
-
`
|
|
234
|
+
`wasla watch` is the background sync process. It watches for file changes across all tool directories while the command is running.
|
|
242
235
|
|
|
243
236
|
```
|
|
244
|
-
[watch starts] →
|
|
245
|
-
[File changes] →
|
|
246
|
-
[watch stops] →
|
|
237
|
+
[watch starts] → Wasla process launched
|
|
238
|
+
[File changes] → Wasla detects change and syncs immediately
|
|
239
|
+
[watch stops] → Wasla process exits cleanly
|
|
247
240
|
```
|
|
248
241
|
|
|
249
242
|
```
|
|
250
|
-
👁
|
|
243
|
+
👁 Wasla active (session: Claude Code)
|
|
251
244
|
Monitoring: ~/.claude ~/.gemini ~/.codex ~/.openclaw
|
|
252
245
|
|
|
253
246
|
[14:32:01] New agent detected → ~/.gemini/agents/planner.md
|
|
@@ -267,10 +260,10 @@ Choose the active scope before running sync, watch, status, or the visualizer:
|
|
|
267
260
|
|
|
268
261
|
```bash
|
|
269
262
|
# Use the current project workspace registry
|
|
270
|
-
|
|
263
|
+
wasla config --scope workspace
|
|
271
264
|
|
|
272
265
|
# Use the user-level registry across projects
|
|
273
|
-
|
|
266
|
+
wasla config --scope user
|
|
274
267
|
```
|
|
275
268
|
|
|
276
269
|
All other commands use the saved scope automatically. They do not accept `--scope`.
|
|
@@ -280,7 +273,7 @@ All other commands use the saved scope automatically. They do not accept `--scop
|
|
|
280
273
|
### Status — see everything and where it lives
|
|
281
274
|
|
|
282
275
|
```bash
|
|
283
|
-
|
|
276
|
+
wasla status
|
|
284
277
|
```
|
|
285
278
|
|
|
286
279
|
```
|
|
@@ -322,55 +315,55 @@ review-pr command openclaw claude ✔ gemini ✔ codex ✔ her
|
|
|
322
315
|
|
|
323
316
|
## 🗃️ Registry Storage
|
|
324
317
|
|
|
325
|
-
|
|
318
|
+
Wasla keeps its own state separately from all orchestrators. You choose the active scope explicitly before the first sync:
|
|
326
319
|
|
|
327
320
|
**User-level** (available across all your projects):
|
|
328
321
|
```
|
|
329
|
-
~/.
|
|
322
|
+
~/.wasla/
|
|
330
323
|
├── registry.json ← user-scope assets and stub locations
|
|
331
324
|
└── config.json ← active scope preference
|
|
332
325
|
```
|
|
333
326
|
|
|
334
327
|
**Workspace-level** (scoped to current project only):
|
|
335
328
|
```
|
|
336
|
-
.
|
|
329
|
+
.wasla/
|
|
337
330
|
└── registry.json ← workspace-scope assets and stub locations
|
|
338
331
|
```
|
|
339
332
|
|
|
340
333
|
Switch anytime:
|
|
341
334
|
```bash
|
|
342
|
-
|
|
343
|
-
|
|
335
|
+
wasla config --scope workspace
|
|
336
|
+
wasla config --scope user
|
|
344
337
|
```
|
|
345
338
|
|
|
346
339
|
---
|
|
347
340
|
|
|
348
341
|
## 🌱 Gradual Centralization
|
|
349
342
|
|
|
350
|
-
|
|
343
|
+
Wasla 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.
|
|
351
344
|
|
|
352
|
-
But over time,
|
|
345
|
+
But over time, Wasla offers a path toward centralization — for portability, backup, and eventually team sharing.
|
|
353
346
|
|
|
354
347
|
```
|
|
355
348
|
Day 1 — Agents live in ~/.claude/, ~/.gemini/, ~/.codex/
|
|
356
|
-
|
|
349
|
+
Wasla syncs them via stubs. You don't change anything.
|
|
357
350
|
|
|
358
351
|
Over time — You discover agents scattered across 5 tool directories.
|
|
359
|
-
You run:
|
|
360
|
-
Now researcher lives in ~/.
|
|
352
|
+
You run: wasla migrate researcher --to ~/.wasla/
|
|
353
|
+
Now researcher lives in ~/.wasla/ and stubs point there.
|
|
361
354
|
|
|
362
|
-
Later — All your agents are in ~/.
|
|
363
|
-
Backup is:
|
|
364
|
-
New machine is:
|
|
355
|
+
Later — All your agents are in ~/.wasla/.
|
|
356
|
+
Backup is: wasla export
|
|
357
|
+
New machine is: wasla import backup.tar
|
|
365
358
|
```
|
|
366
359
|
|
|
367
360
|
**Commands:**
|
|
368
361
|
|
|
369
362
|
```bash
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
363
|
+
wasla status # see where every asset lives today
|
|
364
|
+
wasla migrate <name> --to ~/.wasla/ # optionally move an asset to central location
|
|
365
|
+
wasla export # bundle everything for backup or new machine
|
|
366
|
+
wasla import backup.tar # restore on a new machine
|
|
374
367
|
```
|
|
375
368
|
|
|
376
369
|
Nothing is forced. Centralization is a convenience, not a requirement.
|
|
@@ -380,7 +373,7 @@ Nothing is forced. Centralization is a convenience, not a requirement.
|
|
|
380
373
|
## 🏗️ Project Structure
|
|
381
374
|
|
|
382
375
|
```
|
|
383
|
-
wasla
|
|
376
|
+
wasla/
|
|
384
377
|
├── apps/
|
|
385
378
|
│ ├── cli/src/ # CLI commands and visualizer server
|
|
386
379
|
│ └── visualizer/src/ # React visualizer
|
|
@@ -398,12 +391,10 @@ wasla-genie/
|
|
|
398
391
|
|
|
399
392
|
---
|
|
400
393
|
|
|
401
|
-
## 🌍 Why "
|
|
394
|
+
## 🌍 Why "Wasla"?
|
|
402
395
|
|
|
403
396
|
**Wasla (وصلة)** is Arabic for *connection* — the act of joining what was always separate.
|
|
404
397
|
|
|
405
|
-
**Genie** — it appears when summoned, connects what you need, and watches quietly in the background until called again.
|
|
406
|
-
|
|
407
398
|
Your agents live where they were born.
|
|
408
399
|
Your tools see everything.
|
|
409
400
|
Nothing is ever duplicated.
|
|
@@ -413,8 +404,8 @@ Nothing is ever duplicated.
|
|
|
413
404
|
## 🤝 Contributing
|
|
414
405
|
|
|
415
406
|
```bash
|
|
416
|
-
git clone https://github.com/The-Untitled-Org/wasla
|
|
417
|
-
cd wasla
|
|
407
|
+
git clone https://github.com/The-Untitled-Org/wasla
|
|
408
|
+
cd wasla
|
|
418
409
|
npm install
|
|
419
410
|
npm run visualizer:install
|
|
420
411
|
npm run dev
|
|
@@ -435,7 +426,7 @@ MIT © [The Untitled Org](https://github.com/The-Untitled-Org)
|
|
|
435
426
|
<div align="center">
|
|
436
427
|
|
|
437
428
|
**Your agents live where they were born.**
|
|
438
|
-
**
|
|
429
|
+
**Wasla makes sure every tool can find them.**
|
|
439
430
|
|
|
440
431
|
⭐ Star this repo if you are tired of copy-pasting the same config into five different tools.
|
|
441
432
|
|
|
@@ -13,11 +13,11 @@ function color(text, ...codes) {
|
|
|
13
13
|
}
|
|
14
14
|
export function banner() {
|
|
15
15
|
console.log(color(`
|
|
16
|
-
__ __ _
|
|
17
|
-
\\ \\ / /_ _ ___| | __ _
|
|
18
|
-
\\ \\ /\\ / / _\` / __| |/ _\` |
|
|
19
|
-
\\ V V / (_| \\__ \\ | (_| |
|
|
20
|
-
\\_/\\_/ \\__,_|___/_|\\__,_
|
|
16
|
+
__ __ _
|
|
17
|
+
\\ \\ / /_ _ ___| | __ _
|
|
18
|
+
\\ \\ /\\ / / _\` / __| |/ _\` |
|
|
19
|
+
\\ V V / (_| \\__ \\ | (_| |
|
|
20
|
+
\\_/\\_/ \\__,_|___/_|\\__,_|
|
|
21
21
|
`, ansi.bold, ansi.cyan));
|
|
22
22
|
}
|
|
23
23
|
export function success(message) {
|
|
@@ -27,7 +27,7 @@ export async function configCommand(options) {
|
|
|
27
27
|
const response = await prompts({
|
|
28
28
|
type: 'select',
|
|
29
29
|
name: 'scope',
|
|
30
|
-
message: 'Where should
|
|
30
|
+
message: 'Where should Wasla store and sync assets?',
|
|
31
31
|
choices: [
|
|
32
32
|
{ title: 'Workspace - current project only', value: 'workspace' },
|
|
33
33
|
{ title: 'User - available across all projects', value: 'user' },
|
|
@@ -2,7 +2,7 @@ import { section, success, error, highlight, spacer } from '../cli-output.js';
|
|
|
2
2
|
import { readConfiguredScope } from '#shared/config.js';
|
|
3
3
|
export async function installCommand() {
|
|
4
4
|
try {
|
|
5
|
-
section('Preparing
|
|
5
|
+
section('Preparing Wasla CLI...');
|
|
6
6
|
spacer();
|
|
7
7
|
const scope = await readConfiguredScope();
|
|
8
8
|
if (scope) {
|
|
@@ -10,8 +10,8 @@ export async function installCommand() {
|
|
|
10
10
|
}
|
|
11
11
|
else {
|
|
12
12
|
console.log('Choose a scope before running sync:');
|
|
13
|
-
console.log('
|
|
14
|
-
console.log('
|
|
13
|
+
console.log(' wasla config --scope user');
|
|
14
|
+
console.log(' wasla config --scope workspace');
|
|
15
15
|
}
|
|
16
16
|
spacer();
|
|
17
17
|
highlight('CLI setup complete!');
|
|
@@ -19,9 +19,9 @@ export async function installCommand() {
|
|
|
19
19
|
console.log('This command does not write skills into Claude, Gemini, or other tools.');
|
|
20
20
|
console.log('');
|
|
21
21
|
console.log('Common commands:');
|
|
22
|
-
console.log('
|
|
23
|
-
console.log('
|
|
24
|
-
console.log('
|
|
22
|
+
console.log(' wasla sync');
|
|
23
|
+
console.log(' wasla sync-to --from gemini --to claude');
|
|
24
|
+
console.log(' wasla register # optional: add Wasla helper skills to tools');
|
|
25
25
|
console.log('');
|
|
26
26
|
}
|
|
27
27
|
catch (err) {
|
|
@@ -35,7 +35,7 @@ export async function registerCommand(options = {}) {
|
|
|
35
35
|
targets = requested.map((name) => installedByName.get(name));
|
|
36
36
|
}
|
|
37
37
|
spacer();
|
|
38
|
-
section('Registering
|
|
38
|
+
section('Registering Wasla helper skills...');
|
|
39
39
|
spacer();
|
|
40
40
|
await ensureDir(getRegistryDir(scope));
|
|
41
41
|
for (const adapter of targets) {
|
|
@@ -9,7 +9,7 @@ export async function statusCommand() {
|
|
|
9
9
|
const scope = await requireConfiguredScope();
|
|
10
10
|
const registryPath = getRegistryPath(scope);
|
|
11
11
|
if (!(await fileExists(registryPath))) {
|
|
12
|
-
error('Registry not found. Run:
|
|
12
|
+
error('Registry not found. Run: wasla sync');
|
|
13
13
|
process.exit(1);
|
|
14
14
|
}
|
|
15
15
|
const registry = new RegistryManager(scope);
|
|
@@ -10,8 +10,8 @@ export async function syncToCommand(options) {
|
|
|
10
10
|
const to = options.to;
|
|
11
11
|
if (!from || !to) {
|
|
12
12
|
error('Error: --from and --to are required');
|
|
13
|
-
console.log('Usage:
|
|
14
|
-
console.log('Example:
|
|
13
|
+
console.log('Usage: wasla sync-to --from <source> --to <target>');
|
|
14
|
+
console.log('Example: wasla sync-to --from gemini --to claude');
|
|
15
15
|
process.exit(1);
|
|
16
16
|
}
|
|
17
17
|
const targets = to.split(',').map((t) => t.trim());
|
|
@@ -24,7 +24,7 @@ export async function watchCommand() {
|
|
|
24
24
|
ignored: [
|
|
25
25
|
/(^|[\/\\])node_modules([\/\\]|$)/,
|
|
26
26
|
/(^|[\/\\])\.git([\/\\]|$)/,
|
|
27
|
-
/(^|[\/\\])\.
|
|
27
|
+
/(^|[\/\\])\.wasla([\/\\]|$)/,
|
|
28
28
|
/(^|[\/\\])dist([\/\\]|$)/,
|
|
29
29
|
/(^|[\/\\])output([\/\\]|$)/,
|
|
30
30
|
],
|
|
@@ -27,13 +27,13 @@ function readPackageVersion(moduleUrl) {
|
|
|
27
27
|
}
|
|
28
28
|
}
|
|
29
29
|
program
|
|
30
|
-
.name('
|
|
30
|
+
.name('wasla')
|
|
31
31
|
.description('Universal synchronization layer for AI agent orchestrators')
|
|
32
32
|
.version(readPackageVersion(import.meta.url));
|
|
33
|
-
program.addCommand(new Command('install').description('Prepare
|
|
33
|
+
program.addCommand(new Command('install').description('Prepare Wasla CLI state').action(installCommand));
|
|
34
34
|
program.addCommand(new Command('register')
|
|
35
35
|
.option('--to <targets>', 'Target provider(s), comma-separated. Example: claude,gemini')
|
|
36
|
-
.description('Register
|
|
36
|
+
.description('Register Wasla helper skills inside installed AI tools')
|
|
37
37
|
.action((options) => registerCommand(options)));
|
|
38
38
|
program.addCommand(new Command('sync')
|
|
39
39
|
.description('Scan and sync agents/MCPs across tools')
|
|
@@ -49,7 +49,7 @@ program.addCommand(new Command('status')
|
|
|
49
49
|
program.addCommand(new Command('config')
|
|
50
50
|
.option('--scope <scope>', 'Set scope to user or workspace')
|
|
51
51
|
.option('--show', 'Show current config')
|
|
52
|
-
.description('Configure
|
|
52
|
+
.description('Configure Wasla settings')
|
|
53
53
|
.action(async (options) => {
|
|
54
54
|
await configCommand(options);
|
|
55
55
|
}));
|
|
@@ -18,7 +18,7 @@ async function getEntityContent(scope, type, name, providerId) {
|
|
|
18
18
|
const scanner = new Scanner(scope);
|
|
19
19
|
await scanner.initialize();
|
|
20
20
|
const assetType = mapEntityType(type);
|
|
21
|
-
const discovered = providerId === '
|
|
21
|
+
const discovered = providerId === 'wasla'
|
|
22
22
|
? await scanner.scanAllTools([assetType])
|
|
23
23
|
: await scanner.scanTool(providerId, [assetType]);
|
|
24
24
|
const target = discovered
|
|
@@ -49,8 +49,7 @@ function isAllowedOrigin(origin, port) {
|
|
|
49
49
|
return origin === `http://127.0.0.1:${port}` || origin === `http://localhost:${port}`;
|
|
50
50
|
}
|
|
51
51
|
function isKnownProvider(scope, providerId) {
|
|
52
|
-
return (providerId === '
|
|
53
|
-
getAllAdapters(scope).some((adapter) => adapter.name === providerId));
|
|
52
|
+
return (providerId === 'wasla' || getAllAdapters(scope).some((adapter) => adapter.name === providerId));
|
|
54
53
|
}
|
|
55
54
|
function mapEntityType(type) {
|
|
56
55
|
if (type === 'instruction')
|
|
@@ -88,7 +87,7 @@ function openBrowser(url) {
|
|
|
88
87
|
exec(`xdg-open "${url}"`);
|
|
89
88
|
}
|
|
90
89
|
export const PROVIDER_ICONS = {
|
|
91
|
-
|
|
90
|
+
wasla: '/logo.png',
|
|
92
91
|
claude: 'https://cdn.simpleicons.org/claude',
|
|
93
92
|
gemini: 'https://cdn.simpleicons.org/googlegemini',
|
|
94
93
|
cursor: 'https://cdn.simpleicons.org/cursor',
|
|
@@ -105,9 +104,9 @@ async function buildConfig(scope) {
|
|
|
105
104
|
const installedNames = new Set(installed.map((adapter) => adapter.name));
|
|
106
105
|
const providers = [
|
|
107
106
|
{
|
|
108
|
-
id: '
|
|
109
|
-
title: '
|
|
110
|
-
iconUrl: PROVIDER_ICONS.
|
|
107
|
+
id: 'wasla',
|
|
108
|
+
title: 'Wasla',
|
|
109
|
+
iconUrl: PROVIDER_ICONS.wasla,
|
|
111
110
|
isHub: true,
|
|
112
111
|
isInstalled: true,
|
|
113
112
|
},
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
export declare abstract class BaseAdapter implements
|
|
1
|
+
import { WaslaAdapter, Asset, AssetFormat } from '#core/types.js';
|
|
2
|
+
export declare abstract class BaseAdapter implements WaslaAdapter {
|
|
3
3
|
abstract name: string;
|
|
4
4
|
abstract displayName: string;
|
|
5
5
|
abstract mcpKey: string;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { BaseAdapter } from './base.js';
|
|
2
2
|
import { fileExists, writeText, ensureDir } from '#shared/fs.js';
|
|
3
|
-
import { join } from 'path';
|
|
3
|
+
import { dirname, join } from 'path';
|
|
4
4
|
import { getToolMarkers } from '#shared/paths.js';
|
|
5
5
|
export class ClaudeAdapter extends BaseAdapter {
|
|
6
6
|
constructor(scope = 'workspace') {
|
|
@@ -19,13 +19,16 @@ export class ClaudeAdapter extends BaseAdapter {
|
|
|
19
19
|
}
|
|
20
20
|
get paths() {
|
|
21
21
|
const markers = getToolMarkers(this.scope);
|
|
22
|
+
const workspaceRoot = dirname(markers.claude);
|
|
22
23
|
return {
|
|
23
24
|
agent: join(markers.claude, 'agents'),
|
|
24
25
|
skill: join(markers.claude, 'skills'),
|
|
25
26
|
mcp: this.scope === 'workspace'
|
|
26
27
|
? join(markers.claude, 'mcp.json')
|
|
27
28
|
: join(markers.claude, 'settings.json'),
|
|
28
|
-
context:
|
|
29
|
+
context: this.scope === 'workspace'
|
|
30
|
+
? join(workspaceRoot, 'CLAUDE.md')
|
|
31
|
+
: join(markers.claude, 'CLAUDE.md'),
|
|
29
32
|
};
|
|
30
33
|
}
|
|
31
34
|
get skillDirs() {
|
|
@@ -62,9 +65,9 @@ export class ClaudeAdapter extends BaseAdapter {
|
|
|
62
65
|
await writeText(targetPath, content);
|
|
63
66
|
}
|
|
64
67
|
async installSkill() {
|
|
65
|
-
// Write a
|
|
68
|
+
// Write a Wasla skill into Claude's native skills directory.
|
|
66
69
|
// We do NOT touch CLAUDE.md — that file belongs to the user.
|
|
67
|
-
const skillDir = join(this.paths.skill, '
|
|
70
|
+
const skillDir = join(this.paths.skill, 'wasla');
|
|
68
71
|
await ensureDir(skillDir);
|
|
69
72
|
const skillPath = join(skillDir, 'SKILL.md');
|
|
70
73
|
if (await fileExists(skillPath)) {
|
|
@@ -72,19 +75,19 @@ export class ClaudeAdapter extends BaseAdapter {
|
|
|
72
75
|
}
|
|
73
76
|
const skillContent = `---
|
|
74
77
|
description: >
|
|
75
|
-
Runs
|
|
78
|
+
Runs Wasla CLI commands to sync, inspect, or manage agents and MCPs
|
|
76
79
|
across AI orchestrators. Use when asked to sync tools, check sync status,
|
|
77
|
-
install
|
|
80
|
+
install Wasla, or troubleshoot why an agent isn't appearing in a tool.
|
|
78
81
|
---
|
|
79
82
|
|
|
80
|
-
#
|
|
83
|
+
# Wasla Operator
|
|
81
84
|
|
|
82
|
-
Use the \`
|
|
85
|
+
Use the \`wasla\` CLI to sync agents and MCPs across all installed AI tools.
|
|
83
86
|
|
|
84
87
|
\`\`\`bash
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
+
wasla sync # Mirror agents across all tools
|
|
89
|
+
wasla status # Show registry state
|
|
90
|
+
wasla watch # Auto-sync on file changes
|
|
88
91
|
\`\`\`
|
|
89
92
|
`;
|
|
90
93
|
await writeText(skillPath, skillContent);
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
export declare function getAdapter(toolName: string, scope?: 'user' | 'workspace'):
|
|
3
|
-
export declare function getInstalledAdapters(scope?: 'user' | 'workspace'): Promise<
|
|
4
|
-
export declare function getAllAdapters(scope?: 'user' | 'workspace'):
|
|
1
|
+
import { WaslaAdapter } from '#core/types.js';
|
|
2
|
+
export declare function getAdapter(toolName: string, scope?: 'user' | 'workspace'): WaslaAdapter;
|
|
3
|
+
export declare function getInstalledAdapters(scope?: 'user' | 'workspace'): Promise<WaslaAdapter[]>;
|
|
4
|
+
export declare function getAllAdapters(scope?: 'user' | 'workspace'): WaslaAdapter[];
|
|
@@ -64,30 +64,30 @@ export class GeminiAdapter extends BaseAdapter {
|
|
|
64
64
|
}
|
|
65
65
|
async installSkill() {
|
|
66
66
|
// Create the skills/ directory (Gemini CLI's native skill location) and
|
|
67
|
-
// write a
|
|
67
|
+
// write a Wasla skill file so Gemini knows how to run sync commands.
|
|
68
68
|
// We do NOT touch GEMINI.md — that file belongs to the user.
|
|
69
|
-
const skillDir = join(this.paths.skill, '
|
|
69
|
+
const skillDir = join(this.paths.skill, 'wasla');
|
|
70
70
|
await ensureDir(skillDir);
|
|
71
71
|
const skillPath = join(skillDir, 'SKILL.md');
|
|
72
72
|
if (await fileExists(skillPath)) {
|
|
73
73
|
return; // already installed, idempotent
|
|
74
74
|
}
|
|
75
75
|
const skillContent = `---
|
|
76
|
-
name:
|
|
76
|
+
name: wasla
|
|
77
77
|
description: >
|
|
78
|
-
Runs
|
|
78
|
+
Runs Wasla CLI commands to sync, inspect, or manage agents and MCPs
|
|
79
79
|
across AI orchestrators. Use when asked to sync tools, check sync status,
|
|
80
|
-
install
|
|
80
|
+
install Wasla, or troubleshoot why an agent isn't appearing in a tool.
|
|
81
81
|
---
|
|
82
82
|
|
|
83
|
-
#
|
|
83
|
+
# Wasla Operator
|
|
84
84
|
|
|
85
|
-
Use the \`
|
|
85
|
+
Use the \`wasla\` CLI to sync agents and MCPs across all installed AI tools.
|
|
86
86
|
|
|
87
87
|
\`\`\`bash
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
88
|
+
wasla sync # Mirror agents across all tools
|
|
89
|
+
wasla status # Show registry state
|
|
90
|
+
wasla watch # Auto-sync on file changes
|
|
91
91
|
\`\`\`
|
|
92
92
|
`;
|
|
93
93
|
await writeText(skillPath, skillContent);
|