@thenavidm/slipway 0.1.17 → 0.1.19

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/CHANGELOG.md CHANGED
@@ -2,6 +2,15 @@
2
2
 
3
3
  What changed in Slipway, newest first.
4
4
 
5
+ ## 0.1.19, 2026-10-05: what Lemon Squeezy needed
6
+
7
+ - **`which` answers with a command's help when one fits well ahead of the rest.** An agent asked `which` for the command and then read that command's `--help`, and each request carries the whole conversation. On Lemon Squeezy, `which cancel subscription` and then `cancel-subscription --help` cost Codex a median of 83,076 input tokens, where its 2.x CLI guessed the command's name and read its help in two requests for 61,541. When the first answer scores at least half again as much as the second, its help now follows the list, and three runs took 61,903, 61,913 and 61,908 in two requests. A close second gets the list alone: Gumroad's `which refund` fits refunding a sale and its refund policy alike, and the help shown would be a guess between them.
8
+
9
+ ## 0.1.18, 2026-10-05: what Wistia and Testimonial.to needed
10
+
11
+ - **A command's help never lists `--confirm` as the only required flag.** Wistia's import takes its URL as a flag or inside `--payload`, so no flag is required, and its help showed a Required section holding only `--confirm`. That reads as if nothing else were needed: every Codex run then read the command's schema as well, and finding the command and its flags cost a median of 105,140 input tokens, where Wistia's own 2.x CLI cost 86,365. Alone, `--confirm` now closes the options, where 2.x listed it, and the usage line still ends with it; two runs then took 83,069 and 82,817.
12
+ - **The general help leaves the flags to each command.** Each command's `--help` lists the flags it can use, `--agent` among them, so the general help's line of them repeated what an agent reads one step later, after carrying that line through every step in between. Without it the general help is 35 tokens shorter on every server: Testimonial.to's goes from 324 to 289.
13
+
5
14
  ## 0.1.17, 2026-10-05: what Google Photos needed
6
15
 
7
16
  - **`which` reads an argument by its own words, not through a synonym.** Since 0.1.14 a tool's argument names count toward finding it, and a synonym reached them too. Google Photos says "photos" means media, so `get_media_item`, which takes a `media_item_id`, drew level with the photo picker for "let me choose photos" and was listed first. An argument now counts only for the words it is made of, so the picker is first again. Buffer's "schedule a post to a channel" still reads `channelId` and `schedulingType`, and the first answer to every task measured on the other servers is unchanged.
package/README.md CHANGED
@@ -390,7 +390,7 @@ Override any operation's name or risk with `names` and `risk`, keep a subset wit
390
390
  | `<cli>` | Every command, grouped by toolset, writes marked |
391
391
  | `<cli> <command> [flags]` | Run one tool |
392
392
  | `<cli> <command> --help` | Its flags, choices, defaults, examples and risk |
393
- | `<cli> which <words>` | Find the command for a task, by what it does. An app's `synonyms` add the words its users type: `{ picture: ["image"] }` |
393
+ | `<cli> which <words>` | Find the command for a task, by what it does, with its help when one fits well ahead of the rest. An app's `synonyms` add the words its users type: `{ picture: ["image"] }` |
394
394
  | `<cli> schema <command>` | The JSON Schema an MCP client receives. `--output` for the result's |
395
395
  | `<cli> agent-context` | Commands, flags, risk, examples, exit codes and settings as JSON. `--brief` for just the commands, which ones write or need `--confirm`, and the exit codes |
396
396
  | `<cli> doctor` | Check the setup. `--network` also calls the service, which an app with `doctorNetwork` does every time |
package/dist/cli/help.js CHANGED
@@ -174,8 +174,17 @@ export function renderToolHelp(tool, bin, aliases = {}) {
174
174
  }
175
175
  lines.push(...after, ``);
176
176
  };
177
- describe(required, "Required", tool.requireConfirm ? line(" --confirm", "it runs only with this; --agent never adds it") : []);
178
- describe(optional, "Options");
177
+ const confirm = tool.requireConfirm ? line(" --confirm", "it runs only with this; --agent never adds it") : [];
178
+ // A Required section holding only --confirm reads as if nothing else were needed, when a write's body
179
+ // often comes as flags or as one --payload: Codex then read Wistia's schema to check, one more step.
180
+ // Alone, --confirm closes the options instead, and the usage line still ends with it.
181
+ if (required.length) {
182
+ describe(required, "Required", confirm);
183
+ describe(optional, "Options");
184
+ }
185
+ else {
186
+ describe(optional, "Options", confirm);
187
+ }
179
188
  if (tool.paginate) {
180
189
  lines.push(`Pages:`, ...line(" --all", "follow every page and print all items"), ...line(" --max-items <n>", "stop after this many items"), ``);
181
190
  }
@@ -208,13 +217,12 @@ export function renderGeneralHelp(app, bin) {
208
217
  const applies = switchesThatApply(app.allTools);
209
218
  const cache = app.allTools.some((tool) => tool.cache);
210
219
  const sync = app.allTools.some((tool) => tool.sync);
211
- const jobs = app.allTools.some((tool) => tool.job);
212
220
  // An agent often reads this first and pays for it again on every later step, so the
213
221
  // rarely needed commands share one line, an older name for a command is left out, and
214
222
  // Slipway's settings past the two safety switches are named on one line.
215
223
  const commands = [
216
224
  [app.bins.cli, "list the commands"],
217
- [`${bin} <command> --help`, "what one takes"],
225
+ [`${bin} <command> --help`, "what one takes, and its flags"],
218
226
  [`${bin} which <words>`, "find the command for a task"],
219
227
  [`${bin} doctor${app.definition.doctorNetwork ? "" : " [--network]"}`, "check the setup"],
220
228
  typeof app.definition.login === "object"
@@ -261,16 +269,6 @@ export function renderGeneralHelp(app, bin) {
261
269
  ...(app.allTools.some((tool) => tool.tags.length > 0) ? [[`${names.toolsets}=a,b`, "only these toolsets, or all"]] : []),
262
270
  ];
263
271
  const more = tuning.length + 4;
264
- // The list formats appear in the help of the commands that list; flags that cannot apply
265
- // here (jobs, the cache) are left out. agent-context lists every one.
266
- const flags = GLOBAL_FLAGS.map(([flag]) => flag).filter((flag) => flag !== "--agent" &&
267
- flag !== "--jsonl" &&
268
- flag !== "--csv / --tsv" &&
269
- flag !== "--quiet" &&
270
- flag !== "--out <file>" &&
271
- flag !== "--timeout <ms>" &&
272
- (flag !== "--wait" || jobs) &&
273
- (flag !== "--refresh" || cache));
274
272
  const commandRow = table(commands);
275
273
  const settingRow = table(settings);
276
274
  const lines = [
@@ -280,8 +278,8 @@ export function renderGeneralHelp(app, bin) {
280
278
  ...commands.map(commandRow),
281
279
  ` Also: schema <command>, agent-context (all of this as JSON), completion <shell>.`,
282
280
  ``,
283
- `Flags: ${flags.join(", ")}, and --agent: compact JSON, no prompts, never confirms a write.`,
284
- ``,
281
+ // No flags line: each command's own --help shows the flags it can use, --agent among them,
282
+ // and an agent reading this first carried those 44 tokens through every later step.
285
283
  `Settings:`,
286
284
  ...settings.map(settingRow),
287
285
  ` And ${more} more, for tuning and --http: agent-context describes each.`,
package/dist/cli/run.js CHANGED
@@ -257,7 +257,16 @@ async function runBuiltin(app, io, command, rest, globals) {
257
257
  }
258
258
  if (!matches.length)
259
259
  return print(io, `No command matches '${query}'. Run \`${app.bins.cli}\` to see them all.`);
260
- return print(io, matches.map(({ tool }) => toolLine(tool)).join("\n"));
260
+ const list = matches.map(({ tool }) => toolLine(tool)).join("\n");
261
+ // One command well ahead of the rest comes with its help, so finding a command and its flags is
262
+ // one step: on Lemon Squeezy, `which cancel subscription` and then `cancel-subscription --help`
263
+ // cost Codex a request its 2.x CLI had saved by guessing the name, and each request carries the
264
+ // whole conversation. A close second gets the list alone: Gumroad's `which refund` fits refunding
265
+ // a sale and its refund policy alike, and the help shown would be a guess between them.
266
+ const [first, second] = matches;
267
+ if (first && (!second || first.score >= second.score * 1.5))
268
+ return print(io, `${list}\n${renderToolHelp(first.tool, io.bin, app.definition.flagAliases)}`);
269
+ return print(io, list);
261
270
  }
262
271
  case "doctor":
263
272
  return runDoctor(app, io, { network: rest.includes("--network"), json: globals.format !== "auto" });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@thenavidm/slipway",
3
- "version": "0.1.17",
3
+ "version": "0.1.19",
4
4
  "description": "Slipway, the TypeScript framework for MCP servers and agent-native CLIs. One tool definition ships an MCP server and a CLI, with write safety, typed results and release checks built in.",
5
5
  "type": "module",
6
6
  "license": "Apache-2.0",