jaspervault_cli 1.1.0 → 1.1.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.
Files changed (59) hide show
  1. package/README.md +8 -19
  2. package/config/chains.json +1 -3
  3. package/dist/bin/jv.js +4 -2
  4. package/dist/bin/jv.js.map +1 -1
  5. package/dist/src/commands/deposit.js +1 -1
  6. package/dist/src/commands/deposit.js.map +1 -1
  7. package/dist/src/commands/install.js +1 -1
  8. package/dist/src/commands/install.js.map +1 -1
  9. package/dist/src/commands/order.js +179 -46
  10. package/dist/src/commands/order.js.map +1 -1
  11. package/dist/src/commands/orders.js +2 -2
  12. package/dist/src/commands/orders.js.map +1 -1
  13. package/dist/src/commands/sl.js +3 -3
  14. package/dist/src/commands/sl.js.map +1 -1
  15. package/dist/src/commands/tp.js +3 -3
  16. package/dist/src/commands/tp.js.map +1 -1
  17. package/dist/src/commands/vault.d.ts +1 -6
  18. package/dist/src/commands/vault.js +15 -70
  19. package/dist/src/commands/vault.js.map +1 -1
  20. package/dist/src/commands/wallet.d.ts +2 -0
  21. package/dist/src/commands/wallet.js +126 -0
  22. package/dist/src/commands/wallet.js.map +1 -0
  23. package/dist/src/commands/withdraw.js +2 -2
  24. package/dist/src/commands/withdraw.js.map +1 -1
  25. package/dist/src/mcp/index.js +3 -7
  26. package/dist/src/mcp/index.js.map +1 -1
  27. package/dist/src/mcp/tools.js +23 -6
  28. package/dist/src/mcp/tools.js.map +1 -1
  29. package/dist/src/services/chain-config.d.ts +4 -3
  30. package/dist/src/services/chain-config.js +13 -5
  31. package/dist/src/services/chain-config.js.map +1 -1
  32. package/dist/src/services/key-manager.js +4 -12
  33. package/dist/src/services/key-manager.js.map +1 -1
  34. package/dist/src/services/order-signer.js +2 -2
  35. package/dist/src/services/order-signer.js.map +1 -1
  36. package/dist/src/services/perps-order.d.ts +48 -0
  37. package/dist/src/services/perps-order.js +66 -0
  38. package/dist/src/services/perps-order.js.map +1 -0
  39. package/dist/src/services/profile-manager.d.ts +49 -0
  40. package/dist/src/services/profile-manager.js +179 -0
  41. package/dist/src/services/profile-manager.js.map +1 -0
  42. package/dist/src/services/vault-profile.js +4 -12
  43. package/dist/src/services/vault-profile.js.map +1 -1
  44. package/dist/src/templates/skill-content/SKILL.core.md +26 -24
  45. package/dist/src/templates/skill-content/references/onboarding.md +1 -1
  46. package/dist/src/templates/skill-content/references/queries.md +20 -0
  47. package/dist/src/templates/skill-content/references/trading.md +64 -33
  48. package/docs/OPENCLAW_GUIDE.md +136 -0
  49. package/docs/USER_GUIDE.md +276 -0
  50. package/package.json +3 -2
  51. package/dist/src/commands/connect.d.ts +0 -26
  52. package/dist/src/commands/connect.js +0 -93
  53. package/dist/src/commands/connect.js.map +0 -1
  54. package/dist/src/commands/init.d.ts +0 -4
  55. package/dist/src/commands/init.js +0 -114
  56. package/dist/src/commands/init.js.map +0 -1
  57. package/dist/src/commands/skill.d.ts +0 -4
  58. package/dist/src/commands/skill.js +0 -117
  59. package/dist/src/commands/skill.js.map +0 -1
@@ -0,0 +1,276 @@
1
+ # User Guide
2
+
3
+ Complete reference for the JasperVault CLI (`jv`). This guide covers installation, wallet setup, trading operations, and advanced configuration.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install -g jaspervault_cli
9
+ ```
10
+
11
+ Verify:
12
+
13
+ ```bash
14
+ jv --version
15
+ ```
16
+
17
+ **Requirements:** Node.js 18+
18
+
19
+ ## Wallet Setup
20
+
21
+ Before trading, you need to initialize your vault. This creates an AA (Account Abstraction) wallet and a local delegation key.
22
+
23
+ ```bash
24
+ jv enable --pretty
25
+ ```
26
+
27
+ This opens a hosted web page where you connect your wallet (MetaMask, Rabby, etc.) and sign a delegation authorization. Your private key never leaves the browser.
28
+
29
+ After setup completes, your delegation key and vault profile are saved to `~/.jaspervault/`. All subsequent commands use these automatically.
30
+
31
+ ## Deposits & Withdrawals
32
+
33
+ Bridge assets between Base and JasperVault via Hyperlane.
34
+
35
+ **Deposit:**
36
+
37
+ ```bash
38
+ jv deposit --token usdc --amount 100 --pretty
39
+ ```
40
+
41
+ **Withdraw:**
42
+
43
+ ```bash
44
+ jv withdraw --token usdc --amount 100 --pretty
45
+ ```
46
+
47
+ Both commands open a hosted web page for you to approve the transaction in your browser wallet.
48
+
49
+ ## Trading
50
+
51
+ ### Market Orders
52
+
53
+ Execute immediately at current market price.
54
+
55
+ ```bash
56
+ # Long BTC, 100 USDC margin, 50x leverage
57
+ jv order create --side long --symbol JBTC --margin 100 --leverage 50
58
+
59
+ # Short BTC, 50 USDC margin, 100x leverage
60
+ jv order create --side short --symbol JBTC --margin 50 --leverage 100
61
+ ```
62
+
63
+ Market orders return a `jobId`. The order typically confirms on-chain within seconds.
64
+
65
+ ### Limit Orders
66
+
67
+ Execute when price reaches the target.
68
+
69
+ ```bash
70
+ # Short BTC at $95,000
71
+ jv order create --side short --symbol JBTC --margin 50 --leverage 100 --limit-price 95000
72
+ ```
73
+
74
+ Limit orders return a `limitOrderId` and remain active until triggered, expired, or cancelled.
75
+
76
+ ### Close a Position
77
+
78
+ Use `jv order close` for a **full** close. It reads the position's side, margin,
79
+ symbol, and leverage on-chain and submits the reverse order for you — no need to
80
+ look anything up first.
81
+
82
+ ```bash
83
+ # Close a single position by order ID
84
+ jv order close --order-id 99
85
+
86
+ # Close every active position
87
+ jv order close --all
88
+ ```
89
+
90
+ Under the hood, JasperVault has no native close endpoint — closing is a
91
+ reverse-side order with the same margin. `jv order close` just does that
92
+ derivation for you.
93
+
94
+ For a **partial** close, use `jv order create` directly with the opposite side
95
+ and a smaller margin than the position:
96
+
97
+ ```bash
98
+ # Partial close: reduce a LONG position by half (position has 100 USDC margin)
99
+ jv order create --side short --symbol JBTC --margin 50
100
+ ```
101
+
102
+ Check your positions any time with `jv orders list --pretty`.
103
+
104
+ ### Take-Profit & Stop-Loss
105
+
106
+ ```bash
107
+ jv tp set --order-id 99 --price 105000 --symbol JBTC
108
+ jv sl set --order-id 99 --price 88000 --symbol JBTC
109
+ ```
110
+
111
+ ## PPO Hedge Protection
112
+
113
+ PPO (Perpetual Protection Option) is JasperVault's on-chain hedge option that protects leveraged positions against sudden price wicks and liquidation cascades.
114
+
115
+ ### Why PPO
116
+
117
+ In leveraged perpetual trading, flash crashes and price wicks ("pin bars") can liquidate positions in seconds — even when the market quickly recovers. Traditional stop-loss orders execute *at* the wick price, locking in maximum loss. PPO solves this by attaching a real option contract to your position:
118
+
119
+ - **Survives the wick** — the option payoff offsets unrealized loss, keeping your position alive through the spike
120
+ - **No slippage** — peer-to-peer fully collateralized settlement on-chain, independent of orderbook depth or liquidity
121
+ - **Auto hedge type** — LONG positions get PUT options, SHORT positions get CALL options (selected automatically)
122
+
123
+ ### Using PPO
124
+
125
+ **Open a position with PPO:**
126
+
127
+ ```bash
128
+ jv order create --side long --symbol JBTC --margin 100 --leverage 50 --ppo
129
+ ```
130
+
131
+ **Add PPO to an existing position:**
132
+
133
+ ```bash
134
+ jv order protect --order-id 42 --symbol JBTC
135
+ ```
136
+
137
+ **Customize PPO parameters:**
138
+
139
+ ```bash
140
+ jv order create --side long --symbol JBTC --margin 100 --leverage 50 \
141
+ --ppo --ppo-expire 8h --ppo-category OTM --ppo-tier 3
142
+ ```
143
+
144
+ ### PPO Parameters
145
+
146
+ | Parameter | Options | Default | Description |
147
+ |-----------|---------|---------|-------------|
148
+ | `--ppo` | flag | off | Enable PPO protection |
149
+ | `--ppo-category` | `ATM`, `OTM` | `ATM` | ATM = strike at current price; OTM = offset from current price |
150
+ | `--ppo-tier` | `1`–`5` | — | OTM strike offset (0.1%–0.5%). Required when category is OTM |
151
+ | `--ppo-expire` | `30m`, `8h` | `30m` | Option expiry duration |
152
+
153
+ ### OTM Tiers
154
+
155
+ | Tier | Strike Offset | Use Case |
156
+ |------|---------------|----------|
157
+ | 1 | 0.1% | Tight protection, higher premium |
158
+ | 2 | 0.2% | Balanced |
159
+ | 3 | 0.3% | Moderate offset |
160
+ | 4 | 0.4% | Wider offset, lower premium |
161
+ | 5 | 0.5% | Maximum offset, lowest premium |
162
+
163
+ ### PPO Lifecycle
164
+
165
+ - **Combine with any operation** — PPO can be added when opening, adding size, or setting TP/SL
166
+ - **Auto-cancellation** — Executing any position operation *without* `--ppo` automatically cancels the existing PPO on that position
167
+ - **Keep PPO on reduce** — Add `--ppo` when partially closing to maintain protection on the remaining position
168
+ - **No separate cancel** — There is no "cancel PPO" command. To remove PPO, execute any position operation without the `--ppo` flag
169
+
170
+ ## Querying Data
171
+
172
+ ```bash
173
+ # List active positions
174
+ jv orders list --pretty
175
+
176
+ # Get specific order details
177
+ jv orders get <orderId> --pretty
178
+
179
+ # Portfolio statistics
180
+ jv orders stats --pretty
181
+
182
+ # Real-time price
183
+ jv price --symbol JBTC --pretty
184
+
185
+ # Check market order execution status
186
+ jv job status <jobId> --pretty
187
+ ```
188
+
189
+ ### Limit Order Management
190
+
191
+ ```bash
192
+ # List limit orders
193
+ jv limit-order list --wallet 0x... --status PENDING --pretty
194
+
195
+ # Check status
196
+ jv limit-order status <limitOrderId>
197
+
198
+ # Cancel
199
+ jv limit-order cancel <limitOrderId>
200
+ ```
201
+
202
+ ## AI Platform Integration
203
+
204
+ Install JasperVault trading capabilities into your AI agent:
205
+
206
+ ```bash
207
+ jv install --ai claude # Claude Code (project-level)
208
+ jv install --ai claude --global # Claude Code (user-level)
209
+ jv install --ai cursor # Cursor (project-level)
210
+ jv install --ai cursor --global # Cursor (user-level)
211
+ jv install --ai openclaw # OpenClaw
212
+ jv install # All platforms (global)
213
+ ```
214
+
215
+ After installation, your AI can execute trades via MCP tools or skills. See the [OpenClaw Guide](OPENCLAW_GUIDE.md) for platform-specific setup details.
216
+
217
+ ## Configuration
218
+
219
+ All environment variables are optional. The CLI works out of the box with sensible defaults.
220
+
221
+ | Variable | Description | Default |
222
+ |----------|-------------|---------|
223
+ | `JV_API_URL` | Trading API endpoint | Production endpoint |
224
+ | `JV_API_KEY` | Bearer token for API auth | — |
225
+ | `JV_TIMEOUT` | Request timeout (ms) | 30000 |
226
+ | `JV_DELEGATION_KEY` | Delegation wallet key | Auto-generated |
227
+ | `BASE_HTTP_RPC_URL` | Base chain RPC (required) | — |
228
+ | `JV_JASPERVAULT_RPC_URL` | JasperVault chain RPC | Built-in |
229
+ | `JV_SUBGRAPH_URL` | Subgraph endpoint | Built-in |
230
+
231
+ ### Local Override Example
232
+
233
+ ```bash
234
+ export JV_API_URL=http://localhost:3000
235
+ ```
236
+
237
+ ### Configuration Files
238
+
239
+ | Path | Purpose |
240
+ |------|---------|
241
+ | `~/.jaspervault/keys.json` | Delegation wallet key (auto-generated) |
242
+ | `~/.jaspervault/profile.json` | Vault addresses and type mappings |
243
+
244
+ ## Output Formats
245
+
246
+ - **JSON** (default) — Machine-readable, suitable for scripting and piping
247
+ - **Pretty** — Human-readable tables. Append `--pretty` to any command
248
+
249
+ ## Exit Codes
250
+
251
+ | Code | Meaning |
252
+ |------|---------|
253
+ | 0 | Success |
254
+ | 1 | Configuration error (missing params, invalid input) |
255
+ | 2 | Network / HTTP error |
256
+ | 3 | Business error (API-level rejection) |
257
+
258
+ ## Updates
259
+
260
+ ```bash
261
+ jv update # Check and install latest version
262
+ ```
263
+
264
+ ## FAQ
265
+
266
+ **Q: Do I need to export my private key?**
267
+ No. Browser signing keeps your keys in your wallet. Your private key never leaves the browser.
268
+
269
+ **Q: How do I switch networks?**
270
+ Set `JV_API_URL` to your target environment's API endpoint.
271
+
272
+ **Q: Is my delegation key safe?**
273
+ The delegation key is generated locally and stored in `~/.jaspervault/keys.json`. It can only execute trades within the scope authorized by your delegation signature. It cannot transfer or withdraw funds without additional browser signing.
274
+
275
+ **Q: What trading pairs are available?**
276
+ Currently BTC perpetuals (symbol: `JBTC`). Additional pairs will be added — check `jv price --symbol <symbol>` for availability.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "jaspervault_cli",
3
- "version": "1.1.0",
3
+ "version": "1.1.2",
4
4
  "description": "JasperVault CLI for interacting with the JasperVault Manager API",
5
5
  "type": "module",
6
6
  "bin": {
@@ -19,7 +19,8 @@
19
19
  },
20
20
  "files": [
21
21
  "dist",
22
- "config"
22
+ "config",
23
+ "docs"
23
24
  ],
24
25
  "keywords": [
25
26
  "jaspervault",
@@ -1,26 +0,0 @@
1
- import { SignClient } from '@walletconnect/sign-client';
2
- export declare function startHeartbeat(phase: string, message: string): {
3
- stop: () => void;
4
- };
5
- export interface InitWcResult {
6
- client: InstanceType<typeof SignClient>;
7
- session: {
8
- topic: string;
9
- pairingTopic: string;
10
- namespaces: Record<string, {
11
- accounts: string[];
12
- }>;
13
- };
14
- walletAddress: string;
15
- }
16
- export interface QrCodeOutput {
17
- qrCodeUrl: string;
18
- }
19
- /**
20
- * Initialize WalletConnect SignClient, connect, show QR, wait for approval.
21
- * Returns client + session + walletAddress for further requests (e.g. eth_signTypedData_v4).
22
- */
23
- export declare function initWcAndConnect(opts: {
24
- timeoutS: number;
25
- onAwaiting?: (uri: string, qrCodes: QrCodeOutput) => void;
26
- }): Promise<InitWcResult>;
@@ -1,93 +0,0 @@
1
- import * as fs from 'node:fs/promises';
2
- import { join } from 'node:path';
3
- import { SignClient } from '@walletconnect/sign-client';
4
- import QRCode from 'qrcode';
5
- import { exitWithError, EXIT_CODES } from '../utils/output.js';
6
- const DEFAULT_TIMEOUT_S = 120;
7
- const HEARTBEAT_INTERVAL_MS = 10_000;
8
- export function startHeartbeat(phase, message) {
9
- const start = Date.now();
10
- const timer = setInterval(() => {
11
- const elapsed = Math.round((Date.now() - start) / 1000);
12
- process.stderr.write(JSON.stringify({ status: 'waiting', phase, elapsed, message }) + '\n');
13
- }, HEARTBEAT_INTERVAL_MS);
14
- return { stop: () => clearInterval(timer) };
15
- }
16
- // Embedded project ID — users can override with WC_PROJECT_ID env var
17
- const DEFAULT_WC_PROJECT_ID = 'f47863c3ad29e5bae9cee8013ec05982';
18
- const WC_METADATA = {
19
- name: 'JasperVault CLI',
20
- description: 'JasperVault perpetual trading CLI',
21
- url: 'https://jaspervault.io',
22
- icons: [],
23
- };
24
- function getJvDir() {
25
- return join(process.env.HOME || process.env.USERPROFILE || '', '.jaspervault');
26
- }
27
- function getQrCodePath() {
28
- return join(getJvDir(), 'wc-qrcode.png');
29
- }
30
- function buildQrCodeUrl(data) {
31
- return `https://api.qrserver.com/v1/create-qr-code/?size=400x400&data=${encodeURIComponent(data)}`;
32
- }
33
- /**
34
- * Initialize WalletConnect SignClient, connect, show QR, wait for approval.
35
- * Returns client + session + walletAddress for further requests (e.g. eth_signTypedData_v4).
36
- */
37
- export async function initWcAndConnect(opts) {
38
- const projectId = process.env.WC_PROJECT_ID || DEFAULT_WC_PROJECT_ID;
39
- let client;
40
- try {
41
- client = await SignClient.init({
42
- projectId,
43
- metadata: WC_METADATA,
44
- });
45
- }
46
- catch (err) {
47
- exitWithError(`Failed to initialize WalletConnect: ${err.message}`, EXIT_CODES.HTTP_ERROR);
48
- }
49
- const { uri, approval } = await client.connect({
50
- optionalNamespaces: {
51
- eip155: {
52
- chains: ['eip155:8453', 'eip155:55531'],
53
- methods: ['eth_signTypedData_v4', 'eth_sendTransaction'],
54
- events: ['accountsChanged', 'chainChanged'],
55
- },
56
- },
57
- });
58
- if (!uri) {
59
- exitWithError('WalletConnect did not return a pairing URI', EXIT_CODES.HTTP_ERROR);
60
- }
61
- await fs.mkdir(getJvDir(), { recursive: true });
62
- const qrPath = getQrCodePath();
63
- await QRCode.toFile(qrPath, uri, { width: 400, errorCorrectionLevel: 'M' });
64
- const qrCodeUrl = buildQrCodeUrl(uri);
65
- opts.onAwaiting?.(uri, { qrCodeUrl });
66
- const heartbeat = startHeartbeat('wallet_scan', 'Waiting for wallet connection...');
67
- const timeoutMs = opts.timeoutS * 1000;
68
- let session;
69
- try {
70
- session = await Promise.race([
71
- approval(),
72
- new Promise((_, reject) => setTimeout(() => reject(new Error('timeout')), timeoutMs)),
73
- ]);
74
- }
75
- catch (err) {
76
- heartbeat.stop();
77
- const msg = err.message;
78
- if (msg === 'timeout') {
79
- throw new Error(`Connection timed out after ${opts.timeoutS}s`);
80
- }
81
- throw new Error(`Connection rejected or failed: ${msg}`);
82
- }
83
- heartbeat.stop();
84
- const accounts = Object.values(session.namespaces).flatMap((ns) => ns.accounts);
85
- const firstAccount = accounts[0];
86
- if (!firstAccount) {
87
- exitWithError('No accounts returned from wallet', EXIT_CODES.BUSINESS_ERROR);
88
- }
89
- const parts = firstAccount.split(':');
90
- const walletAddress = parts[2];
91
- return { client, session, walletAddress };
92
- }
93
- //# sourceMappingURL=connect.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"connect.js","sourceRoot":"","sources":["../../../src/commands/connect.ts"],"names":[],"mappings":"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"}
@@ -1,4 +0,0 @@
1
- import { Command } from 'commander';
2
- export declare const PLATFORMS: readonly ["openclaw", "cursor", "claude", "all"];
3
- export type Platform = (typeof PLATFORMS)[number];
4
- export declare function registerInitCommand(program: Command): void;
@@ -1,114 +0,0 @@
1
- import * as fs from 'node:fs/promises';
2
- import * as path from 'node:path';
3
- import { homedir } from 'node:os';
4
- import { BANNER, buildSkillContent } from '../templates/skill-body.js';
5
- export const PLATFORMS = ['openclaw', 'cursor', 'claude', 'all'];
6
- const SKILL_DIR = 'jasper-vault-cli';
7
- function getTargetPath(platform, global) {
8
- const home = homedir();
9
- const cwd = process.cwd();
10
- switch (platform) {
11
- case 'openclaw':
12
- return [path.join(home, '.openclaw', 'skills', SKILL_DIR)];
13
- case 'cursor':
14
- return global
15
- ? [path.join(home, '.cursor', 'skills', SKILL_DIR)]
16
- : [path.join(cwd, '.cursor', 'skills', SKILL_DIR)];
17
- case 'claude':
18
- return global
19
- ? [path.join(home, '.claude', 'skills', SKILL_DIR)]
20
- : [path.join(cwd, '.claude', 'skills', SKILL_DIR)];
21
- case 'all':
22
- return [
23
- path.join(home, '.openclaw', 'skills', SKILL_DIR),
24
- path.join(cwd, '.cursor', 'skills', SKILL_DIR),
25
- path.join(cwd, '.claude', 'skills', SKILL_DIR),
26
- ];
27
- default:
28
- throw new Error(`Unknown platform: ${platform}`);
29
- }
30
- }
31
- function getPlatformFromPath(pathStr) {
32
- if (pathStr.includes('.openclaw'))
33
- return 'openclaw';
34
- if (pathStr.includes('.cursor'))
35
- return 'cursor';
36
- if (pathStr.includes('.claude'))
37
- return 'claude';
38
- throw new Error(`Cannot determine platform from path: ${pathStr}`);
39
- }
40
- function getPlatformDisplayName(p) {
41
- return p === 'openclaw' ? 'OpenClaw' : p === 'cursor' ? 'Cursor' : 'Claude Code';
42
- }
43
- export function registerInitCommand(program) {
44
- program
45
- .command('init')
46
- .description('Install JasperVault skill to AI platform (OpenClaw, Cursor, Claude Code)')
47
- .requiredOption('--ai <platform>', `Target platform: ${PLATFORMS.join(', ')}`)
48
- .option('--global', 'Install to user home directory (cursor/claude only)')
49
- .option('--force', 'Overwrite existing skill files without prompting')
50
- .action(async (opts) => {
51
- const platform = opts.ai;
52
- if (!PLATFORMS.includes(platform)) {
53
- process.stderr.write(`Error: Invalid platform "${platform}". Use one of: ${PLATFORMS.join(', ')}\n`);
54
- process.exit(1);
55
- }
56
- const globalFlag = opts.global ?? false;
57
- const force = opts.force ?? false;
58
- const targetPaths = getTargetPath(platform, globalFlag);
59
- process.stdout.write(BANNER + '\n\n');
60
- const results = [];
61
- for (const targetDir of targetPaths) {
62
- const skillPlatform = platform === 'all' ? getPlatformFromPath(targetDir) : platform;
63
- const platDisplay = getPlatformDisplayName(skillPlatform);
64
- try {
65
- const skillMdPath = path.join(targetDir, 'SKILL.md');
66
- const exists = await fs
67
- .access(skillMdPath)
68
- .then(() => true)
69
- .catch(() => false);
70
- if (exists && !force) {
71
- process.stderr.write(`Error: Skill already exists at ${targetDir}\n` +
72
- 'Use --force to overwrite.\n');
73
- process.exit(1);
74
- }
75
- const files = buildSkillContent(skillPlatform);
76
- let fileCount = 0;
77
- for (const [relPath, content] of Object.entries(files)) {
78
- const filePath = path.join(targetDir, relPath);
79
- await fs.mkdir(path.dirname(filePath), { recursive: true });
80
- await fs.writeFile(filePath, content, 'utf8');
81
- fileCount++;
82
- }
83
- // Make scripts executable
84
- const scriptsDir = path.join(targetDir, 'scripts');
85
- const scriptsDirExists = await fs
86
- .access(scriptsDir)
87
- .then(() => true)
88
- .catch(() => false);
89
- if (scriptsDirExists) {
90
- const scriptFiles = await fs.readdir(scriptsDir);
91
- for (const sf of scriptFiles) {
92
- if (sf.endsWith('.sh')) {
93
- await fs.chmod(path.join(scriptsDir, sf), 0o755);
94
- }
95
- }
96
- }
97
- results.push({ path: targetDir, platform: platDisplay, fileCount });
98
- }
99
- catch (err) {
100
- process.stderr.write(`Error installing to ${platDisplay}: ${err.message}\n`);
101
- process.exit(1);
102
- }
103
- }
104
- process.stdout.write('\n ✓ Skill installed successfully!\n\n' +
105
- results
106
- .map((r) => ` Platform: ${r.platform}\n Location: ${r.path}\n Files: ${r.fileCount} (SKILL.md + references/ + scripts/)`)
107
- .join('\n\n') +
108
- '\n\n Next steps:\n' +
109
- ' 1. First-time setup: jv vault setup --network jaspervault\n' +
110
- ' 2. (Optional) Override API URL for local debugging: export JV_API_URL=http://localhost:3000\n' +
111
- ' 3. Start using jv commands or let your AI agent call them\n');
112
- });
113
- }
114
- //# sourceMappingURL=init.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"init.js","sourceRoot":"","sources":["../../../src/commands/init.ts"],"names":[],"mappings":"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"}
@@ -1,4 +0,0 @@
1
- import { Command } from 'commander';
2
- export declare const PLATFORMS: readonly ["openclaw", "cursor", "claude", "all"];
3
- export type Platform = (typeof PLATFORMS)[number];
4
- export declare function registerSkillCommand(program: Command): void;
@@ -1,117 +0,0 @@
1
- import * as fs from 'node:fs/promises';
2
- import * as path from 'node:path';
3
- import { homedir } from 'node:os';
4
- import { BANNER, buildSkillContent } from '../templates/skill-body.js';
5
- export const PLATFORMS = ['openclaw', 'cursor', 'claude', 'all'];
6
- const SKILL_DIR = 'jasper-vault-cli';
7
- function getTargetPath(platform, global) {
8
- const home = homedir();
9
- const cwd = process.cwd();
10
- switch (platform) {
11
- case 'openclaw':
12
- return [path.join(home, '.openclaw', 'skills', SKILL_DIR)];
13
- case 'cursor':
14
- return global
15
- ? [path.join(home, '.cursor', 'skills', SKILL_DIR)]
16
- : [path.join(cwd, '.cursor', 'skills', SKILL_DIR)];
17
- case 'claude':
18
- return global
19
- ? [path.join(home, '.claude', 'skills', SKILL_DIR)]
20
- : [path.join(cwd, '.claude', 'skills', SKILL_DIR)];
21
- case 'all':
22
- return [
23
- path.join(home, '.openclaw', 'skills', SKILL_DIR),
24
- path.join(cwd, '.cursor', 'skills', SKILL_DIR),
25
- path.join(cwd, '.claude', 'skills', SKILL_DIR),
26
- ];
27
- default:
28
- throw new Error(`Unknown platform: ${platform}`);
29
- }
30
- }
31
- function getPlatformFromPath(pathStr) {
32
- if (pathStr.includes('.openclaw'))
33
- return 'openclaw';
34
- if (pathStr.includes('.cursor'))
35
- return 'cursor';
36
- if (pathStr.includes('.claude'))
37
- return 'claude';
38
- throw new Error(`Cannot determine platform from path: ${pathStr}`);
39
- }
40
- function getPlatformDisplayName(p) {
41
- return p === 'openclaw' ? 'OpenClaw' : p === 'cursor' ? 'Cursor' : 'Claude Code';
42
- }
43
- export function registerSkillCommand(program) {
44
- const skill = program
45
- .command('skill')
46
- .description('Manage JasperVault AI skills');
47
- skill
48
- .command('install')
49
- .description('Install JasperVault skill to AI platform (OpenClaw, Cursor, Claude Code)')
50
- .requiredOption('--ai <platform>', `Target platform: ${PLATFORMS.join(', ')}`)
51
- .option('--global', 'Install to user home directory (cursor/claude only)')
52
- .option('--force', 'Overwrite existing skill files without prompting')
53
- .action(async (opts) => {
54
- const platform = opts.ai;
55
- if (!PLATFORMS.includes(platform)) {
56
- process.stderr.write(`Error: Invalid platform "${platform}". Use one of: ${PLATFORMS.join(', ')}\n`);
57
- process.exit(1);
58
- }
59
- const globalFlag = opts.global ?? false;
60
- const force = opts.force ?? false;
61
- const targetPaths = getTargetPath(platform, globalFlag);
62
- process.stdout.write(BANNER + '\n\n');
63
- const results = [];
64
- for (const targetDir of targetPaths) {
65
- const skillPlatform = platform === 'all' ? getPlatformFromPath(targetDir) : platform;
66
- const platDisplay = getPlatformDisplayName(skillPlatform);
67
- try {
68
- const skillMdPath = path.join(targetDir, 'SKILL.md');
69
- const exists = await fs
70
- .access(skillMdPath)
71
- .then(() => true)
72
- .catch(() => false);
73
- if (exists && !force) {
74
- process.stderr.write(`Error: Skill already exists at ${targetDir}\n` +
75
- 'Use --force to overwrite.\n');
76
- process.exit(1);
77
- }
78
- const files = buildSkillContent(skillPlatform);
79
- let fileCount = 0;
80
- for (const [relPath, content] of Object.entries(files)) {
81
- const filePath = path.join(targetDir, relPath);
82
- await fs.mkdir(path.dirname(filePath), { recursive: true });
83
- await fs.writeFile(filePath, content, 'utf8');
84
- fileCount++;
85
- }
86
- // Make scripts executable
87
- const scriptsDir = path.join(targetDir, 'scripts');
88
- const scriptsDirExists = await fs
89
- .access(scriptsDir)
90
- .then(() => true)
91
- .catch(() => false);
92
- if (scriptsDirExists) {
93
- const scriptFiles = await fs.readdir(scriptsDir);
94
- for (const sf of scriptFiles) {
95
- if (sf.endsWith('.sh')) {
96
- await fs.chmod(path.join(scriptsDir, sf), 0o755);
97
- }
98
- }
99
- }
100
- results.push({ path: targetDir, platform: platDisplay, fileCount });
101
- }
102
- catch (err) {
103
- process.stderr.write(`Error installing to ${platDisplay}: ${err.message}\n`);
104
- process.exit(1);
105
- }
106
- }
107
- process.stdout.write('\n ✓ Skill installed successfully!\n\n' +
108
- results
109
- .map((r) => ` Platform: ${r.platform}\n Location: ${r.path}\n Files: ${r.fileCount} (SKILL.md + references/ + scripts/)`)
110
- .join('\n\n') +
111
- '\n\n Next steps:\n' +
112
- ' 1. First-time setup: jv vault setup --network jaspervault\n' +
113
- ' 2. (Optional) Override API URL for local debugging: export JV_API_URL=http://localhost:3000\n' +
114
- ' 3. Start using jv commands or let your AI agent call them\n');
115
- });
116
- }
117
- //# sourceMappingURL=skill.js.map