@weftlabs/cli 0.25.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.
package/README.md ADDED
@@ -0,0 +1,186 @@
1
+ # Weft CLI
2
+
3
+ Use Weft from a shell or an autonomous agent. Application code should use the
4
+ separate [`@weftlabs/sdk`](../typescript/README.md) package.
5
+
6
+ The CLI prints one versioned JSON object per command. It accepts credentials
7
+ through `--api-key-stdin`, `WEFT_API_KEY`, or its protected local credential
8
+ store; it rejects API keys in command arguments so they do not leak into shell
9
+ history or process listings.
10
+ `weft --help` and `weft <command> --help` return machine-readable JSON without
11
+ requiring authentication.
12
+
13
+ ## With a buyer API key
14
+
15
+ ```sh
16
+ export WEFT_API_KEY="your-buyer-api-key"
17
+ npx --package @weftlabs/cli weft me
18
+ npx --package @weftlabs/cli weft search "weather data API"
19
+ npx --package @weftlabs/cli weft fetch "https://merchant.example/data" \
20
+ --max-cost-usd 0.05
21
+ npx --package @weftlabs/cli weft --help
22
+ ```
23
+
24
+ ## Fetch results
25
+
26
+ One `weft fetch` call saves the exact response bytes before it prints its JSON
27
+ result. The default fetch output uses `schema_version: "2"`. The `meta` object
28
+ comes before the body and contains `saved_path` (an absolute path), `byte_count`,
29
+ `receipt_path`, and `idempotency_key`. The `data` object retains the SDK receipt
30
+ fields, including `status`, `headers`, `paidUsd`, `heldUsd`, `paymentStatus`, and
31
+ `artifactId`.
32
+
33
+ For text and JSON with valid UTF-8, `data.body` contains the complete original
34
+ text and `data.body_encoding` is `"utf-8"`. JSON is kept as text, so number
35
+ precision, duplicate keys, whitespace, and a UTF-8 BOM are preserved. The body
36
+ is escaped as a string in the outer JSON object. `data.media_type` identifies
37
+ its media type. Binary, compressed, invalid UTF-8, and other non-text responses
38
+ use `data.body_encoding: "file"` and omit `body`. Read `meta.saved_path` to use
39
+ those bytes. Reading the local file does not make a request or spend money.
40
+
41
+ Results are saved under `$HOME/.weft-results/result-<random>/` by default
42
+ (`USERPROFILE` or the operating system home is used when `HOME` is absent).
43
+ Set `WEFT_RESULTS_DIR` to use another storage directory. On Unix, that directory
44
+ must belong to your user and must not be writable by another user. The storage
45
+ path itself must not be a symlink. Each result directory has mode `0700`; its
46
+ `body` and `receipt.json` files have mode `0600`. The receipt file contains
47
+ metadata and the retry key, with no copy of the response body. Upstream filenames
48
+ do not determine the local path. Payloads are never made executable.
49
+
50
+ The CLI never deletes saved results. Remove individual result directories when
51
+ you no longer need them. A failed call can leave an empty directory or a partial
52
+ file. Do not use a file from a failed delivery as a complete result.
53
+
54
+ If the CLI cannot reserve a directory, it returns
55
+ `RESULT_STORAGE_UNAVAILABLE` before it sends the fetch. If storage fails after
56
+ fetch, it returns `RESULT_STORAGE_FAILED` on stderr with exit code `5`, the
57
+ receipt, and the same retry key. This is a local delivery failure; the receipt
58
+ still describes the payment state. Fix storage and retry the same URL, method,
59
+ and cost limit with `--idempotency-key` set to that key. The CLI does not retry
60
+ or purchase again automatically. Keep the same key after any uncertain result;
61
+ the server's existing retry rules and expiry still apply.
62
+
63
+ Invalid Base64 from the API returns `RESULT_DECODE_FAILED` with the receipt and
64
+ retry key; the CLI does not claim that damaged bytes were delivered. If stdout
65
+ fails, for example because a pipe closes, `RESULT_OUTPUT_FAILED` on stderr keeps
66
+ the receipt and saved paths. Read the saved file to recover without another
67
+ fetch. These delivery errors use exit code `5`.
68
+
69
+ Existing scripts can select `weft fetch ... --raw`. This retains the version 1
70
+ SDK envelope with `data.bodyBase64` and does not save local files. Other commands
71
+ retain their version 1 output. There is one fetch operation for every body size.
72
+ Hosts can still limit the text shown to a model; use the saved path when stdout
73
+ is clipped.
74
+
75
+ ## With no credential: agent bootstrap and human claim
76
+
77
+ An agent that has no Weft credential can start by itself. The flow needs the
78
+ human's email address and nothing else. There is no promotional balance, free
79
+ credit, or subsidy: paid fetch spends the human's own funded wallet, and the
80
+ wallet is funded by the human after the claim.
81
+
82
+ ```sh
83
+ npm install -g @weftlabs/cli
84
+
85
+ # 1. Ask the human for an email address. Never ask for a password.
86
+ # 2. Create the temporary bootstrap and send the claim email.
87
+ weft bootstrap --email "human@example.com" \
88
+ --agent-name "Research agent" \
89
+ --reason "Find weather data"
90
+
91
+ # 3. Search immediately, before the human does anything.
92
+ weft search "weather data API"
93
+
94
+ # 4. Tell the human to open the claim email and approve the agent.
95
+ # 5. Poll at the interval the bootstrap response returned.
96
+ weft auth status
97
+
98
+ # 6. After approval the CLI exchanges OAuth device tokens for the temporary
99
+ # credential, and normal authenticated commands work again.
100
+ weft me
101
+
102
+ # 7. Ask the human to fund the wallet before any paid fetch.
103
+ weft balance
104
+ ```
105
+
106
+ ### The `weft` Skill
107
+
108
+ Installing the package does not write to the machine. Install the `weft` Skill
109
+ (`SKILL.md` plus `rules/cli.md`, vendored from
110
+ [weftlabs/skills](https://github.com/weftlabs/skills)) with:
111
+
112
+ ```bash
113
+ weft skill install
114
+ ```
115
+
116
+ Any ordinary command installs it too, so an agent that runs `weft search`
117
+ before anyone reads this section still gets the Skill. Both paths are the same
118
+ idempotent operation, and running either again is safe.
119
+
120
+ Install one optional Weft workflow Skill for a specific agent host with:
121
+
122
+ ```bash
123
+ weft skill install weft-flights-search --agent codex
124
+ ```
125
+
126
+ Add `--global` to install it for all projects for that host. Named workflow
127
+ installs do not need Weft authentication. They delegate to the public Skills
128
+ CLI and keep its installation layout and host support.
129
+
130
+ Earlier versions installed the Skill from an `npm` package hook. That hook was
131
+ removed: `pnpm` and `bun` block dependency scripts by default, and `pnpm`
132
+ replays a cached package without re-running them, so the hook could be skipped
133
+ with no error and no Skill. Running it from the CLI removes that whole class of
134
+ silent failure, and it also picks up an agent host installed after the CLI —
135
+ the hook only ever ran once, at package install time.
136
+
137
+ The installer writes only for supported agent hosts already present on the
138
+ machine. It does not create configuration for absent hosts or replace a
139
+ different existing Skill. If an earlier version of this package installed the
140
+ retired `weft-cli` Skill, the installer removes that copy after the `weft`
141
+ Skill is in place; a hand-edited or user-owned `weft-cli` copy stays
142
+ untouched. Restart the agent host after the first install. Set
143
+ `WEFT_SKIP_SKILL_INSTALL=1` to opt out of both paths. Removing the package
144
+ leaves the Skill in place; remove the host's `skills/weft` directory if you
145
+ also want to remove the Skill.
146
+
147
+ `weft bootstrap` registers its OAuth client, creates the bootstrap, and writes
148
+ the temporary and device credentials to a local credential file created with
149
+ mode `0600`. After approval, the stored OAuth credential replaces the temporary
150
+ credential and refreshes before expiry. Normal output never prints a secret.
151
+
152
+ ### The temporary `wbt_` credential
153
+
154
+ - **Secret.** Never print, log, paste, commit, or email it. The CLI stores it
155
+ for you.
156
+ - **Temporary.** It expires 30 minutes after creation and has no refresh.
157
+ - **Search-only.** Its capabilities are `search`, `status`, and `cancel`.
158
+ Balance, paid fetch, wallet, transfer, withdrawal, seller, and organization
159
+ mutation surfaces all refuse it. A refusal there is the contract, not a bug.
160
+
161
+ The human's password is never part of this flow. The agent does not choose,
162
+ receive, or store it. An existing user completes fresh authentication on the
163
+ claim page; possession of the email link alone cannot attach an agent to an
164
+ existing account.
165
+
166
+ ### Bootstrap states
167
+
168
+ | Status | Meaning | Agent action |
169
+ | --- | --- | --- |
170
+ | `pending` | Waiting for the human. Search works. | Keep polling at the returned interval. |
171
+ | `claimed` | The human approved. Search continues until OAuth delivery succeeds. | Complete the OAuth device exchange. |
172
+ | `rejected` | The human declined. Terminal. | Stop; do not re-create the same bootstrap. |
173
+ | `expired` | The 30-minute window closed unclaimed. Terminal. | Offer to start a new bootstrap. |
174
+ | `consumed` | OAuth tokens were delivered. Terminal. | Use the OAuth credential. |
175
+
176
+ These are server lifecycle states. `weft auth status` handles `claimed` by
177
+ performing the OAuth exchange and emits `consumed` after successful delivery;
178
+ it does not emit an intermediate `claimed` result.
179
+
180
+ `rejected`, `expired`, and `consumed` are terminal. A `pending` or `claimed`
181
+ bootstrap can search; `claimed` also keeps status and OAuth token exchange.
182
+
183
+ See [`examples/agent-bootstrap.sh`](examples/agent-bootstrap.sh) for the same
184
+ sequence as a script, and
185
+ [`docs/operation-inventory.md`](../docs/operation-inventory.md) for commands,
186
+ output envelopes, and stable exit codes.
package/bin/weft.mjs ADDED
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env node
2
+
3
+ import { runCli } from "../dist/cli.js";
4
+
5
+ process.exitCode = await runCli(process.argv.slice(2));
package/dist/cli.d.ts ADDED
@@ -0,0 +1,26 @@
1
+ declare const EXIT_SUCCESS = 0;
2
+ declare const EXIT_USAGE = 2;
3
+ declare const EXIT_AUTH = 3;
4
+ declare const EXIT_API = 4;
5
+ declare const EXIT_INTERNAL = 5;
6
+ interface CliDependencies {
7
+ env?: Record<string, string | undefined>;
8
+ fetchApi?: typeof fetch;
9
+ readStdin?: () => Promise<string>;
10
+ writeOut?: (value: string) => void | Promise<void>;
11
+ writeErr?: (value: string) => void;
12
+ generateIdempotencyKey?: () => string;
13
+ runProcess?: ProcessRunner;
14
+ platform?: NodeJS.Platform;
15
+ nodeExecutable?: string;
16
+ npxCliPath?: string;
17
+ }
18
+ interface ProcessResult {
19
+ exitCode: number;
20
+ stdout: string;
21
+ stderr: string;
22
+ }
23
+ type ProcessRunner = (command: string, args: string[]) => Promise<ProcessResult>;
24
+ declare function runCli(args: string[], dependencies?: CliDependencies): Promise<number>;
25
+
26
+ export { type CliDependencies, EXIT_API, EXIT_AUTH, EXIT_INTERNAL, EXIT_SUCCESS, EXIT_USAGE, runCli };