Skip to content

Add PowerShell (Pwsh 7+) as a supported output language - #118

Merged
kalil0321 merged 14 commits into
kalil0321:mainfrom
sultanberisa:add-powershell-support
Sep 20, 2026
Merged

kalil0321 merged 14 commits into
kalil0321:mainfrom
sultanberisa:add-powershell-support

Conversation

@sultanberisa

@sultanberisa sultanberisa commented Aug 3, 2026 •

Copy link
Copy Markdown
Contributor
  • Adds PowerShell as a first-class output language
  • Generates .psm1 module + Example.ps1 (no .psd1 manifest, matching Go's "only if needed" pattern)
  • Follows approved-verb / CmdletBinding / explicit Export-ModuleMember conventions
  • Full test coverage added, existing suite unaffected

Summary by cubic

Adds PowerShell (pwsh 7+) as a supported output language, generating an api_client.psm1 module and Example.ps1 runner. PowerShell clients run through the companion script, and script arguments now fail with guidance instead of being ignored.

  • Registers PowerShell across configuration, discovery, settings, prompts, docs, and generation, with approved verbs, typed parameters, explicit exports, native HTTP/JSON handling, and no .psd1 manifest.
  • Resolves and shell-quotes runner paths; rejects unrelated modules, missing examples, and unsupported script arguments; runtime tests cover success and failure.
  • CI verifies PowerShell 7+ and CLI startup on all supported OSes; an opt-in live_windows workflow runs real generation with preinstalled Chrome and the free opencode/big-pickle model for PowerShell and Python.
  • Adds an opt-in local browser-to-client acceptance harness that uses isolated configuration and verifies fresh API data after generation, retaining logs, the HAR, and generated client sources (decoded across Windows text encodings) in its report.

Written for commit 6c6a0f5. Summary will update on new commits.

Review in cubic

Greptile Summary

This change adds PowerShell as a selectable generated-client language, including .psm1 modules and an Example.ps1 companion runner.

PowerShell run arguments are passed to Example.ps1, but the generated-wrapper instructions do not require parameters or forwarding into the exported module function. Users invoking a generated client with arguments therefore cannot rely on those values reaching the API call.

T-Rex validation blocked

  • Missing tool: pwsh (PowerShell 7+) is not installed. The command-construction path was exercised and confirmed to append caller values after Example.ps1, but actual PowerShell parameter binding and forwarding could not be executed. The focused existing test selection was also unavailable because the Python environment lacked the click package.

Confidence Score: 4/5

@cubic-dev-ai cubic-dev-ai Bot left a comment •

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1 issue found across 13 files

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="src/reverse_api/base_engineer.py">

<violation number="1" location="src/reverse_api/base_engineer.py:633">
P1: PowerShell runs on Linux/macOS can fail before exercising the generated client because this new command executes the example whose module import uses a Windows-style `\` path. Generating the import path with `Join-Path $PSScriptRoot '{client_filename}'` (or a platform-neutral separator) would keep the advertised cross-platform `pwsh` support working.</violation>
</file>

Reply with feedback, questions, or to request a fix.

Re-trigger cubic

# re-interpreted against the agent's cwd (scripts_dir.parent.
# parent) instead of the original cwd it was relative to,
# pointing -File at the wrong, doubly-nested location.
example = self._quote_path(str(self.scripts_dir.resolve() / "Example.ps1"))

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1: PowerShell runs on Linux/macOS can fail before exercising the generated client because this new command executes the example whose module import uses a Windows-style \ path. Generating the import path with Join-Path $PSScriptRoot '{client_filename}' (or a platform-neutral separator) would keep the advertised cross-platform pwsh support working.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At src/reverse_api/base_engineer.py, line 633:

<comment>PowerShell runs on Linux/macOS can fail before exercising the generated client because this new command executes the example whose module import uses a Windows-style `\` path. Generating the import path with `Join-Path $PSScriptRoot '{client_filename}'` (or a platform-neutral separator) would keep the advertised cross-platform `pwsh` support working.</comment>

<file context>
@@ -613,6 +614,24 @@ def _get_run_command(self) -> str:
+            # re-interpreted against the agent's cwd (scripts_dir.parent.
+            # parent) instead of the original cwd it was relative to,
+            # pointing -File at the wrong, doubly-nested location.
+            example = self._quote_path(str(self.scripts_dir.resolve() / "Example.ps1"))
+            return f"pwsh -NoProfile -File {example}"
         return {
</file context>

Comment thread src/reverse_api/utils.py Resolved
Comment thread src/reverse_api/utils.py Resolved
Comment thread src/reverse_api/utils.py Outdated
# (Example.ps1) that Imports the module and calls its exported
# functions, not the script argument itself.
example = d / "Example.ps1"
return [["pwsh", "-NoProfile", "-File", str(example), *script_args]], "pwsh"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Example wrapper drops run arguments

When a user supplies arguments to run, this branch passes them to Example.ps1, but the generation prompt does not require that wrapper to declare parameters or forward values to the module functions. As a result, generated PowerShell clients cannot reliably consume caller-provided run arguments: PowerShell may reject the unbound values, or the wrapper will never pass them to the exported API call.

Prompt To Fix With AI
This is a comment left during a code review.
Path: src/reverse_api/utils.py
Line: 839

Comment:
**Example wrapper drops run arguments**

When a user supplies arguments to `run`, this branch passes them to `Example.ps1`, but the generation prompt does not require that wrapper to declare parameters or forward values to the module functions. As a result, generated PowerShell clients cannot reliably consume caller-provided run arguments: PowerShell may reject the unbound values, or the wrapper will never pass them to the exported API call.

---

For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.

@giordano-lucas giordano-lucas changed the title Add PowerShell (Pwsh 7+) as a supported output language [NOT-744] Add PowerShell (Pwsh 7+) as a supported output language Aug 5, 2026
@kalil0321 kalil0321 changed the title [NOT-744] Add PowerShell (Pwsh 7+) as a supported output language Add PowerShell (Pwsh 7+) as a supported output language Sep 20, 2026

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

8 issues found across 15 files

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="src/reverse_api/utils.py">

<violation number="1" location="src/reverse_api/utils.py:837">
P3: `build_script_commands` now rejects every PowerShell argument, but its public docstring still promises argument passthrough and documents only Java as an exception. Update the docstring to identify PowerShell as an intentional exception.</violation>
</file>

<file name="website/content/docs/index.mdx">

<violation number="1" location="website/content/docs/index.mdx:8">
P3: The rewritten paragraph line is 89 characters, while the rest of this file wraps prose at ~77 characters, breaking the wrapping convention. Rewrap so the sentence still flows across lines.</violation>

<violation number="2" location="website/content/docs/index.mdx:8">
P3: The user-facing docs now advertise PowerShell but never state the prerequisite that README.md documents on the same feature: PowerShell requires `pwsh` 7+ (PowerShell Core, not Windows PowerShell 5.1), and its runner relies on the generated companion `Example.ps1` with no argument overrides. A site reader who picks PowerShell without pwsh installed gets scripts they cannot run. Add the requirement next to the language list (mirroring the README note you added).</violation>

<violation number="3" location="website/content/docs/index.mdx:123">
P3: This page now states that PowerShell is selectable in `/settings` and counts ten languages, but `website/content/docs/configuration/output.mdx` still says "Generated API clients can be emitted in nine languages:" and lists no PowerShell option. The shipped site will contradict itself. Update output.mdx (count and language list) in the same PR.</violation>
</file>

<file name="tests/test_base_engineer.py">

<violation number="1" location="tests/test_base_engineer.py:472">
P3: The new `test_get_run_command_powershell_quotes_metacharacters` only token-round-trips the command, but the existing `test_run_command_preserves_posix_shell_quoting` explicitly documents that "Token round-trips alone cannot detect unsafe double-quoted substitutions." The PowerShell run command embeds a shell-quoted path (`Example.ps1` via `_quote_path`, same as Java/C#/PHP/Ruby/C), so it should be added to that parametrize list (`["java", "csharp", "php", "ruby", "c"]`) to get the same `shlex.quote(path) in command` substitution-safety regression coverage the other quoted-path languages get.</violation>
</file>

<file name=".github/workflows/ci.yml">

<violation number="1" location=".github/workflows/ci.yml:73">
P3: The new `--version` and `--help` smoke steps duplicate coverage that `tests/test_cli_no_httpx.py` already provides in a stronger form: that test parametrizes both flags and runs them in a subprocess with a fresh interpreter (`python -I`) plus legacy-HTTP-import blocking on every matrix entry. The only coverage the smoke steps add is the `uv`-generated console-script wrapper, which is low-risk. Consider dropping these two steps, or keeping a single one (`--version`) if you want an entry-point smoke test, to avoid paying ~9 extra `uv run` invocations per PR for near-zero added coverage.</violation>
</file>

<file name="src/reverse_api/prompts/partials/_language_powershell.md">

<violation number="1" location="src/reverse_api/prompts/partials/_language_powershell.md:24">
P2: The Testing section's only verification is running `{run_command}` (pwsh -File Example.ps1) and relying on its exit code, but nothing states what a passing run is and nothing checks the module's full export surface. Example.ps1 exercises only the fixed demonstration arguments, so a function that is missing from the `Export-ModuleMember` list, or is broken but not called by the example, still passes all 5 attempts and ships. Instruct the agent to verify that every exported function is present and callable after the run, and to define the pass criterion (exit 0 and JSON-only output).</violation>

<violation number="2" location="src/reverse_api/prompts/partials/_language_powershell.md:34">
P3: Nothing in the prompt forbids top-level side effects in the `.psm1`. Because the run-command verification checks only exit status (the module guidelines already demand rethrow rather than swallow, and test_powershell_failure_is_nonzero confirms nonzero exit is the failure signal), an agent that places demo/request code at module import time would still 'pass' while streaming unwanted network calls and output on every `Import-Module`. That output joins Example.ps1's success stream and breaks the JSON-on-stdout contract the runtime checks and users rely on. Add an explicit rule that importing the module must be side-effect free: no requests and no output at import time; all work happens only inside exported functions.</violation>
</file>

Reply with feedback, questions, or to request a fix.

Re-trigger cubic

Comment on lines +24 to +25
- Run: `{run_command}`
- You have up to 5 attempts to fix issues

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: The Testing section's only verification is running {run_command} (pwsh -File Example.ps1) and relying on its exit code, but nothing states what a passing run is and nothing checks the module's full export surface. Example.ps1 exercises only the fixed demonstration arguments, so a function that is missing from the Export-ModuleMember list, or is broken but not called by the example, still passes all 5 attempts and ships. Instruct the agent to verify that every exported function is present and callable after the run, and to define the pass criterion (exit 0 and JSON-only output).

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At src/reverse_api/prompts/partials/_language_powershell.md, line 24:

<comment>The Testing section's only verification is running `{run_command}` (pwsh -File Example.ps1) and relying on its exit code, but nothing states what a passing run is and nothing checks the module's full export surface. Example.ps1 exercises only the fixed demonstration arguments, so a function that is missing from the `Export-ModuleMember` list, or is broken but not called by the example, still passes all 5 attempts and ships. Instruct the agent to verify that every exported function is present and callable after the run, and to define the pass criterion (exit 0 and JSON-only output).</comment>

<file context>
@@ -0,0 +1,39 @@
+- Handle auth refresh so the module doesn't go stale: if you see a token refresh endpoint, OAuth refresh flow, or login endpoint in the traffic, implement automatic re-authentication when a request returns 401/403. If cookies have expiry, re-fetch them before they expire
+
+**Testing:**
+- Run: `{run_command}`
+- You have up to 5 attempts to fix issues
+
</file context>
Suggested change
- Run: `{run_command}`
- You have up to 5 attempts to fix issues
- Run: `{run_command}`; a passing attempt means Example.ps1 exits 0 and prints only its JSON output (no stray text)
- Confirm the export surface after running: `pwsh -NoProfile -Command "Import-Module (Join-Path '{scripts_dir}' '{client_filename}') -Force; Get-Command -Module (Get-Item '{scripts_dir}/{client_filename}').BaseName | Select-Object -ExpandProperty Name"` and verify every function a documented endpoint needs is exported and callable
- You have up to 5 attempts to fix issues

Comment thread src/reverse_api/utils.py
# The generated example is bound to api_client.psm1, not an arbitrary module.
if script.name != "api_client.psm1":
raise ValueError("PowerShell execution only supports api_client.psm1 with its companion Example.ps1")
if script_args:

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P3: build_script_commands now rejects every PowerShell argument, but its public docstring still promises argument passthrough and documents only Java as an exception. Update the docstring to identify PowerShell as an intentional exception.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At src/reverse_api/utils.py, line 837:

<comment>`build_script_commands` now rejects every PowerShell argument, but its public docstring still promises argument passthrough and documents only Java as an exception. Update the docstring to identify PowerShell as an intentional exception.</comment>

<file context>
@@ -829,6 +830,19 @@ def build_script_commands(script: Path, script_args: tuple[str, ...] = ()) -> tu
+        # The generated example is bound to api_client.psm1, not an arbitrary module.
+        if script.name != "api_client.psm1":
+            raise ValueError("PowerShell execution only supports api_client.psm1 with its companion Example.ps1")
+        if script_args:
+            raise ValueError(
+                "script arguments are not supported for PowerShell clients: "
</file context>

**Reverse API Engineer** is a CLI tool that captures browser traffic and uses
your configured AI SDK to generate production-ready API clients in Python,
JavaScript, TypeScript, Go, Java, C#, PHP, Ruby, or C. No more manual reverse
JavaScript, TypeScript, Go, Java, C#, PHP, Ruby, C, or PowerShell. No more manual reverse

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P3: The rewritten paragraph line is 89 characters, while the rest of this file wraps prose at ~77 characters, breaking the wrapping convention. Rewrap so the sentence still flows across lines.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At website/content/docs/index.mdx, line 8:

<comment>The rewritten paragraph line is 89 characters, while the rest of this file wraps prose at ~77 characters, breaking the wrapping convention. Rewrap so the sentence still flows across lines.</comment>

<file context>
@@ -5,7 +5,7 @@ description: Capture browser traffic and turn it into a production-ready typed A
 **Reverse API Engineer** is a CLI tool that captures browser traffic and uses
 your configured AI SDK to generate production-ready API clients in Python,
-JavaScript, TypeScript, Go, Java, C#, PHP, Ruby, or C. No more manual reverse
+JavaScript, TypeScript, Go, Java, C#, PHP, Ruby, C, or PowerShell. No more manual reverse
 engineering: browse, capture, and get clean API code.
 
</file context>
Suggested change
JavaScript, TypeScript, Go, Java, C#, PHP, Ruby, C, or PowerShell. No more manual reverse
JavaScript, TypeScript, Go, Java, C#, PHP, Ruby, C, or
PowerShell. No more manual reverse

in `/settings`. Same capture, different code. Useful when you want the same API
client surfaced to multiple stacks.
Switch between Python, JavaScript, TypeScript, Go, Java, C#, PHP, Ruby, C, and
PowerShell in `/settings`. Same capture, different code. Useful when you want

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P3: This page now states that PowerShell is selectable in /settings and counts ten languages, but website/content/docs/configuration/output.mdx still says "Generated API clients can be emitted in nine languages:" and lists no PowerShell option. The shipped site will contradict itself. Update output.mdx (count and language list) in the same PR.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At website/content/docs/index.mdx, line 123:

<comment>This page now states that PowerShell is selectable in `/settings` and counts ten languages, but `website/content/docs/configuration/output.mdx` still says "Generated API clients can be emitted in nine languages:" and lists no PowerShell option. The shipped site will contradict itself. Update output.mdx (count and language list) in the same PR.</comment>

<file context>
@@ -117,11 +117,11 @@ Generated scripts include type hints, structured error handling, and inline
-in `/settings`. Same capture, different code. Useful when you want the same API
-client surfaced to multiple stacks.
+Switch between Python, JavaScript, TypeScript, Go, Java, C#, PHP, Ruby, C, and
+PowerShell in `/settings`. Same capture, different code. Useful when you want
+the same API client surfaced to multiple stacks.
 
</file context>

expansion — what the naive f'"{path}"' approach got wrong."""
eng = self._make_engineer(tmp_path, output_language="powershell")
eng.scripts_dir = tmp_path / "weird$(marker) dir"
tokens = _split_run_command(eng._get_run_command())

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P3: The new test_get_run_command_powershell_quotes_metacharacters only token-round-trips the command, but the existing test_run_command_preserves_posix_shell_quoting explicitly documents that "Token round-trips alone cannot detect unsafe double-quoted substitutions." The PowerShell run command embeds a shell-quoted path (Example.ps1 via _quote_path, same as Java/C#/PHP/Ruby/C), so it should be added to that parametrize list (["java", "csharp", "php", "ruby", "c"]) to get the same shlex.quote(path) in command substitution-safety regression coverage the other quoted-path languages get.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At tests/test_base_engineer.py, line 472:

<comment>The new `test_get_run_command_powershell_quotes_metacharacters` only token-round-trips the command, but the existing `test_run_command_preserves_posix_shell_quoting` explicitly documents that "Token round-trips alone cannot detect unsafe double-quoted substitutions." The PowerShell run command embeds a shell-quoted path (`Example.ps1` via `_quote_path`, same as Java/C#/PHP/Ruby/C), so it should be added to that parametrize list (`["java", "csharp", "php", "ruby", "c"]`) to get the same `shlex.quote(path) in command` substitution-safety regression coverage the other quoted-path languages get.</comment>

<file context>
@@ -445,6 +454,38 @@ def test_get_run_command_c_resolves_relative_output_dir(self, tmp_path):
+        expansion — what the naive f'"{path}"' approach got wrong."""
+        eng = self._make_engineer(tmp_path, output_language="powershell")
+        eng.scripts_dir = tmp_path / "weird$(marker) dir"
+        tokens = _split_run_command(eng._get_run_command())
+        assert tokens[:3] == ["pwsh", "-NoProfile", "-File"]
+        assert tokens[3] == str(eng.scripts_dir.resolve() / "Example.ps1")
</file context>

Comment thread .github/workflows/ci.yml
shell: pwsh
run: |
if ($PSVersionTable.PSVersion.Major -lt 7) { throw 'PowerShell 7+ required' }
- run: uv run reverse-api-engineer --version

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P3: The new --version and --help smoke steps duplicate coverage that tests/test_cli_no_httpx.py already provides in a stronger form: that test parametrizes both flags and runs them in a subprocess with a fresh interpreter (python -I) plus legacy-HTTP-import blocking on every matrix entry. The only coverage the smoke steps add is the uv-generated console-script wrapper, which is low-risk. Consider dropping these two steps, or keeping a single one (--version) if you want an entry-point smoke test, to avoid paying ~9 extra uv run invocations per PR for near-zero added coverage.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At .github/workflows/ci.yml, line 73:

<comment>The new `--version` and `--help` smoke steps duplicate coverage that `tests/test_cli_no_httpx.py` already provides in a stronger form: that test parametrizes both flags and runs them in a subprocess with a fresh interpreter (`python -I`) plus legacy-HTTP-import blocking on every matrix entry. The only coverage the smoke steps add is the `uv`-generated console-script wrapper, which is low-risk. Consider dropping these two steps, or keeping a single one (`--version`) if you want an entry-point smoke test, to avoid paying ~9 extra `uv run` invocations per PR for near-zero added coverage.</comment>

<file context>
@@ -63,4 +66,10 @@ jobs:
+        shell: pwsh
+        run: |
+          if ($PSVersionTable.PSVersion.Major -lt 7) { throw 'PowerShell 7+ required' }
+      - run: uv run reverse-api-engineer --version
+      - run: uv run reverse-api-engineer --help
       - run: uv run pytest -q
</file context>

Save the example script to: `{scripts_dir}/Example.ps1`, which does:
```powershell
$ErrorActionPreference = 'Stop'
Import-Module (Join-Path $PSScriptRoot '{client_filename}') -Force -ErrorAction Stop

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P3: Nothing in the prompt forbids top-level side effects in the .psm1. Because the run-command verification checks only exit status (the module guidelines already demand rethrow rather than swallow, and test_powershell_failure_is_nonzero confirms nonzero exit is the failure signal), an agent that places demo/request code at module import time would still 'pass' while streaming unwanted network calls and output on every Import-Module. That output joins Example.ps1's success stream and breaks the JSON-on-stdout contract the runtime checks and users rely on. Add an explicit rule that importing the module must be side-effect free: no requests and no output at import time; all work happens only inside exported functions.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At src/reverse_api/prompts/partials/_language_powershell.md, line 34:

<comment>Nothing in the prompt forbids top-level side effects in the `.psm1`. Because the run-command verification checks only exit status (the module guidelines already demand rethrow rather than swallow, and test_powershell_failure_is_nonzero confirms nonzero exit is the failure signal), an agent that places demo/request code at module import time would still 'pass' while streaming unwanted network calls and output on every `Import-Module`. That output joins Example.ps1's success stream and breaks the JSON-on-stdout contract the runtime checks and users rely on. Add an explicit rule that importing the module must be side-effect free: no requests and no output at import time; all work happens only inside exported functions.</comment>

<file context>
@@ -0,0 +1,39 @@
+Save the example script to: `{scripts_dir}/Example.ps1`, which does:
+```powershell
+$ErrorActionPreference = 'Stop'
+Import-Module (Join-Path $PSScriptRoot '{client_filename}') -Force -ErrorAction Stop
+# Invoke the exported function(s), using valid demonstration arguments.
+# Serialize returned data with ConvertTo-Json -Depth 20.
</file context>

**Reverse API Engineer** is a CLI tool that captures browser traffic and uses
your configured AI SDK to generate production-ready API clients in Python,
JavaScript, TypeScript, Go, Java, C#, PHP, Ruby, or C. No more manual reverse
JavaScript, TypeScript, Go, Java, C#, PHP, Ruby, C, or PowerShell. No more manual reverse

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P3: The user-facing docs now advertise PowerShell but never state the prerequisite that README.md documents on the same feature: PowerShell requires pwsh 7+ (PowerShell Core, not Windows PowerShell 5.1), and its runner relies on the generated companion Example.ps1 with no argument overrides. A site reader who picks PowerShell without pwsh installed gets scripts they cannot run. Add the requirement next to the language list (mirroring the README note you added).

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At website/content/docs/index.mdx, line 8:

<comment>The user-facing docs now advertise PowerShell but never state the prerequisite that README.md documents on the same feature: PowerShell requires `pwsh` 7+ (PowerShell Core, not Windows PowerShell 5.1), and its runner relies on the generated companion `Example.ps1` with no argument overrides. A site reader who picks PowerShell without pwsh installed gets scripts they cannot run. Add the requirement next to the language list (mirroring the README note you added).</comment>

<file context>
@@ -5,7 +5,7 @@ description: Capture browser traffic and turn it into a production-ready typed A
 **Reverse API Engineer** is a CLI tool that captures browser traffic and uses
 your configured AI SDK to generate production-ready API clients in Python,
-JavaScript, TypeScript, Go, Java, C#, PHP, Ruby, or C. No more manual reverse
+JavaScript, TypeScript, Go, Java, C#, PHP, Ruby, C, or PowerShell. No more manual reverse
 engineering: browse, capture, and get clean API code.
 
</file context>

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

4 issues found and verified against the latest diff

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="tests/test_engineer.py">

<violation number="1" location="tests/test_engineer.py:974">
P3: The powershell entry duplicates the exact language tuple already hardcoded in test_base_engineer.py:504. Adding a future language requires editing both lists, and forgetting one silently drops coverage while both tests' docstrings claim they cover every partials/_language_*.md. Extract one shared constant (e.g. ALL_OUTPUT_LANGUAGES in tests/conftest.py) and import it in both tests.</violation>
</file>

<file name="tests/test_base_engineer.py">

<violation number="1" location="tests/test_base_engineer.py:472">
P3: test_get_run_command_powershell_quotes_metacharacters only token-round-trips the quoted path, which cannot detect a regression to naive double-quoting (shlex.split yields the same token for both quote styles) — the exact failure mode this suite's own test_run_command_preserves_posix_shell_quoting docstring warns about. Powershell was not added to that test's parametrize list, leaving the new metacharacter-quoting path without the guard that java/csharp/php/ruby/c all get. Add "powershell" to the parametrize list of test_run_command_preserves_posix_shell_quoting so unsafe double-quoted substitution in the pwsh command is actually detected.</violation>
</file>

<file name="website/content/docs/index.mdx">

<violation number="1" location="website/content/docs/index.mdx:120">
P2: The PR updates this page to "ten languages" and adds PowerShell, but the canonical `/docs/configuration/output` page was not updated: `website/content/docs/configuration/output.mdx` still says "Generated API clients can be emitted in nine languages:" and its bullet list omits `powershell`. A reader clicking the linked "Output language & sync" doc gets a count and list that contradict every other page changed in this PR, and never learns that `powershell` is a valid `output_language` value. Update output.mdx in the same PR (rename the heading to "ten languages", add `**powershell** (Pwsh 7+)` to the list, and note `pwsh -NoProfile -File Example.ps1` in the toolchain paragraph alongside the other runtimes).</violation>
</file>

<file name="src/reverse_api/prompts/partials/_language_powershell.md">

<violation number="1" location="src/reverse_api/prompts/partials/_language_powershell.md:17">
P2: These instructions store live session credentials (cookies, bearer tokens, API keys) as plaintext inside the generated `api_client.psm1` under `~/.reverse-api/runs/scripts/<run_id>/`, so anyone with filesystem access to the run directory (or to the synced local copy when `--sync` is on) obtains working credentials for the captured user session. This follows the PR's stated zero-configuration requirement, but the exposure is implicit — consider requiring the generated README.md to state that the module contains real credentials and should not be committed or shared.</violation>
</file>

Reply with feedback, questions, or to request a fix.

Re-trigger cubic

your codebase and called from production.

### Output in nine languages
### Output in ten languages

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: The PR updates this page to "ten languages" and adds PowerShell, but the canonical /docs/configuration/output page was not updated: website/content/docs/configuration/output.mdx still says "Generated API clients can be emitted in nine languages:" and its bullet list omits powershell. A reader clicking the linked "Output language & sync" doc gets a count and list that contradict every other page changed in this PR, and never learns that powershell is a valid output_language value. Update output.mdx in the same PR (rename the heading to "ten languages", add **powershell** (Pwsh 7+) to the list, and note pwsh -NoProfile -File Example.ps1 in the toolchain paragraph alongside the other runtimes).

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At website/content/docs/index.mdx, line 120:

<comment>The PR updates this page to "ten languages" and adds PowerShell, but the canonical `/docs/configuration/output` page was not updated: `website/content/docs/configuration/output.mdx` still says "Generated API clients can be emitted in nine languages:" and its bullet list omits `powershell`. A reader clicking the linked "Output language & sync" doc gets a count and list that contradict every other page changed in this PR, and never learns that `powershell` is a valid `output_language` value. Update output.mdx in the same PR (rename the heading to "ten languages", add `**powershell** (Pwsh 7+)` to the list, and note `pwsh -NoProfile -File Example.ps1` in the toolchain paragraph alongside the other runtimes).</comment>

<file context>
@@ -117,11 +117,11 @@ Generated scripts include type hints, structured error handling, and inline
 your codebase and called from production.
 
-### Output in nine languages
+### Output in ten languages
 
-Switch between Python, JavaScript, TypeScript, Go, Java, C#, PHP, Ruby, and C
</file context>

- Create a separate exported function for each distinct API endpoint

**Authentication & credentials:**
- Hardcode all cookies, tokens, session IDs, and auth headers found in the traffic directly in the module

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: These instructions store live session credentials (cookies, bearer tokens, API keys) as plaintext inside the generated api_client.psm1 under ~/.reverse-api/runs/scripts/<run_id>/, so anyone with filesystem access to the run directory (or to the synced local copy when --sync is on) obtains working credentials for the captured user session. This follows the PR's stated zero-configuration requirement, but the exposure is implicit — consider requiring the generated README.md to state that the module contains real credentials and should not be committed or shared.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At src/reverse_api/prompts/partials/_language_powershell.md, line 17:

<comment>These instructions store live session credentials (cookies, bearer tokens, API keys) as plaintext inside the generated `api_client.psm1` under `~/.reverse-api/runs/scripts/<run_id>/`, so anyone with filesystem access to the run directory (or to the synced local copy when `--sync` is on) obtains working credentials for the captured user session. This follows the PR's stated zero-configuration requirement, but the exposure is implicit — consider requiring the generated README.md to state that the module contains real credentials and should not be committed or shared.</comment>

<file context>
@@ -0,0 +1,39 @@
+- Create a separate exported function for each distinct API endpoint
+
+**Authentication & credentials:**
+- Hardcode all cookies, tokens, session IDs, and auth headers found in the traffic directly in the module
+- The user should be able to run the example immediately with zero configuration — no env vars, no config files, no manual setup
+- If the API uses cookies, populate a `WebRequestSession` with them and reuse it across calls
</file context>

Comment thread tests/test_engineer.py
from reverse_api.base_engineer import REPORT_CLIENT_VERIFIED_INSTRUCTION

for language in ("python", "javascript", "typescript", "go", "java", "csharp", "php", "ruby", "c"):
for language in ("python", "javascript", "typescript", "go", "java", "csharp", "php", "ruby", "c", "powershell"):

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P3: The powershell entry duplicates the exact language tuple already hardcoded in test_base_engineer.py:504. Adding a future language requires editing both lists, and forgetting one silently drops coverage while both tests' docstrings claim they cover every partials/language*.md. Extract one shared constant (e.g. ALL_OUTPUT_LANGUAGES in tests/conftest.py) and import it in both tests.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At tests/test_engineer.py, line 974:

<comment>The powershell entry duplicates the exact language tuple already hardcoded in test_base_engineer.py:504. Adding a future language requires editing both lists, and forgetting one silently drops coverage while both tests' docstrings claim they cover every partials/_language_*.md. Extract one shared constant (e.g. ALL_OUTPUT_LANGUAGES in tests/conftest.py) and import it in both tests.</comment>

<file context>
@@ -971,7 +971,7 @@ def test_get_codegen_instructions_appends_for_every_language(self, tmp_path):
         from reverse_api.base_engineer import REPORT_CLIENT_VERIFIED_INSTRUCTION
 
-        for language in ("python", "javascript", "typescript", "go", "java", "csharp", "php", "ruby", "c"):
+        for language in ("python", "javascript", "typescript", "go", "java", "csharp", "php", "ruby", "c", "powershell"):
             eng = self._make_engineer(tmp_path, output_language=language, output_mode="client")
             assert eng._get_codegen_instructions().endswith(REPORT_CLIENT_VERIFIED_INSTRUCTION), language
</file context>

expansion — what the naive f'"{path}"' approach got wrong."""
eng = self._make_engineer(tmp_path, output_language="powershell")
eng.scripts_dir = tmp_path / "weird$(marker) dir"
tokens = _split_run_command(eng._get_run_command())

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P3: test_get_run_command_powershell_quotes_metacharacters only token-round-trips the quoted path, which cannot detect a regression to naive double-quoting (shlex.split yields the same token for both quote styles) — the exact failure mode this suite's own test_run_command_preserves_posix_shell_quoting docstring warns about. Powershell was not added to that test's parametrize list, leaving the new metacharacter-quoting path without the guard that java/csharp/php/ruby/c all get. Add "powershell" to the parametrize list of test_run_command_preserves_posix_shell_quoting so unsafe double-quoted substitution in the pwsh command is actually detected.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At tests/test_base_engineer.py, line 472:

<comment>test_get_run_command_powershell_quotes_metacharacters only token-round-trips the quoted path, which cannot detect a regression to naive double-quoting (shlex.split yields the same token for both quote styles) — the exact failure mode this suite's own test_run_command_preserves_posix_shell_quoting docstring warns about. Powershell was not added to that test's parametrize list, leaving the new metacharacter-quoting path without the guard that java/csharp/php/ruby/c all get. Add "powershell" to the parametrize list of test_run_command_preserves_posix_shell_quoting so unsafe double-quoted substitution in the pwsh command is actually detected.</comment>

<file context>
@@ -445,6 +454,38 @@ def test_get_run_command_c_resolves_relative_output_dir(self, tmp_path):
+        expansion — what the naive f'"{path}"' approach got wrong."""
+        eng = self._make_engineer(tmp_path, output_language="powershell")
+        eng.scripts_dir = tmp_path / "weird$(marker) dir"
+        tokens = _split_run_command(eng._get_run_command())
+        assert tokens[:3] == ["pwsh", "-NoProfile", "-File"]
+        assert tokens[3] == str(eng.scripts_dir.resolve() / "Example.ps1")
</file context>

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1 issue found across 3 files (changes from recent commits).

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="scripts/validation/generation_e2e.py">

<violation number="1" location="scripts/validation/generation_e2e.py:127">
P2: Between probing this port and starting OpenCode, the probe socket is released and the port is unreserved. Keep the reservation through server startup or retry with a newly allocated port when startup cannot bind, otherwise concurrent local processes can make this acceptance check flaky.</violation>
</file>

Tip: Review your code locally with the cubic CLI to iterate faster.

Re-trigger cubic

utils.get_app_dir = lambda: config_dir
with socket.socket() as probe:
probe.bind(("127.0.0.1", 0))
base_url = f"http://127.0.0.1:{probe.getsockname()[1]}"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: Between probing this port and starting OpenCode, the probe socket is released and the port is unreserved. Keep the reservation through server startup or retry with a newly allocated port when startup cannot bind, otherwise concurrent local processes can make this acceptance check flaky.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At scripts/validation/generation_e2e.py, line 127:

<comment>Between probing this port and starting OpenCode, the probe socket is released and the port is unreserved. Keep the reservation through server startup or retry with a newly allocated port when startup cannot bind, otherwise concurrent local processes can make this acceptance check flaky.</comment>

<file context>
@@ -0,0 +1,206 @@
+    utils.get_app_dir = lambda: config_dir
+    with socket.socket() as probe:
+        probe.bind(("127.0.0.1", 0))
+        base_url = f"http://127.0.0.1:{probe.getsockname()[1]}"
+    os.environ.update({
+        "RAE_E2E_CONFIG_DIR": str(config_dir),
</file context>

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1 issue found across 2 files (changes from recent commits).

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name=".github/workflows/ci.yml">

<violation number="1" location=".github/workflows/ci.yml:87">
P2: When a live Windows dispatch runs on `main` while ordinary CI is active, the shared concurrency group cancels the ordinary run, but this dispatch does not run its required checks. Use a separate concurrency group for live validation so it cannot cancel normal CI.</violation>
</file>

Tip: Review your code locally with the cubic CLI to iterate faster.

Re-trigger cubic

Comment thread .github/workflows/ci.yml

live-windows:
name: Live Windows generation (Chrome already installed)
if: github.event_name == 'workflow_dispatch' && inputs.live_windows

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: When a live Windows dispatch runs on main while ordinary CI is active, the shared concurrency group cancels the ordinary run, but this dispatch does not run its required checks. Use a separate concurrency group for live validation so it cannot cancel normal CI.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At .github/workflows/ci.yml, line 87:

<comment>When a live Windows dispatch runs on `main` while ordinary CI is active, the shared concurrency group cancels the ordinary run, but this dispatch does not run its required checks. Use a separate concurrency group for live validation so it cannot cancel normal CI.</comment>

<file context>
@@ -73,3 +81,53 @@ jobs:
+
+  live-windows:
+    name: Live Windows generation (Chrome already installed)
+    if: github.event_name == 'workflow_dispatch' && inputs.live_windows
+    runs-on: windows-latest
+    timeout-minutes: 12
</file context>

@cubic-dev-ai cubic-dev-ai Bot left a comment •

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All reported issues were addressed across 1 file (changes from recent commits).

Tip: Review your code locally with the cubic CLI to iterate faster.

Re-trigger cubic

Comment thread scripts/validation/generation_e2e.py Resolved
Comment thread scripts/validation/generation_e2e.py Resolved
@kalil0321
kalil0321 merged commit 7a0e9ef into kalil0321:main Sep 20, 2026
13 of 14 checks passed
@kalil0321

Copy link
Copy Markdown
Owner

Hey, thanks a lot for your PR!

@kalil0321

Copy link
Copy Markdown
Owner

and sorry for the delay before merging it

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.

2 participants