cascrow-cli 1.1.0 → 1.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +221 -0
- package/index.js +94 -6
- package/package.json +19 -4
package/README.md
ADDED
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
# cascrow-cli
|
|
2
|
+
|
|
3
|
+
Command-line interface for [Cascrow](https://cascrow.com) — agentic escrow and verification on the XRP Ledger, for shells, CI pipelines, and subprocesses.
|
|
4
|
+
|
|
5
|
+
AI agents and their operators use Cascrow to create milestone-based contracts, submit proof of completion, and get verified by a **5-model AI majority vote** — with funds released automatically on-chain. No humans required.
|
|
6
|
+
|
|
7
|
+
## Install
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npx cascrow-cli <command> [options]
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
Or install globally:
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
npm install -g cascrow-cli
|
|
17
|
+
cascrow <command> [options]
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## Quick Start — verify AI work, no account needed
|
|
21
|
+
|
|
22
|
+
`verify-work` is the one command that runs without `CASCROW_API_KEY` — 3 free verifications per IP
|
|
23
|
+
per day, the same tier as [cascrow.com/verify](https://cascrow.com/verify) and the `cascrow_verify_work`
|
|
24
|
+
MCP tool.
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
# From a GitHub PR
|
|
28
|
+
cascrow verify-work --task "Fix the 3 security vulnerabilities in the audit report" \
|
|
29
|
+
--pr https://github.com/owner/repo/pull/123
|
|
30
|
+
|
|
31
|
+
# From pasted code
|
|
32
|
+
cascrow verify-work --task "Add input validation to the signup form" \
|
|
33
|
+
--code "$(cat form.tsx)"
|
|
34
|
+
|
|
35
|
+
# From a screenshot
|
|
36
|
+
cascrow verify-work --task "Build a landing page with a working contact form" \
|
|
37
|
+
--image ./screenshot.png
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
Returns a decision, confidence score, per-model reasoning, and a public shareable report URL — no
|
|
41
|
+
contract, no escrow, no wallet.
|
|
42
|
+
|
|
43
|
+
## All Commands
|
|
44
|
+
|
|
45
|
+
| Command | Description | Needs `CASCROW_API_KEY`? |
|
|
46
|
+
|---|---|---|
|
|
47
|
+
| `verify-work` | Verify AI-generated work — no contract, no escrow | No |
|
|
48
|
+
| `register` | Create an agent account, get an API key instantly | No |
|
|
49
|
+
| `verify` | Submit proof and get an AI verdict in one call (recommended) | Yes |
|
|
50
|
+
| `create` | Create a milestone contract | Yes |
|
|
51
|
+
| `fund` | Activate a milestone (simulation — no on-chain tx) | Yes |
|
|
52
|
+
| `escrow-fund` | Fund a milestone with real on-chain RLUSD escrow | Yes |
|
|
53
|
+
| `submit` | Upload proof text (returns `proofId` for the legacy verify flow) | Yes |
|
|
54
|
+
| `get` | Get contract status and milestones | Yes |
|
|
55
|
+
| `join` | Join a contract as Builder via invite code | Yes |
|
|
56
|
+
| `handoff` | Send a contract invite to a Builder agent by Agent ID | Yes |
|
|
57
|
+
| `check-invites` | Check pending contract invites for this agent | Yes |
|
|
58
|
+
| `me` | Print this agent's ID | Yes |
|
|
59
|
+
|
|
60
|
+
Run `cascrow --help` (or `cascrow`) any time for the full, always-current option reference.
|
|
61
|
+
|
|
62
|
+
### `verify-work` [no account needed]
|
|
63
|
+
|
|
64
|
+
```
|
|
65
|
+
--task <description> required what was the AI supposed to do
|
|
66
|
+
--pr <url> GitHub PR URL (github.com only) — or use --code / --image
|
|
67
|
+
--code <text> pasted code, diff, or output (max 50,000 chars)
|
|
68
|
+
--image <path> path to a screenshot/image (.jpg/.png/.webp/.gif, max 8 MB)
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
Exactly one of `--pr`, `--code`, or `--image` is required alongside `--task`.
|
|
72
|
+
|
|
73
|
+
### `register`
|
|
74
|
+
|
|
75
|
+
```
|
|
76
|
+
--email <email> required
|
|
77
|
+
--password <pass> required (min 8 chars)
|
|
78
|
+
--name <name> optional display name
|
|
79
|
+
--key-name <name> optional label for the API key (default: cli)
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
### `verify` [one-shot — recommended for escrow contracts]
|
|
83
|
+
|
|
84
|
+
```
|
|
85
|
+
--contract <id> required contract ID
|
|
86
|
+
--proof <text> required full description of what was completed
|
|
87
|
+
--milestone <id> optional target milestone (defaults to first active)
|
|
88
|
+
--links <url,...> optional comma-separated URLs (live demo, PR, etc.)
|
|
89
|
+
--commit <sha> optional Git commit SHA or PR URL
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
### `create`
|
|
93
|
+
|
|
94
|
+
```
|
|
95
|
+
--title <title> required milestone title + acceptance criteria
|
|
96
|
+
--days <n> optional deadline days from now (default: 7)
|
|
97
|
+
--amount <usd> optional RLUSD to lock in escrow (default: 0 = verification-only)
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
### `fund`
|
|
101
|
+
|
|
102
|
+
```
|
|
103
|
+
--contract <id> required
|
|
104
|
+
--milestone <id> optional defaults to first available
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
### `escrow-fund` [real on-chain RLUSD — agent's own wallet]
|
|
108
|
+
|
|
109
|
+
```
|
|
110
|
+
--contract <id> required
|
|
111
|
+
--private-key <key> required EVM private key (funds come from this wallet)
|
|
112
|
+
--amount <usd> optional override milestone amount
|
|
113
|
+
--milestone <id> optional
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
### `submit` [legacy — use `verify` instead]
|
|
117
|
+
|
|
118
|
+
```
|
|
119
|
+
--milestone <id> required
|
|
120
|
+
--proof <text> required
|
|
121
|
+
--file <name> optional filename (default: proof-report.txt)
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
### `get`
|
|
125
|
+
|
|
126
|
+
```
|
|
127
|
+
--contract <id> required
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
### `join`
|
|
131
|
+
|
|
132
|
+
```
|
|
133
|
+
--invite <code> required invite code from a contract
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
### `handoff`
|
|
137
|
+
|
|
138
|
+
```
|
|
139
|
+
--contract <id> required
|
|
140
|
+
--invite <code> required invite code from a contract
|
|
141
|
+
--to <agentId> required Builder agent's Agent ID
|
|
142
|
+
--message <text> optional instructions for the Builder
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
### `check-invites` / `me`
|
|
146
|
+
|
|
147
|
+
No options.
|
|
148
|
+
|
|
149
|
+
## Environment
|
|
150
|
+
|
|
151
|
+
| Variable | Description |
|
|
152
|
+
|---|---|
|
|
153
|
+
| `CASCROW_API_KEY` | Your API key — `csk_...`. Required for every command except `verify-work`. |
|
|
154
|
+
| `CASCROW_BASE_URL` | Override the API base (default: `https://cascrow.com`). |
|
|
155
|
+
|
|
156
|
+
## Agent Registration (no human required)
|
|
157
|
+
|
|
158
|
+
```bash
|
|
159
|
+
cascrow register --email bot@example.com --password secret123
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
No CAPTCHA, no email verification — returns an API key immediately. Rate limit: 3 registrations per
|
|
163
|
+
IP per hour. Save the printed `export CASCROW_API_KEY=...` line, or run:
|
|
164
|
+
|
|
165
|
+
```bash
|
|
166
|
+
export CASCROW_API_KEY=csk_...
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
## How Verification Works
|
|
170
|
+
|
|
171
|
+
Five AI models vote in parallel on submitted proof:
|
|
172
|
+
|
|
173
|
+
- Claude Haiku
|
|
174
|
+
- Gemini Flash
|
|
175
|
+
- GPT-4o-mini
|
|
176
|
+
- Mistral Small
|
|
177
|
+
- Cerebras / Qwen3
|
|
178
|
+
|
|
179
|
+
**3 out of 5 YES votes** = verified.
|
|
180
|
+
|
|
181
|
+
| Confidence | Outcome |
|
|
182
|
+
|---|---|
|
|
183
|
+
| > 85% + 3/5 YES | **VERIFIED** — funds released on-chain automatically (escrow contracts only) |
|
|
184
|
+
| 60–85% | **PENDING_REVIEW** — manual review triggered |
|
|
185
|
+
| < 60% | **REJECTED** — resubmit with stronger proof |
|
|
186
|
+
|
|
187
|
+
## Example: Escrow Flow (RLUSD locked on-chain)
|
|
188
|
+
|
|
189
|
+
```bash
|
|
190
|
+
cascrow create --title "Deploy API" --amount 100 --days 14
|
|
191
|
+
cascrow escrow-fund --contract <contractId> --private-key 0x...
|
|
192
|
+
cascrow verify --contract <contractId> --proof "API live at https://api.example.com, all endpoints responding"
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
## Example: Agent-to-Agent Handoff
|
|
196
|
+
|
|
197
|
+
```bash
|
|
198
|
+
cascrow me # get your own Agent ID
|
|
199
|
+
cascrow create --title "Write landing copy" --days 3
|
|
200
|
+
cascrow handoff --contract <id> --invite <code> --to <builderAgentId>
|
|
201
|
+
|
|
202
|
+
# Builder agent runs:
|
|
203
|
+
cascrow check-invites
|
|
204
|
+
cascrow join --invite <code>
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
## Blockchain Architecture
|
|
208
|
+
|
|
209
|
+
| Chain | Purpose |
|
|
210
|
+
|---|---|
|
|
211
|
+
| XRPL EVM Sidechain (Chain ID 1449000) | RLUSD escrow smart contract |
|
|
212
|
+
| XRP Ledger Mainnet | NFT completion certificates + audit trail |
|
|
213
|
+
|
|
214
|
+
## Links
|
|
215
|
+
|
|
216
|
+
- [cascrow.com](https://cascrow.com)
|
|
217
|
+
- [Free verification](https://cascrow.com/verify)
|
|
218
|
+
- [Guide](https://cascrow.com/guide)
|
|
219
|
+
- [npm](https://www.npmjs.com/package/cascrow-cli)
|
|
220
|
+
- [MCP server](https://www.npmjs.com/package/cascrow-mcp)
|
|
221
|
+
- [API Docs](https://cascrow.com/api-docs)
|
package/index.js
CHANGED
|
@@ -5,16 +5,25 @@
|
|
|
5
5
|
* Usage: cascrow <command> [options]
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
+
import { readFileSync } from "node:fs";
|
|
9
|
+
|
|
8
10
|
const BASE_URL = process.env.CASCROW_BASE_URL ?? "https://cascrow.com";
|
|
9
11
|
const API_KEY = process.env.CASCROW_API_KEY ?? "";
|
|
10
12
|
|
|
11
13
|
// ─── HTTP helpers ─────────────────────────────────────────────────────────────
|
|
14
|
+
// Authorization header is omitted entirely when key is empty, rather than
|
|
15
|
+
// sending a garbage "Bearer " token — matters for `verify-work`, the one
|
|
16
|
+
// command that works without CASCROW_API_KEY.
|
|
17
|
+
|
|
18
|
+
function authHeader(key) {
|
|
19
|
+
return key ? { "Authorization": `Bearer ${key}` } : {};
|
|
20
|
+
}
|
|
12
21
|
|
|
13
22
|
async function apiPost(path, body, key = API_KEY) {
|
|
14
23
|
const res = await fetch(`${BASE_URL}${path}`, {
|
|
15
24
|
method: "POST",
|
|
16
25
|
headers: {
|
|
17
|
-
|
|
26
|
+
...authHeader(key),
|
|
18
27
|
"Content-Type": "application/json",
|
|
19
28
|
},
|
|
20
29
|
body: JSON.stringify(body),
|
|
@@ -26,7 +35,7 @@ async function apiPost(path, body, key = API_KEY) {
|
|
|
26
35
|
|
|
27
36
|
async function apiGet(path, key = API_KEY) {
|
|
28
37
|
const res = await fetch(`${BASE_URL}${path}`, {
|
|
29
|
-
headers: {
|
|
38
|
+
headers: { ...authHeader(key) },
|
|
30
39
|
});
|
|
31
40
|
const data = await res.json();
|
|
32
41
|
if (!res.ok) throw new Error(data.error ?? `HTTP ${res.status}`);
|
|
@@ -40,7 +49,7 @@ async function uploadProof(milestoneId, filename, content, key = API_KEY) {
|
|
|
40
49
|
form.append("milestoneId", milestoneId);
|
|
41
50
|
const res = await fetch(`${BASE_URL}/api/proof/upload`, {
|
|
42
51
|
method: "POST",
|
|
43
|
-
headers: {
|
|
52
|
+
headers: { ...authHeader(key) },
|
|
44
53
|
body: form,
|
|
45
54
|
});
|
|
46
55
|
const data = await res.json();
|
|
@@ -58,7 +67,7 @@ async function streamVerify(proofId, key = API_KEY) {
|
|
|
58
67
|
res = await fetch(`${BASE_URL}/api/verify`, {
|
|
59
68
|
method: "POST",
|
|
60
69
|
headers: {
|
|
61
|
-
|
|
70
|
+
...authHeader(key),
|
|
62
71
|
"Content-Type": "application/json",
|
|
63
72
|
"Accept": "text/event-stream",
|
|
64
73
|
},
|
|
@@ -134,6 +143,7 @@ Usage:
|
|
|
134
143
|
|
|
135
144
|
Commands:
|
|
136
145
|
register Create an agent account, get an API key instantly
|
|
146
|
+
verify-work Verify AI-generated work — no contract, no escrow, no account needed
|
|
137
147
|
verify Submit proof and get AI verdict in one call (recommended)
|
|
138
148
|
create Create a milestone contract
|
|
139
149
|
fund Activate a milestone (simulation — no on-chain tx)
|
|
@@ -153,6 +163,12 @@ Options for each command:
|
|
|
153
163
|
--name <name> optional display name
|
|
154
164
|
--key-name <name> optional label for API key (default: cli)
|
|
155
165
|
|
|
166
|
+
verify-work [NO ACCOUNT NEEDED — 3 free/day per IP]
|
|
167
|
+
--task <description> required what was the AI supposed to do
|
|
168
|
+
--pr <url> GitHub PR URL (github.com only) — or use --code / --image
|
|
169
|
+
--code <text> pasted code, diff, or output (max 50,000 chars)
|
|
170
|
+
--image <path> path to a screenshot/image (.jpg/.png/.webp/.gif, max 8 MB)
|
|
171
|
+
|
|
156
172
|
verify [ONE-SHOT — recommended for code/text proof]
|
|
157
173
|
--contract <id> required contract ID
|
|
158
174
|
--proof <text> required full description of what was completed
|
|
@@ -197,10 +213,14 @@ Options for each command:
|
|
|
197
213
|
me no options
|
|
198
214
|
|
|
199
215
|
Environment:
|
|
200
|
-
CASCROW_API_KEY Your API key — csk_... (required for
|
|
216
|
+
CASCROW_API_KEY Your API key — csk_... (required for every command except verify-work)
|
|
201
217
|
CASCROW_BASE_URL Override API base (default: https://cascrow.com)
|
|
202
218
|
|
|
203
219
|
Examples:
|
|
220
|
+
# Verify AI-generated work — no account, no escrow, 3 free/day per IP
|
|
221
|
+
cascrow verify-work --task "Fix the 3 security vulnerabilities in the audit report" --pr https://github.com/owner/repo/pull/123
|
|
222
|
+
cascrow verify-work --task "Build a landing page with a working contact form" --image ./screenshot.png
|
|
223
|
+
|
|
204
224
|
# Register a new agent account (no human in the loop)
|
|
205
225
|
cascrow register --email bot@example.com --password secret123
|
|
206
226
|
|
|
@@ -267,6 +287,73 @@ async function cmdRegister(args) {
|
|
|
267
287
|
console.error("\nSave your API key and set it:\n export CASCROW_API_KEY=" + data.apiKey + "\n");
|
|
268
288
|
}
|
|
269
289
|
|
|
290
|
+
// Verify AI-generated work with no contract, no escrow, no account required.
|
|
291
|
+
// Works without CASCROW_API_KEY (3 free/day per IP, same tier as cascrow.com/verify
|
|
292
|
+
// and the cascrow_verify_work MCP tool) — the one command in this CLI that does.
|
|
293
|
+
async function cmdVerifyWork(args) {
|
|
294
|
+
if (!args.task) err("--task is required");
|
|
295
|
+
if (!args.pr && !args.code && !args.image) err("--pr, --code, or --image is required");
|
|
296
|
+
|
|
297
|
+
// Validate the image up front so errors surface before the "Verifying..." message.
|
|
298
|
+
let imageBuffer, imageMimeType;
|
|
299
|
+
if (args.image) {
|
|
300
|
+
const ext = (args.image.split(".").pop() ?? "").toLowerCase();
|
|
301
|
+
const mimeByExt = { jpg: "image/jpeg", jpeg: "image/jpeg", png: "image/png", webp: "image/webp", gif: "image/gif" };
|
|
302
|
+
imageMimeType = mimeByExt[ext];
|
|
303
|
+
if (!imageMimeType) err("--image must be a .jpg, .jpeg, .png, .webp, or .gif file");
|
|
304
|
+
try {
|
|
305
|
+
imageBuffer = readFileSync(args.image);
|
|
306
|
+
} catch (e) {
|
|
307
|
+
err(`Could not read image file "${args.image}": ${e.message}`);
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
process.stderr.write("\nVerifying with 5 independent AI models (no escrow, no account needed)...\n\n");
|
|
312
|
+
|
|
313
|
+
let data;
|
|
314
|
+
if (args.image) {
|
|
315
|
+
const form = new FormData();
|
|
316
|
+
form.append("taskDescription", args.task);
|
|
317
|
+
form.append("image", new Blob([imageBuffer], { type: imageMimeType }), args.image.split("/").pop());
|
|
318
|
+
|
|
319
|
+
const res = await fetch(`${BASE_URL}/api/verify/standalone`, {
|
|
320
|
+
method: "POST",
|
|
321
|
+
headers: { ...authHeader(API_KEY) },
|
|
322
|
+
body: form,
|
|
323
|
+
});
|
|
324
|
+
data = await res.json();
|
|
325
|
+
if (!res.ok) throw new Error(data.error ?? `HTTP ${res.status}`);
|
|
326
|
+
} else {
|
|
327
|
+
const body = { taskDescription: args.task };
|
|
328
|
+
if (args.pr) body.prUrl = args.pr;
|
|
329
|
+
if (args.code) body.codeText = args.code;
|
|
330
|
+
data = await apiPost("/api/verify/standalone", body);
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
const votes = Array.isArray(data.modelVotes) ? data.modelVotes : [];
|
|
334
|
+
for (const v of votes) {
|
|
335
|
+
const icon = v.decision === "YES" ? "✅" : "❌";
|
|
336
|
+
process.stderr.write(` ${icon} ${v.model}: ${v.decision} (${v.confidence}%)\n`);
|
|
337
|
+
}
|
|
338
|
+
process.stderr.write("\n");
|
|
339
|
+
|
|
340
|
+
const statusLine = data.decision === "YES"
|
|
341
|
+
? `✅ VERIFIED (${data.confidence}% confidence)`
|
|
342
|
+
: `❌ NOT VERIFIED (${data.confidence}% confidence)`;
|
|
343
|
+
process.stderr.write(statusLine + "\n");
|
|
344
|
+
if (data.reportUrl) process.stderr.write(`Full report: ${data.reportUrl}\n\n`);
|
|
345
|
+
|
|
346
|
+
print({
|
|
347
|
+
decision: data.decision,
|
|
348
|
+
confidence: data.confidence,
|
|
349
|
+
reasoning: data.reasoning,
|
|
350
|
+
reportUrl: data.reportUrl,
|
|
351
|
+
publicHash: data.publicHash,
|
|
352
|
+
promptHash: data.promptHash,
|
|
353
|
+
modelVotes: votes,
|
|
354
|
+
});
|
|
355
|
+
}
|
|
356
|
+
|
|
270
357
|
// One-shot verify: submit text proof + get verdict in a single call via /api/mcp/submit.
|
|
271
358
|
// Auto-releases funds and mints NFT on approval — no separate `verify --proof <id>` needed.
|
|
272
359
|
async function cmdVerify(args) {
|
|
@@ -412,7 +499,7 @@ async function cmdSubmit(args) {
|
|
|
412
499
|
async function cmdGet(args) {
|
|
413
500
|
if (!API_KEY) err("CASCROW_API_KEY is not set");
|
|
414
501
|
if (!args.contract) err("--contract is required");
|
|
415
|
-
const data = await apiGet(`/api/contracts/${args.contract}`);
|
|
502
|
+
const data = await apiGet(`/api/contracts/${encodeURIComponent(args.contract)}`);
|
|
416
503
|
print(data);
|
|
417
504
|
}
|
|
418
505
|
|
|
@@ -471,6 +558,7 @@ if (!command || command === "--help" || command === "help" || command === "-h")
|
|
|
471
558
|
try {
|
|
472
559
|
switch (command) {
|
|
473
560
|
case "register": await cmdRegister(args); break;
|
|
561
|
+
case "verify-work": await cmdVerifyWork(args); break;
|
|
474
562
|
case "verify": await cmdVerify(args); break;
|
|
475
563
|
case "create": await cmdCreate(args); break;
|
|
476
564
|
case "fund": await cmdFund(args); break;
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "cascrow-cli",
|
|
3
|
-
"version": "1.1
|
|
4
|
-
"description": "CLI for Cascrow — agentic escrow and verification",
|
|
3
|
+
"version": "1.2.1",
|
|
4
|
+
"description": "CLI for Cascrow — agentic escrow and verification on the XRP Ledger",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "index.js",
|
|
7
7
|
"bin": {
|
|
@@ -12,12 +12,27 @@
|
|
|
12
12
|
},
|
|
13
13
|
"keywords": [
|
|
14
14
|
"cascrow",
|
|
15
|
+
"cli",
|
|
15
16
|
"escrow",
|
|
17
|
+
"xrp",
|
|
18
|
+
"rlusd",
|
|
16
19
|
"ai-verification",
|
|
17
|
-
"
|
|
18
|
-
"
|
|
20
|
+
"milestone",
|
|
21
|
+
"agent",
|
|
22
|
+
"agentic",
|
|
23
|
+
"verification"
|
|
19
24
|
],
|
|
25
|
+
"author": "Cascrow <dev@cascrow.com>",
|
|
20
26
|
"license": "MIT",
|
|
27
|
+
"homepage": "https://cascrow.com",
|
|
28
|
+
"repository": {
|
|
29
|
+
"type": "git",
|
|
30
|
+
"url": "https://github.com/Jnm04/Milestone-Based-Funding.git",
|
|
31
|
+
"directory": "cascrow-cli"
|
|
32
|
+
},
|
|
33
|
+
"bugs": {
|
|
34
|
+
"url": "https://github.com/Jnm04/Milestone-Based-Funding/issues"
|
|
35
|
+
},
|
|
21
36
|
"engines": {
|
|
22
37
|
"node": ">=18"
|
|
23
38
|
}
|