Skip to content

feat(api): -q for query parameters, one typed -f, and -F for a body file - #56

Merged
alukach merged 4 commits into
mainfrom
feat/api-query-flags
Oct 16, 2026
Merged

alukach merged 4 commits into
mainfrom
feat/api-query-flags

Conversation

@alukach

@alukach alukach commented Oct 16, 2026 •

Copy link
Copy Markdown
Contributor

source-coop api copied gh api's flags, so query parameters needed -X GET plus fields, and there were two field flags that differed only in typing. This PR splits query and body the way HTTPie does, and makes -F mean the same as in product:

Flag Does
-q, --query KEY=VALUE Adds a query parameter. Never changes the method.
-f, --field KEY=VALUE Sets a body field. The value is sent as JSON when it parses (5, true, ["a"]), as a string otherwise. '"5"' forces a string.
-F, --from-file PATH Reads the body from a JSON file (- for stdin). -f fields override its keys. Same precedence as product create/edit -F.
-X, --method Defaults to GET, or POST when there's a body. A GET with a body is refused.
source-coop api products/my-org -q limit=5
source-coop api products/my-org/new -X PATCH -F changes.json -f title=Renamed

The old --raw-field, typed -F and --input are removed rather than kept as hidden aliases, because api (#45) hasn't been in a release yet.

api --help now has examples, and the README's "Any API request" section is rewritten to match.

Help for agents: api --help now points to the OpenAPI spec (<api-url>/api/openapi) for paths and fields, and says the response is printed as JSON without --json and which exit code each failure gets. The top-level "For scripts and agents" section mentions api too. The spec is live on staging. Production will have it before this ships.

Testing

  • cargo fmt --check and cargo clippy --all-targets -- -D warnings: clean
  • cargo test and cargo test --features staging: 111 passed each
  • New tests: field typing (including arrays and "5" as a string), -f overriding -F's keys, -q keeping a GET, and a GET refusing a body.

🤖 Generated with Claude Code

…file

`source-coop api` took gh's flags: -f string fields, -F typed fields, and
--input for a body, with fields moving to the query string only under
-X GET. Now:

- -q/--query KEY=VALUE adds a query parameter and never changes the method.
- -f/--field KEY=VALUE sets a body field, sent as JSON when the value
  parses as JSON (arrays and objects too), as a string otherwise.
- -F/--from-file PATH (- for stdin) reads the body, like product's -F;
  -f fields override its keys.

The method is GET, or POST when there's a body. `api` hasn't been
released yet, so the old flags aren't kept.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@claude

claude Bot commented Oct 16, 2026 •

Copy link
Copy Markdown

Claude finished @alukach's task in 16s —— View job


✅ No blocking issues — safe to merge.

I read the diff for README.md, src/api_cmd.rs and src/main.rs. I did not build or run the tests.

  • The -q/-f/-F/-X semantics match the PR description.
  • -q doesn't collide with the global -v.
  • -q pairs are appended only when given, so there's no stray ?.
  • The GET-with-body refusal still runs, and -f over a non-object -F file errors cleanly.

Non-blocking note: src/api_cmd.rs:96 uses serde_json::from_str(&v).unwrap_or(String). An integer too large for u64, such as a 25-digit ID, parses as a lossy f64 and is sent silently altered. Leading-zero values like 00123 fall back to strings correctly. The '"…"' quoting escape hatch is documented, so this is acceptable. Enabling serde_json's arbitrary_precision would remove it if it ever matters.

Simplify (ponytail)

  • src/api_cmd.rs body(): the early if fields.is_empty() { return Ok(Some(body)) } is redundant. Without it, a non-object -F file with no -f would wrongly error, so keep it. Nothing to cut.
  • src/main.rs: FOR_SCRIPTS and API_HELP each do .replace("{api}", …). Using format! or a shared helper would avoid the placeholder string, but two call sites are fine.

💰 Estimated review cost: $0.13 · 0m16s · 6 turns

alukach and others added 3 commits October 16, 2026 15:11
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…rints

`api --help` now says where its paths and fields are listed (the
OpenAPI spec at /api/openapi), that the response is printed as JSON
without --json, and which exit code each failure gets. Its summary says
it's for what the other commands don't cover, and the top-level 'For
scripts and agents' section mentions api, since --json there doesn't
apply to it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Rendered from defaults::API_URL, so a staging build points at staging's
spec, and without the aside about other deployments.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@alukach
alukach merged commit b4a8274 into main Oct 16, 2026
10 checks passed
@alukach
alukach deleted the feat/api-query-flags branch October 16, 2026 22:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant