After self-driving the CLI as if I were an agent (probing --help, error paths, JSON contracts, exit codes), here are the frictions I'd want fixed so another agent can reliably drive reverse-api-engineer for reverse engineering.
Status update (post #60, #63 merge): PR #60 (browser-use/stagehand removal) and PR #63 (tag system removal) have landed on main. PR #61 (the agent-friendly MVP this issue tracks follow-ups for) has been rebased onto the new main and is mergeable. Item #7 below ("tag system undocumented") is now obsolete since the tag system was removed entirely.
PR #61 lands the MVP (agent --json, --no-interactive, normalized payload, list/show JSON edge cases, run --no-interactive / --auto-install, README + --help epilogs). This issue tracks what's missing to make the rest of the surface coherently scriptable.
🔴 Blockers for scripted use
1. reverse-api-engineer (no subcommand) hangs without a TTY
Running the binary with no subcommand drops into the prompt_toolkit REPL. Without a TTY (e.g. a wrapper that forgets the subcommand, or a CI invocation), it blocks on stdin forever. I had to kill it with a timeout.
Fix idea: detect not sys.stdin.isatty() at REPL entry → print --help and sys.exit(2).
2. engineer has no --json or --no-interactive
The natural agent pipeline is:
agent --json → run_id → engineer <run_id> → run <run_id>
…but step 3 has no scripted output, so re-engineering an existing run breaks the contract. (Note: manual is intentionally interactive by design — capture requires a human in the loop — so it's lower priority than engineer.)
The cleanup PR #63 did add engineer --prompt and engineer --fresh, but not the JSON contract.
Fix idea: apply the same --json / --no-interactive / normalized payload to engineer. Same shape as agent --json (with a richer script_path / output_path field for the new client / docs file).
🟡 Medium-severity frictions
3. Top-level --help doesn't advertise scripted features
reverse-api-engineer --help doesn't mention that subcommands accept --json or --no-interactive. An agent inspecting only the top-level help misses the contract entirely.
Fix idea: one-line footer in the root command description, e.g. "Most subcommands accept --json and --no-interactive for scripted use; see <cmd> --help."
4. usage field is opaque / not stable across SDKs
README documents usage as {input_tokens, output_tokens, total_cost}, but the actual content is whatever the engineer SDK emits (Claude vs OpenCode vs Copilot may differ). An agent that reads usage.total_cost can break when the user switches SDK.
Fix idea: normalize usage in _build_agent_payload to a stable subset (e.g. always emit input_tokens, output_tokens, total_cost_usd, cache_read_tokens, cache_write_tokens); leave SDK-specific fields under usage.raw if needed.
5. No --dry-run / --validate on agent
A wrapper can't sanity-check its inputs (URL reachable? prompt non-empty? required API keys present? agent_provider deps installed?) without actually launching a browser. Useful when developing/testing a new wrapper.
Fix idea: agent --dry-run --json resolves the config, validates env (API keys, node version for chrome-mcp, etc.), and emits a manifest of "this is what would run" with status "ok" or "error" — without spinning anything up.
6. Errors leak Python reprs; no machine-readable error_kind
Today an OSError surfaces as "[Errno 13] Permission denied: '/nonexistent'" in the JSON payload's error field. An agent that wants to react differently to config issues vs transient runtime failures vs user input errors has to pattern-match on prose.
Fix idea: add an error_kind field with a small enum (misuse, config_invalid, permission_denied, network, engine_failure, interrupted, unknown) alongside the human-readable error.
🟢 Nice-to-have
7. Tag system undocumented in --help — RESOLVED
Removed in #63. The tag system no longer exists; capabilities live as first-class CLI flags / subcommands. No action needed here.
8. run has no --json
For the MVP it's reasonable that run streams the script's stdout. But for chaining multiple runs, a run --json that wraps {run_id, script, exit_code, stdout, stderr, duration_ms} would help.
9. No CLI surface for the JSON schema version
The payload includes schema_version: 1, good. But there's no way to query "what schema version does this binary support?" without running the command. A wrapper that wants to gate on schema version has to invoke a real run.
Fix idea: reverse-api-engineer --json-schema-version (or surface it in --version).
Suggested order of attack
| # |
Item |
Impact |
Effort |
Status |
| 1 |
TTY-detect at REPL entry → exit 2 |
High |
~5 lines |
open |
| 2 |
--json + --no-interactive on engineer |
High |
~30 lines |
open |
| 3 |
Normalize usage to a stable subset |
Med |
~15 lines |
open |
| 4 |
error_kind enum in error payloads |
Med |
~10 lines |
open |
| 5 |
agent --dry-run |
Med |
~50 lines |
open |
| 6 |
Top-level --help mentions --json / --no-interactive |
Low |
~3 lines |
open |
| 7 |
Document tags in agent epilog |
— |
— |
resolved by #63 |
| 8 |
run --json (wrapped) |
Low |
~25 lines |
open |
| 9 |
--json-schema-version |
Low |
~5 lines |
open |
Each item is independent and shippable on its own.
After self-driving the CLI as if I were an agent (probing
--help, error paths, JSON contracts, exit codes), here are the frictions I'd want fixed so another agent can reliably drivereverse-api-engineerfor reverse engineering.PR #61 lands the MVP (
agent --json,--no-interactive, normalized payload,list/showJSON edge cases,run --no-interactive/--auto-install, README +--helpepilogs). This issue tracks what's missing to make the rest of the surface coherently scriptable.🔴 Blockers for scripted use
1.
reverse-api-engineer(no subcommand) hangs without a TTYRunning the binary with no subcommand drops into the
prompt_toolkitREPL. Without a TTY (e.g. a wrapper that forgets the subcommand, or a CI invocation), it blocks on stdin forever. I had to kill it with a timeout.Fix idea: detect
not sys.stdin.isatty()at REPL entry → print--helpandsys.exit(2).2.
engineerhas no--jsonor--no-interactiveThe natural agent pipeline is:
…but step 3 has no scripted output, so re-engineering an existing run breaks the contract. (Note:
manualis intentionally interactive by design — capture requires a human in the loop — so it's lower priority thanengineer.)The cleanup PR #63 did add
engineer --promptandengineer --fresh, but not the JSON contract.Fix idea: apply the same
--json/--no-interactive/ normalized payload toengineer. Same shape asagent --json(with a richerscript_path/output_pathfield for the new client / docs file).🟡 Medium-severity frictions
3. Top-level
--helpdoesn't advertise scripted featuresreverse-api-engineer --helpdoesn't mention that subcommands accept--jsonor--no-interactive. An agent inspecting only the top-level help misses the contract entirely.Fix idea: one-line footer in the root command description, e.g. "Most subcommands accept
--jsonand--no-interactivefor scripted use; see<cmd> --help."4.
usagefield is opaque / not stable across SDKsREADME documents
usageas{input_tokens, output_tokens, total_cost}, but the actual content is whatever the engineer SDK emits (Claude vs OpenCode vs Copilot may differ). An agent that readsusage.total_costcan break when the user switches SDK.Fix idea: normalize
usagein_build_agent_payloadto a stable subset (e.g. always emitinput_tokens,output_tokens,total_cost_usd,cache_read_tokens,cache_write_tokens); leave SDK-specific fields underusage.rawif needed.5. No
--dry-run/--validateonagentA wrapper can't sanity-check its inputs (URL reachable? prompt non-empty? required API keys present? agent_provider deps installed?) without actually launching a browser. Useful when developing/testing a new wrapper.
Fix idea:
agent --dry-run --jsonresolves the config, validates env (API keys, node version for chrome-mcp, etc.), and emits a manifest of "this is what would run" with status"ok"or"error"— without spinning anything up.6. Errors leak Python reprs; no machine-readable
error_kindToday an
OSErrorsurfaces as"[Errno 13] Permission denied: '/nonexistent'"in the JSON payload'serrorfield. An agent that wants to react differently to config issues vs transient runtime failures vs user input errors has to pattern-match on prose.Fix idea: add an
error_kindfield with a small enum (misuse,config_invalid,permission_denied,network,engine_failure,interrupted,unknown) alongside the human-readableerror.🟢 Nice-to-have
7.
Tag system undocumented in— RESOLVED--helpRemoved in #63. The tag system no longer exists; capabilities live as first-class CLI flags / subcommands. No action needed here.
8.
runhas no--jsonFor the MVP it's reasonable that
runstreams the script's stdout. But for chaining multiple runs, arun --jsonthat wraps{run_id, script, exit_code, stdout, stderr, duration_ms}would help.9. No CLI surface for the JSON schema version
The payload includes
schema_version: 1, good. But there's no way to query "what schema version does this binary support?" without running the command. A wrapper that wants to gate on schema version has to invoke a real run.Fix idea:
reverse-api-engineer --json-schema-version(or surface it in--version).Suggested order of attack
--json+--no-interactiveonengineerusageto a stable subseterror_kindenum in error payloadsagent --dry-run--helpmentions--json/--no-interactiveDocument tags inagentepilogrun --json(wrapped)--json-schema-versionEach item is independent and shippable on its own.