@wire-protocol/cli 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.
@@ -0,0 +1,3 @@
1
+ export declare function configCommand(agent: string, opts: {
2
+ skills?: string;
3
+ }): Promise<void>;
@@ -0,0 +1,334 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.configCommand = configCommand;
7
+ const path_1 = __importDefault(require("path"));
8
+ const fs_1 = require("fs");
9
+ const core_1 = require("@wire/core");
10
+ async function configCommand(agent, opts) {
11
+ const supportedAgents = ['claude', 'cursor', 'antigravity'];
12
+ if (!supportedAgents.includes(agent)) {
13
+ console.error(`❌ Unsupported agent: "${agent}"`);
14
+ console.error(`Supported agents are: ${supportedAgents.join(', ')}`);
15
+ process.exit(1);
16
+ }
17
+ const skillsDir = opts.skills || '.wire';
18
+ console.log(`[Wire] Configuring integration for ${agent}...`);
19
+ // Step 1: Ensure skills directory exists so we can generate context
20
+ if (!(0, fs_1.existsSync)(skillsDir)) {
21
+ console.log(`[Wire] Creating ${skillsDir} directory...`);
22
+ (0, fs_1.mkdirSync)(skillsDir, { recursive: true });
23
+ }
24
+ // Generate system context
25
+ let contextStr = '';
26
+ let hasSkills = false;
27
+ let skillFiles = [];
28
+ if ((0, fs_1.existsSync)(skillsDir)) {
29
+ skillFiles = (0, fs_1.readdirSync)(skillsDir)
30
+ .filter((f) => f.endsWith('.wire.yaml'))
31
+ .map((f) => path_1.default.join(skillsDir, f));
32
+ hasSkills = skillFiles.length > 0;
33
+ }
34
+ try {
35
+ if (hasSkills) {
36
+ const engine = new core_1.WireEngine({
37
+ skills: skillFiles,
38
+ secrets: new core_1.EnvSecretsProvider()
39
+ });
40
+ await engine.init();
41
+ contextStr = engine.getSystemContext();
42
+ }
43
+ else {
44
+ contextStr = '## Wire API Skills\n(No skills configured yet. Add .wire.yaml files to the .wire/ directory)';
45
+ }
46
+ }
47
+ catch (e) {
48
+ if (e.message.includes('No .wire.yaml')) {
49
+ // It's okay if there are no skills yet, we just won't have context
50
+ contextStr = '## Wire API Skills\n(No skills configured yet. Add .wire.yaml files to the .wire/ directory)';
51
+ }
52
+ else {
53
+ console.warn(`[Wire] Warning: Could not generate system context: ${e.message}`);
54
+ }
55
+ }
56
+ switch (agent) {
57
+ case 'claude':
58
+ await configClaude(contextStr);
59
+ break;
60
+ case 'cursor':
61
+ await configCursor(contextStr);
62
+ break;
63
+ case 'antigravity':
64
+ await configAntigravity(contextStr);
65
+ break;
66
+ }
67
+ console.log(`\n✅ Successfully configured Wire for ${agent}!`);
68
+ }
69
+ async function configClaude(context) {
70
+ const claudeDir = '.claude';
71
+ if (!(0, fs_1.existsSync)(claudeDir))
72
+ (0, fs_1.mkdirSync)(claudeDir);
73
+ // 1a. Create .claude/wire-hook.sh — thin bash entry point that delegates to Node
74
+ // Using Node avoids shell re-entrancy: the hook calling `wire run` would itself
75
+ // trigger another PreToolUse hook, causing infinite recursion.
76
+ const hookShPath = path_1.default.join(claudeDir, 'wire-hook.sh');
77
+ const hookShContent = `#!/bin/bash
78
+ # Auto-generated by Wire Protocol
79
+ # Delegates to wire-hook.js to avoid Bash hook re-entrancy.
80
+ SCRIPT_DIR="$(cd "$(dirname "\${BASH_SOURCE[0]}")" && pwd)"
81
+ exec node "$SCRIPT_DIR/wire-hook.js"
82
+ `;
83
+ (0, fs_1.writeFileSync)(hookShPath, hookShContent);
84
+ (0, fs_1.chmodSync)(hookShPath, '755');
85
+ console.log(`Created ${hookShPath}`);
86
+ // 1b. Create .claude/wire-hook.js — Node.js hook that runs Wire engine in-process
87
+ const hookJsPath = path_1.default.join(claudeDir, 'wire-hook.js');
88
+ const coreDistPath = require.resolve('@wire/core').replace(/\/index\.js$/, '/index.js');
89
+ const hookJsContent = `#!/usr/bin/env node
90
+ // Auto-generated by Wire Protocol
91
+ // Claude Code PreToolUse hook — intercepts Bash commands and injects tokens.
92
+ // Runs Wire engine in-process (no subprocess) to avoid hook re-entrancy.
93
+
94
+ const { WireEngine } = require('${coreDistPath}')
95
+ const path = require('path')
96
+ const fs = require('fs')
97
+
98
+ const silentLogger = { info: () => {}, warn: () => {}, error: () => {} }
99
+
100
+ const APPROVE = JSON.stringify({
101
+ hookSpecificOutput: { hookEventName: 'PreToolUse', permissionDecision: 'allow' }
102
+ })
103
+
104
+ async function main() {
105
+ let input = ''
106
+ for await (const chunk of process.stdin) input += chunk
107
+
108
+ let toolInput
109
+ try { toolInput = JSON.parse(input) } catch { process.stdout.write(APPROVE + '\\n'); return }
110
+
111
+ const cmd = toolInput?.tool_input?.command || ''
112
+
113
+ // Not a Wire command — no \${PLACEHOLDER} tokens
114
+ if (!cmd || !/\\$\\{[A-Z_]+\\}/.test(cmd)) {
115
+ process.stdout.write(APPROVE + '\\n')
116
+ return
117
+ }
118
+
119
+ const projectRoot = path.resolve(__dirname, '..')
120
+ const wireDir = path.join(projectRoot, '.wire')
121
+ const skillFiles = fs.readdirSync(wireDir)
122
+ .filter(f => f.endsWith('.wire.yaml'))
123
+ .map(f => path.join(wireDir, f))
124
+
125
+ // Load .env from project root into process.env (skip keys already set)
126
+ const envFile = path.join(projectRoot, '.env')
127
+ if (fs.existsSync(envFile)) {
128
+ fs.readFileSync(envFile, 'utf8').split('\\n').forEach(line => {
129
+ const m = line.match(/^([A-Z_][A-Z0-9_]*)=(.*)$/)
130
+ if (m && !process.env[m[1]]) process.env[m[1]] = m[2].trim()
131
+ })
132
+ }
133
+
134
+ // Plain secrets provider — reads process.env directly, no dotenv re-loading
135
+ const secrets = {
136
+ get: async (key) => {
137
+ const val = process.env[key]
138
+ if (!val) throw new Error(\`Wire: Secret "\${key}" not found. Set it in .env or environment.\`)
139
+ return val
140
+ }
141
+ }
142
+
143
+ const engine = new WireEngine({ skills: skillFiles, secrets, logger: silentLogger, onBlock: () => {}, onConfirm: async () => true })
144
+ await engine.init()
145
+ const result = await engine.intercept(cmd)
146
+
147
+ if (!result.allowed) {
148
+ process.stdout.write(JSON.stringify({
149
+ hookSpecificOutput: {
150
+ hookEventName: 'PreToolUse',
151
+ permissionDecision: 'deny',
152
+ permissionDecisionReason: \`[Wire] \${result.reason || 'Blocked'}\`
153
+ }
154
+ }) + '\\n')
155
+ process.exit(2)
156
+ }
157
+
158
+ process.stdout.write(JSON.stringify({
159
+ hookSpecificOutput: {
160
+ hookEventName: 'PreToolUse',
161
+ permissionDecision: 'allow',
162
+ updatedInput: { command: result.sanitizedCmd }
163
+ }
164
+ }) + '\\n')
165
+ }
166
+
167
+ main().catch(err => {
168
+ process.stderr.write(\`[Wire] hook error: \${err.message}\\n\`)
169
+ process.stdout.write(APPROVE + '\\n')
170
+ })
171
+ `;
172
+ (0, fs_1.writeFileSync)(hookJsPath, hookJsContent);
173
+ console.log(`Created ${hookJsPath}`);
174
+ // 2. Update .claude/settings.json with correct hooks format
175
+ const settingsPath = path_1.default.join(claudeDir, 'settings.json');
176
+ let settings = {};
177
+ if ((0, fs_1.existsSync)(settingsPath)) {
178
+ try {
179
+ settings = JSON.parse((0, fs_1.readFileSync)(settingsPath, 'utf8'));
180
+ }
181
+ catch (e) {
182
+ console.warn(`Warning: Could not parse ${settingsPath}, overwriting.`);
183
+ }
184
+ }
185
+ // Remove legacy key if present
186
+ delete settings.bashInterceptor;
187
+ // Merge Wire hook into existing hooks config
188
+ if (!settings.hooks)
189
+ settings.hooks = {};
190
+ if (!settings.hooks.PreToolUse)
191
+ settings.hooks.PreToolUse = [];
192
+ // Remove any existing Wire hook entries to avoid duplicates
193
+ settings.hooks.PreToolUse = settings.hooks.PreToolUse.filter((entry) => !(entry.matcher === 'Bash' && entry.hooks?.some((h) => h.command?.includes('wire-hook'))));
194
+ settings.hooks.PreToolUse.push({
195
+ matcher: 'Bash',
196
+ hooks: [{ type: 'command', command: '.claude/wire-hook.sh' }]
197
+ });
198
+ (0, fs_1.writeFileSync)(settingsPath, JSON.stringify(settings, null, 2));
199
+ console.log(`Updated ${settingsPath} with PreToolUse hook`);
200
+ // 3. Write CLAUDE.md
201
+ writeContextFile('CLAUDE.md', context, [
202
+ '# Wire Protocol — Active',
203
+ '',
204
+ 'This project uses Wire for secure API access via bash. Wire intercepts all curl commands, validates them against registered skills, and injects real credentials at runtime.',
205
+ '',
206
+ '**Rules:**',
207
+ '- Use ONLY the `bash_template` patterns shown below',
208
+ '- NEVER hardcode tokens, keys, or secrets in commands',
209
+ '- NEVER construct curl commands manually for registered APIs',
210
+ '- Wire automatically injects `${TOKEN_NAME}` placeholders at runtime',
211
+ '- For write operations marked ⚠️ — always confirm with the user first',
212
+ '---'
213
+ ].join('\n'));
214
+ }
215
+ async function configCursor(context) {
216
+ // 1. Create cursor.config.js
217
+ const configPath = 'cursor.config.js';
218
+ const configContent = `// Auto-generated by Wire
219
+ const { createCursorAdapter } = require('@wire/adapter-cursor')
220
+ const wire = createCursorAdapter({ projectRoot: __dirname, skillsDir: '.wire' })
221
+
222
+ module.exports = {
223
+ async onBashToolCall(cmd) {
224
+ return wire.run(cmd)
225
+ }
226
+ }
227
+ `;
228
+ if (!(0, fs_1.existsSync)(configPath)) {
229
+ (0, fs_1.writeFileSync)(configPath, configContent);
230
+ console.log(`Created ${configPath}`);
231
+ }
232
+ else {
233
+ console.log(`Skipped ${configPath} (already exists)`);
234
+ }
235
+ // 2. Write .cursorrules
236
+ writeContextFile('.cursorrules', context, [
237
+ '# Wire Protocol — Active',
238
+ '',
239
+ 'This project uses Wire for secure API access via bash. Wire intercepts all curl commands, validates them against registered skills, and injects real credentials at runtime.',
240
+ '',
241
+ '**Rules:**',
242
+ '- Use ONLY the `bash_template` patterns shown below',
243
+ '- NEVER hardcode tokens, keys, or secrets in commands',
244
+ '- NEVER construct curl commands manually for registered APIs',
245
+ '- Wire automatically injects `${TOKEN_NAME}` placeholders at runtime',
246
+ '---'
247
+ ].join('\n'));
248
+ }
249
+ async function configAntigravity(context) {
250
+ const wireDir = '.wire';
251
+ if (!(0, fs_1.existsSync)(wireDir))
252
+ (0, fs_1.mkdirSync)(wireDir);
253
+ // 1. Create wrapper script
254
+ const wrapperPath = path_1.default.join(wireDir, 'antigravity-curl.sh');
255
+ const wrapperContent = `#!/bin/bash
256
+ # Send to Wire via JSON-RPC
257
+ ESCAPED_CMD=$(python3 -c 'import json,sys,shlex; print(json.dumps("curl " + " ".join(shlex.quote(a) for a in sys.argv[1:])))' "$@")
258
+
259
+ RESPONSE=$(printf '{"jsonrpc":"2.0","id":1,"method":"run","params":{"cmd":%s}}\n' "$ESCAPED_CMD" \\
260
+ | wire run --skills .wire/ 2>/dev/null)
261
+
262
+ echo "$RESPONSE" | python3 -c "
263
+ import sys, json
264
+
265
+ # Read all stdin
266
+ raw_input = sys.stdin.read()
267
+
268
+ # Try to find the JSON string by splitting lines and parsing the last line or the line starting with {
269
+ json_str = None
270
+ lines = raw_input.strip().split('\\n')
271
+ for line in reversed(lines):
272
+ if line.startswith('{\\"jsonrpc\\":'):
273
+ json_str = line
274
+ break
275
+
276
+ if not json_str:
277
+ for line in lines:
278
+ if line.startswith('{'):
279
+ try:
280
+ json.loads(line)
281
+ json_str = line
282
+ break
283
+ except:
284
+ pass
285
+
286
+ if not json_str:
287
+ sys.stderr.write(f\\"[Wire] Parse error: Could not find JSON in response: {raw_input}\\\\n\\")
288
+ sys.exit(1)
289
+
290
+ try:
291
+ r = json.loads(json_str)
292
+ if 'error' in r:
293
+ sys.stderr.write(f\\"[Wire] Error: {r['error'].get('message', 'Unknown error')}\\\\n\\")
294
+ sys.exit(1)
295
+ res = r.get('result', {})
296
+ if 'stdout' in res and res['stdout']: sys.stdout.write(res['stdout'])
297
+ if 'stderr' in res and res['stderr']: sys.stderr.write(res['stderr'])
298
+ sys.exit(res.get('exitCode', 0))
299
+ except Exception as e:
300
+ sys.stderr.write(f\\"[Wire] Parse error: {e}\\\\n\\")
301
+ sys.exit(1)
302
+ "
303
+ `;
304
+ (0, fs_1.writeFileSync)(wrapperPath, wrapperContent);
305
+ (0, fs_1.chmodSync)(wrapperPath, '755');
306
+ console.log(`Created executable wrapper ${wrapperPath}`);
307
+ // 2. Write ANTIGRAVITY.md
308
+ writeContextFile('ANTIGRAVITY.md', context, [
309
+ '# Wire Protocol for Antigravity',
310
+ '',
311
+ 'To use Wire with this agent, you must alias `curl` to point to the Wire wrapper:',
312
+ '',
313
+ '```bash',
314
+ 'alias curl="$(pwd)/.wire/antigravity-curl.sh"',
315
+ '```',
316
+ '',
317
+ 'Once aliased, run `curl` exactly as required by the templates below.',
318
+ 'Wire will automatically inject your environment variables for tokens.',
319
+ '---'
320
+ ].join('\n'));
321
+ }
322
+ function writeContextFile(filename, context, prefix) {
323
+ let content = '';
324
+ if ((0, fs_1.existsSync)(filename)) {
325
+ content = (0, fs_1.readFileSync)(filename, 'utf8');
326
+ if (content.includes('Wire API Skills')) {
327
+ console.log(`Updating existing Wire context in ${filename}`);
328
+ }
329
+ }
330
+ const fullContent = `${prefix}\n\n${context}\n\n${content}`;
331
+ (0, fs_1.writeFileSync)(filename, fullContent);
332
+ console.log(`Updated ${filename}`);
333
+ }
334
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/commands/config.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ interface InitOptions {
2
+ name?: string;
3
+ url?: string;
4
+ output?: string;
5
+ }
6
+ export declare function initCommand(opts?: InitOptions): Promise<void>;
7
+ export {};
@@ -0,0 +1,100 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.initCommand = initCommand;
7
+ const fs_1 = require("fs");
8
+ const path_1 = __importDefault(require("path"));
9
+ const readline_1 = __importDefault(require("readline"));
10
+ const TEMPLATE = (name, baseUrl) => {
11
+ const hostname = (() => {
12
+ try {
13
+ return new URL(baseUrl).hostname;
14
+ }
15
+ catch {
16
+ return baseUrl;
17
+ }
18
+ })();
19
+ const envKey = name.toUpperCase().replace(/-/g, '_') + '_TOKEN';
20
+ return `wire_version: "1"
21
+
22
+ skill:
23
+ name: ${name}
24
+ version: 1.0.0
25
+ description: "Describe what this API does in one sentence."
26
+ author: your-github-username
27
+ license: MIT
28
+ tags: []
29
+ base_url: ${baseUrl}
30
+
31
+ auth:
32
+ type: bearer
33
+ token_placeholder: \${${envKey}}
34
+ header: Authorization
35
+ prefix: "Bearer "
36
+
37
+ endpoints:
38
+
39
+ - id: example_endpoint
40
+ description: "What does this endpoint do?"
41
+ when_to_use: "When should the LLM call this endpoint?"
42
+ method: GET
43
+ path: /your/path/here
44
+ params:
45
+ - name: example_param
46
+ in: query
47
+ description: "What is this param?"
48
+ required: false
49
+ default: "default_value"
50
+ bash_template: |
51
+ curl -s \\
52
+ -H "Authorization: Bearer \${${envKey}}" \\
53
+ "${baseUrl}/your/path/here"
54
+ response:
55
+ format: json
56
+
57
+ security:
58
+ allowed_domains:
59
+ - ${hostname}
60
+ allowed_methods: [GET, POST, PUT]
61
+ rate_limit: 60/min
62
+ strip_from_logs: true
63
+ block_on_unknown_url: true
64
+ block_on_unknown_method: true
65
+
66
+ context_hint: |
67
+ Add workflow instructions for the LLM here. Describe call ordering,
68
+ pagination behavior, and what to confirm before write operations.
69
+
70
+ error_hints:
71
+ 401: "Token is invalid or expired. Ask the user to re-enter the token."
72
+ 403: "Insufficient permissions for this resource."
73
+ 404: "Resource not found. Verify your path parameters."
74
+ 429: "Rate limited. Wait before retrying."
75
+ `;
76
+ };
77
+ async function initCommand(opts = {}) {
78
+ const rl = readline_1.default.createInterface({ input: process.stdin, output: process.stdout });
79
+ const ask = (q, def) => new Promise(res => rl.question(def ? `${q} [${def}]: ` : `${q}: `, (ans) => res(ans.trim() || def || '')));
80
+ console.log('\n🔌 Wire — Skill file generator\n');
81
+ const name = opts.name || await ask('Skill name (e.g. sentry, datadog)');
82
+ if (!name) {
83
+ console.error('❌ Skill name is required.');
84
+ process.exit(1);
85
+ }
86
+ const baseUrl = opts.url || await ask('API base URL (e.g. https://api.example.com)');
87
+ if (!baseUrl) {
88
+ console.error('❌ API base URL is required.');
89
+ process.exit(1);
90
+ }
91
+ const outDir = opts.output || '.wire';
92
+ (0, fs_1.mkdirSync)(outDir, { recursive: true });
93
+ const filePath = path_1.default.join(outDir, `${name.toLowerCase()}.wire.yaml`);
94
+ (0, fs_1.writeFileSync)(filePath, TEMPLATE(name.toLowerCase(), baseUrl));
95
+ console.log(`\n✅ Created ${filePath}`);
96
+ console.log(`📝 Fill in your endpoints and run: wire validate ${filePath}`);
97
+ console.log(`🔑 Set your token: export ${name.toUpperCase().replace(/-/g, '_')}_TOKEN=your_token_here\n`);
98
+ rl.close();
99
+ }
100
+ //# sourceMappingURL=init.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"init.js","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":";;;;;AA0EA,kCAsBC;AAhGD,2BAA6C;AAC7C,gDAAuB;AACvB,wDAA+B;AAQ/B,MAAM,QAAQ,GAAG,CAAC,IAAY,EAAE,OAAe,EAAU,EAAE;IACzD,MAAM,QAAQ,GAAG,CAAC,GAAG,EAAE;QACrB,IAAI,CAAC;YAAC,OAAO,IAAI,GAAG,CAAC,OAAO,CAAC,CAAC,QAAQ,CAAA;QAAC,CAAC;QAAC,MAAM,CAAC;YAAC,OAAO,OAAO,CAAA;QAAC,CAAC;IACnE,CAAC,CAAC,EAAE,CAAA;IACJ,MAAM,MAAM,GAAG,IAAI,CAAC,WAAW,EAAE,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,GAAG,QAAQ,CAAA;IAE/D,OAAO;;;UAGC,IAAI;;;;;;cAMA,OAAO;;;;0BAIK,MAAM;;;;;;;;;;;;;;;;;;;uCAmBO,MAAM;WAClC,OAAO;;;;;;QAMV,QAAQ;;;;;;;;;;;;;;;;CAgBf,CAAA;AACD,CAAC,CAAA;AAEM,KAAK,UAAU,WAAW,CAAC,OAAoB,EAAE;IACtD,MAAM,EAAE,GAAG,kBAAQ,CAAC,eAAe,CAAC,EAAE,KAAK,EAAE,OAAO,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,CAAC,CAAA;IACrF,MAAM,GAAG,GAAG,CAAC,CAAS,EAAE,GAAY,EAAmB,EAAE,CACvD,IAAI,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,GAAG,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,EAAE,IAAI,GAAG,IAAI,EAAE,CAAC,CAAC,CAAC,CAAA;IAE5G,OAAO,CAAC,GAAG,CAAC,oCAAoC,CAAC,CAAA;IAEjD,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,IAAI,MAAM,GAAG,CAAC,mCAAmC,CAAC,CAAA;IACxE,IAAI,CAAC,IAAI,EAAE,CAAC;QAAC,OAAO,CAAC,KAAK,CAAC,2BAA2B,CAAC,CAAC;QAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;IAAC,CAAC;IAE1E,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,IAAI,MAAM,GAAG,CAAC,6CAA6C,CAAC,CAAA;IACpF,IAAI,CAAC,OAAO,EAAE,CAAC;QAAC,OAAO,CAAC,KAAK,CAAC,6BAA6B,CAAC,CAAC;QAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;IAAC,CAAC;IAE/E,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,IAAI,OAAO,CAAA;IACrC,IAAA,cAAS,EAAC,MAAM,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAA;IACtC,MAAM,QAAQ,GAAG,cAAI,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,IAAI,CAAC,WAAW,EAAE,YAAY,CAAC,CAAA;IACrE,IAAA,kBAAa,EAAC,QAAQ,EAAE,QAAQ,CAAC,IAAI,CAAC,WAAW,EAAE,EAAE,OAAO,CAAC,CAAC,CAAA;IAE9D,OAAO,CAAC,GAAG,CAAC,eAAe,QAAQ,EAAE,CAAC,CAAA;IACtC,OAAO,CAAC,GAAG,CAAC,oDAAoD,QAAQ,EAAE,CAAC,CAAA;IAC3E,OAAO,CAAC,GAAG,CAAC,6BAA6B,IAAI,CAAC,WAAW,EAAE,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,0BAA0B,CAAC,CAAA;IACzG,EAAE,CAAC,KAAK,EAAE,CAAA;AACZ,CAAC"}
@@ -0,0 +1,3 @@
1
+ type RegistryAction = 'add' | 'install' | 'list' | 'remove' | 'uninstall' | 'search' | 'info' | 'publish';
2
+ export declare function registryCommand(action: RegistryAction, arg?: string): Promise<void>;
3
+ export {};