Add C as a supported output language#105
Conversation
Follows the same overall pattern as python/javascript/typescript, but
C is genuinely different from every language added so far in two
ways, both addressed directly in the new partial
(prompts/partials/_language_c.md):
1. No stdlib HTTP or JSON. Unlike Go/PHP/Ruby (all fully
dependency-free via their own standard libraries), C has neither.
Uses libcurl for HTTP and vendors cJSON (a small, widely-used,
permissively-licensed single-file JSON library) for JSON, rather
than hand-rolling either - same reasoning as the Java PR's Gson
choice: a real, tested library beats ad-hoc parsing written from
scratch. libcurl itself is a system library a build step can't
fetch, so the partial calls out installing it via the platform's
package manager if the compiler can't find curl/curl.h.
2. Compiled, not run directly - the only such language here. Every
other language's {run_command} is (or now points at) a single
interpreter/build-tool invocation; C needs an explicit compile step
first. _get_run_command() chains `cc <source> <cJSON.c> -lcurl -o
<binary> && <binary>` as one command, using full paths throughout
for the same reason already fixed on the Go/Java/C#/PHP/Ruby PRs -
the agent's cwd is scripts_dir.parent.parent, not scripts_dir where
everything is actually saved.
base_engineer.py: added "c" to _OUTPUT_LANGUAGE_EXTENSIONS (.c) and
_get_language_name() ("C"). _get_auto_output_files() always lists the
vendored cJSON.c/cJSON.h (not conditional - C always needs them, no
stdlib fallback, matching Java's always-included pom.xml rather than
javascript/go's conditional dependency files).
cli.py: added C to the interactive `output_language` config picker.
Updated the three docstrings/comments listing the language set
(config.py, engineer.py, prompts/__init__.py) and README.md's output
language line. Tests mirror the existing per-language pattern in both
test_base_engineer.py and test_prompts.py.
Checked for the literal-brace str.format_map() bug caught in the Java
PR - no literal `{`/`}` anywhere in the new partial.
Full test suite passes (49/49, run 3x) except the same pre-existing
flaky test noted on the other language PRs. ruff check clean on every
file this touches (8 pre-existing lint errors elsewhere on main, none
in the touched lines).
| Choice(title="python", value="python"), | ||
| Choice(title="javascript", value="javascript"), | ||
| Choice(title="typescript", value="typescript"), | ||
| Choice(title="c", value="c"), |
There was a problem hiding this comment.
Selecting C creates api_client.c, but reverse-api-engineer run <run_id> still discovers only files with a .py suffix. A C-only run is therefore reported as having no scripts, so the normal run-by-ID workflow cannot execute the newly supported output.
Prompt To Fix With AI
This is a comment left during a code review.
Path: src/reverse_api/cli.py
Line: 1086
Comment:
**C Runs Are Not Discoverable**
Selecting C creates `api_client.c`, but `reverse-api-engineer run <run_id>` still discovers only files with a `.py` suffix. A C-only run is therefore reported as having no scripts, so the normal run-by-ID workflow cannot execute the newly supported output.
How can I resolve this? If you propose a fix, please make it concise.| @@ -0,0 +1,23 @@ | |||
| **Generate a C program** that replicates the API calls found in the traffic. The following are guidelines — use your judgment on what's appropriate for the specific API: | |||
|
|
|||
| - C has no HTTP client or JSON support in its standard library, unlike every other output language here — use `libcurl` for requests and vendor `cJSON` (a small, widely-used, permissively-licensed single-file JSON library — `cJSON.c`/`cJSON.h`) for JSON, rather than hand-rolling either from scratch | |||
There was a problem hiding this comment.
Vendored Dependency Is Not Supplied
The build command always requires cJSON.c, but the application does not provide a pinned cJSON source or a deterministic retrieval step. The agent must recreate or independently obtain the library, so a realistic generation can produce an incomplete or incompatible parser that fails to compile or behaves incorrectly at runtime.
Prompt To Fix With AI
This is a comment left during a code review.
Path: src/reverse_api/prompts/partials/_language_c.md
Line: 3
Comment:
**Vendored Dependency Is Not Supplied**
The build command always requires `cJSON.c`, but the application does not provide a pinned cJSON source or a deterministic retrieval step. The agent must recreate or independently obtain the library, so a realistic generation can produce an incomplete or incompatible parser that fails to compile or behaves incorrectly at runtime.
How can I resolve this? If you propose a fix, please make it concise.| **Generate a C program** that replicates the API calls found in the traffic. The following are guidelines — use your judgment on what's appropriate for the specific API: | ||
|
|
||
| - C has no HTTP client or JSON support in its standard library, unlike every other output language here — use `libcurl` for requests and vendor `cJSON` (a small, widely-used, permissively-licensed single-file JSON library — `cJSON.c`/`cJSON.h`) for JSON, rather than hand-rolling either from scratch | ||
| - `libcurl` itself is a system library, not something a build step can fetch — if compilation fails because `curl/curl.h` isn't found, install it with whatever package manager is available (e.g. `apt-get install -y libcurl4-openssl-dev`, `brew install curl`) before retrying |
There was a problem hiding this comment.
Compile Failure Modifies The Host
When the curl headers are missing, this instruction can make the automatically authorized agent install a system package. A privileged session is modified without a separate confirmation, while an unprivileged or unsupported environment exhausts generation retries and leaves the client unusable.
Prompt To Fix With AI
This is a comment left during a code review.
Path: src/reverse_api/prompts/partials/_language_c.md
Line: 4
Comment:
**Compile Failure Modifies The Host**
When the curl headers are missing, this instruction can make the automatically authorized agent install a system package. A privileged session is modified without a separate confirmation, while an unprivileged or unsupported environment exhausts generation retries and leaves the client unusable.
How can I resolve this? If you propose a fix, please make it concise.
This is likely a transient issue. You can re-trigger a run from the dashboard. |
There was a problem hiding this comment.
2 issues found across 10 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:478">
P2: The C run command always compiles `cJSON.c`, but this change set does not ship a pinned cJSON source artifact or deterministic retrieval path. That makes C execution depend on model-generated library code, which can be incomplete or incompatible and lead to compile/runtime failures; consider bundling a pinned vendored cJSON copy and compiling against that file.</violation>
</file>
<file name="src/reverse_api/cli.py">
<violation number="1" location="src/reverse_api/cli.py:1086">
P1: Adding `c` to the output-language picker exposes a path where `reverse-api-engineer run <run_id>` can’t execute C-only outputs if run discovery still filters to `.py` files. It would help to wire C into run-file discovery so the standard run-by-ID workflow works for the new language.</violation>
</file>
Reply with feedback, questions, or to request a fix.
Re-trigger cubic
| Choice(title="python", value="python"), | ||
| Choice(title="javascript", value="javascript"), | ||
| Choice(title="typescript", value="typescript"), | ||
| Choice(title="c", value="c"), |
There was a problem hiding this comment.
P1: Adding c to the output-language picker exposes a path where reverse-api-engineer run <run_id> can’t execute C-only outputs if run discovery still filters to .py files. It would help to wire C into run-file discovery so the standard run-by-ID workflow works for the new language.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At src/reverse_api/cli.py, line 1086:
<comment>Adding `c` to the output-language picker exposes a path where `reverse-api-engineer run <run_id>` can’t execute C-only outputs if run discovery still filters to `.py` files. It would help to wire C into run-file discovery so the standard run-by-ID workflow works for the new language.</comment>
<file context>
@@ -1083,6 +1083,7 @@ def handle_settings(mode_color=THEME_PRIMARY):
Choice(title="python", value="python"),
Choice(title="javascript", value="javascript"),
Choice(title="typescript", value="typescript"),
+ Choice(title="c", value="c"),
Choice(title="back", value="back"),
]
</file context>
| source = f"{self.scripts_dir}/{self._get_client_filename()}" | ||
| cjson = f"{self.scripts_dir}/cJSON.c" | ||
| binary = f"{self.scripts_dir}/api_client" | ||
| return f'cc "{source}" "{cjson}" -lcurl -o "{binary}" && "{binary}"' |
There was a problem hiding this comment.
P2: The C run command always compiles cJSON.c, but this change set does not ship a pinned cJSON source artifact or deterministic retrieval path. That makes C execution depend on model-generated library code, which can be incomplete or incompatible and lead to compile/runtime failures; consider bundling a pinned vendored cJSON copy and compiling against that file.
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 478:
<comment>The C run command always compiles `cJSON.c`, but this change set does not ship a pinned cJSON source artifact or deterministic retrieval path. That makes C execution depend on model-generated library code, which can be incomplete or incompatible and lead to compile/runtime failures; consider bundling a pinned vendored cJSON copy and compiling against that file.</comment>
<file context>
@@ -463,6 +465,17 @@ def _get_client_filename(self) -> str:
+ source = f"{self.scripts_dir}/{self._get_client_filename()}"
+ cjson = f"{self.scripts_dir}/cJSON.c"
+ binary = f"{self.scripts_dir}/api_client"
+ return f'cc "{source}" "{cjson}" -lcurl -o "{binary}" && "{binary}"'
return {
"python": "python api_client.py",
</file context>
Manually double-quoting each path (f'cc "{source}" "{cjson}" ... "{binary}"')
does not stop $()/backtick command substitution inside a POSIX shell
double-quoted string. Use shlex.quote() on all three paths (source,
vendored cJSON, compiled binary) instead, matching the fix already
applied to the Go/Java/C#/PHP/Ruby run commands after bot review
flagged the same issue on the PHP PR.
… host Both review bots independently flagged two real issues in the C partial: - The instruction to "vendor cJSON" gave no deterministic retrieval step, so the agent had to reconstruct the library from memory, risking an incomplete or subtly wrong JSON parser. Now fetches the exact pinned upstream source (cJSON v1.7.18) via curl instead. - Telling the agent to run apt-get/brew itself when libcurl headers are missing lets an auto-authorized session modify the host without a separate confirmation. Now it stops and reports a clear prerequisite error instead, leaving the actual install to the user. Also investigated a third finding from both bots: `reverse-api-engineer run <run_id>` only discovers `.py` files (utils.py's discover_scripts), so a C-only run can't be executed via that subcommand. Confirmed this predates this PR — JS/TS output has the same gap already, and the run subcommand's execution path (venv creation, pip install, ModuleNotFoundError- driven dependency retry) is Python-specific throughout, not just a filename filter. Fixing it means designing a per-language execution/dependency- retry story, which is a cross-cutting feature beyond a single-language addition. Not fixed here, same reasoning as the Java/C# PRs.
Same root cause cubic flagged on the C# and Ruby PRs: a relative --output-dir leaves scripts_dir relative to the original cwd, but once the agent's cwd moves to scripts_dir.parent.parent (see analyze_and_generate), embedding that same relative string re-interprets it from the new location and points all three paths (source, vendored cJSON, compiled binary) at the wrong, doubly-nested location. Resolve scripts_dir once before deriving all three paths, proactively applying the same fix here before it gets flagged.
Follows the same overall pattern as python/javascript/typescript, but C is genuinely different from every language added so far in two ways, both addressed directly in the new partial
(prompts/partials/_language_c.md):
No stdlib HTTP or JSON. Unlike Go/PHP/Ruby (all fully dependency-free via their own standard libraries), C has neither. Uses libcurl for HTTP and vendors cJSON (a small, widely-used, permissively-licensed single-file JSON library) for JSON, rather than hand-rolling either - same reasoning as the Java PR's Gson choice: a real, tested library beats ad-hoc parsing written from scratch. libcurl itself is a system library a build step can't fetch, so the partial calls out installing it via the platform's package manager if the compiler can't find curl/curl.h.
Compiled, not run directly - the only such language here. Every other language's {run_command} is (or now points at) a single interpreter/build-tool invocation; C needs an explicit compile step first. _get_run_command() chains
cc <source> <cJSON.c> -lcurl -o <binary> && <binary>as one command, using full paths throughout for the same reason already fixed on the Go/Java/C#/PHP/Ruby PRs - the agent's cwd is scripts_dir.parent.parent, not scripts_dir where everything is actually saved.base_engineer.py: added "c" to _OUTPUT_LANGUAGE_EXTENSIONS (.c) and _get_language_name() ("C"). _get_auto_output_files() always lists the vendored cJSON.c/cJSON.h (not conditional - C always needs them, no stdlib fallback, matching Java's always-included pom.xml rather than javascript/go's conditional dependency files).
cli.py: added C to the interactive
output_languageconfig picker. Updated the three docstrings/comments listing the language set (config.py, engineer.py, prompts/init.py) and README.md's output language line. Tests mirror the existing per-language pattern in both test_base_engineer.py and test_prompts.py.Checked for the literal-brace str.format_map() bug caught in the Java PR - no literal
{/}anywhere in the new partial.Full test suite passes (49/49, run 3x) except the same pre-existing flaky test noted on the other language PRs. ruff check clean on every file this touches (8 pre-existing lint errors elsewhere on main, none in the touched lines).
Summary by cubic
Adds C as a supported output language, generating a
libcurl+cJSONclient that compiles and runs in one step. Vendors pinnedcJSONand stops host installs; the compile-and-run command now resolves absolute paths and shell-quotes viashlex.New Features
CURLhandle, error checks, auth hardcoding + refresh, cookie engine).cc <source> <cJSON.c> -lcurl -o <binary> && <binary>.cJSON.c/cJSON.hwith the client and fetches pinnedcJSONv1.7.18 from upstream; ifcurl/curl.his missing, surface a clear prerequisite error (no auto-install). Updated CLI picker, docs, and tests.Migration
libcurlheaders to compile (install your platform’s package before running).Written for commit 971df93. Summary will update on new commits.
Greptile Summary
This PR adds C as a generated output language. The main changes are:
Confidence Score: 4/5
C output cannot use the normal run-by-ID workflow, and dependency setup can produce unusable output or modify the host.
src/reverse_api/cli.py and src/reverse_api/prompts/partials/_language_c.md
Security Review
The C prompt can direct an automatically authorized agent to install host-level packages after a compile failure. System dependency installation should remain an explicit user-controlled step.
Important Files Changed
Prompt To Fix All With AI
Reviews (1): Last reviewed commit: "Add C as a supported output language" | Re-trigger Greptile