Feat/agent eval showcase#106
Conversation
Add the complete jcode Agent autonomous-execution evaluation suite: - Round-table discussion artifact (roundtable/) - ACP headless harness (harness/) with isolated-HOME orchestration (suite/) - 65-run prior evaluation report (report/report.html, analysis/) - 6 new frontend test cases and deterministic oracles (suite/testcases.json, verify.py) - 18-run frontend batch results: 17/18 passed (94%), clean end_turns - Self-contained showcase landing page (showcase/index.html) displaying the prior report metrics, the 6 discovered defects, and the 6 generated frontend projects as live iframes with per-project model/runtime/token metadata. All generated frontend projects render offline with no external CDN assets. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> 🤖 Generated with [Claude Code](https://claude.com/claude-code)
…frames Redesign the agent-eval landing experience after open-design.ai: - Add agent-eval/site/ with shared CSS/JS, nav, and six pages: index, showcase, report, findings, roundtable, docs. - Apply warm cream background (#f6f3ec), serif display type, pill buttons, white cards, numbered sections, and generous whitespace. - Convert existing docs (README, report, findings, roundtable) into the new site pages while preserving the original report in an iframe. - Embed the 6 generated frontend projects in the showcase as full-width 780px-tall iframes (responsive down to 460px on mobile) so they are actually usable, not thumbnails. - Mirror generated project files under site/projects/ for self-contained browsing, and redirect the old showcase/index.html to the new site. - Update README to point users at site/index.html as the entry point. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> 🤖 Generated with [Claude Code](https://claude.com/claude-code)
- Add 津ICP备13004281号-4 to the footer of every site page. - Fix a malformed li tag in site/roundtable.html. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> 🤖 Generated with [Claude Code](https://claude.com/claude-code)
- Rewrite site/index.html as a product marketing page for jcode (AI coding companion) - Add hero terminal mockup, feature grid, desktop download section, CLI section - Link to GitHub and actual docs/docs/ (copied from repo docs/_site with /jcode/ → /docs/ rewrite) - Rebuild showcase.html with per-demo Maximize modal and Open-in-new-window links - Remove eval/report/test pages from the site nav (report, findings, roundtable, docs.html) - Add Chinese ICP footer to all pages Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> 🤖 Generated with [Claude Code](https://claude.com/claude-code)
📝 WalkthroughWalkthroughThis PR adds a new ChangesEvaluation Harness Core
Documentation Site, Showcase, and Frontend Demo Projects
Estimated code review effort: 3 (Moderate) | ~25 minutes Sequence Diagram(s)sequenceDiagram
participant Orchestrator as orchestrate.py
participant Home as isolated HOME
participant Harness as jcode-acp-harness
participant Agent as jcode acp
participant Verify as verify.py
Orchestrator->>Home: build_home() + seed_fixtures()
Orchestrator->>Harness: run_one() spawns subprocess with timeout
Harness->>Agent: Initialize, NewSession, Prompt
Agent-->>Harness: SessionUpdate events, StopReason
Harness-->>Orchestrator: result.json + events.jsonl
Orchestrator->>Verify: verify_case(oracles)
Verify-->>Orchestrator: pass/fail per oracle
Orchestrator->>Orchestrator: contract_checks() + record.json
Orchestrator->>Orchestrator: all_records.json aggregation
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 10
🧹 Nitpick comments (11)
agent-eval/analysis/analyze.py (3)
29-37: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick winSilently dropped malformed
record.jsonfiles skew aggregate stats.
except Exception: passdrops runs with unparseablerecord.jsonwith no trace, sototal_runs/pass-rate/CI in the final report can silently exclude failed runs without anyone knowing why counts don't match expectations.🩹 Suggested fix
for rd in sorted(Path(runs_dir).glob("*/record.json")): try: recs.append(json.loads(rd.read_text())) recs[-1]["_dir"] = str(rd.parent) - except Exception: - pass + except Exception as e: + print(f"warn: failed to load {rd}: {e}") return recs🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@agent-eval/analysis/analyze.py` around lines 29 - 37, The load_records function is swallowing every exception while parsing record.json, which hides malformed runs and skews the aggregate stats. Update load_records to handle json parsing failures explicitly and emit a warning or error that includes the run directory from rd.parent before skipping that record. Keep the _dir tagging for successfully parsed entries so the final report can still trace which runs were included.Source: Linters/SAST tools
40-62: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick winMalformed event lines silently dropped in loop detection.
Same swallow-and-continue pattern (Ruff S112/BLE001) — a corrupted/truncated
events.jsonlline silently reduces the loop-detection signal to 0 instead of flagging the run as suspect, undermining the very trustworthiness this harness is built to provide.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@agent-eval/analysis/analyze.py` around lines 40 - 62, The malformed `events.jsonl` parsing in `detect_loops` is silently swallowing corrupted lines, which can hide loop signals and make a bad run look clean. Update `detect_loops` so JSON decode failures are not ignored; either surface the parse error or mark the run as suspect while preserving the existing loop-count logic for valid `session_update` / `tool_call` entries. Use the `detect_loops` function and its `events.jsonl` read loop as the location to adjust the error handling.Source: Linters/SAST tools
87-99: 🎯 Functional Correctness | 🔵 Trivial | 💤 Low valueFuzzy substring model-id matching in
est_costcan attribute wrong pricing.
if k in model or model in kmatches on substring containment, so e.g. a pricing entry for"gpt-4"would also match"gpt-4o-mini"or vice versa, silently attaching an incorrect price. Since the docstring already flags this as "best-effort," this is low priority, but consider anchoring the match (e.g., exact suffix segment match) to avoid silent cost misattribution as more models are added.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@agent-eval/analysis/analyze.py` around lines 87 - 99, The fuzzy fallback matching in est_cost can select the wrong pricing entry because it uses substring containment between the pricing key and the model id. Update the matching logic in est_cost to prefer exact matches and, for fallback, only use a stricter anchored/suffix-segment comparison so models like gpt-4 and gpt-4o-mini do not cross-match. Keep the change localized to est_cost and its pricing lookup loop.agent-eval/analysis/report.py (2)
40-62: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winDuplicate JSONL event-parsing logic vs.
analyze.py.detect_loops.Both
render_trajectoryhere anddetect_loopsinagent-eval/analysis/analyze.pyimplement near-identical "read events.jsonl → skip blank/unparsable lines → filterkind == session_update" loops, with the same silent except/continue pattern. Consider extracting a sharediter_session_updates(rundir)helper (e.g. in a smallevents.pymodule) used by both scripts to avoid drift between the two consumers of the same event-stream contract.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@agent-eval/analysis/report.py` around lines 40 - 62, The event-stream parsing logic in render_trajectory duplicates the same events.jsonl scanning pattern used by detect_loops, so move the shared “read/skip/parse/filter session_update” behavior into a common helper such as iter_session_updates in a shared module. Update render_trajectory and detect_loops to consume that helper instead of maintaining separate silent try/continue loops, keeping the events.jsonl contract in one place.
64-71: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick winSilent parse-error swallowing in the report's trajectory renderer.
Same broad
except Exception: continue(Ruff S112/BLE001) asanalyze.py.detect_loops— a corrupted event line silently truncates the rendered trajectory shown in the public showcase without any indication.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@agent-eval/analysis/report.py` around lines 64 - 71, The trajectory reader in report.py is silently swallowing JSON parse failures in the loop that reads ev lines, which can hide corrupted event data and truncate the rendered output. Update the parsing in the same read_text/json.loads flow to avoid a broad except Exception and instead handle decode errors explicitly in the renderer path, logging or surfacing the bad line while continuing only when that behavior is intentional. Use the surrounding trajectory rendering logic in the report module to keep the failure visible rather than silently ignored.Source: Linters/SAST tools
agent-eval/site/showcase.html (1)
66-113: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winHardcoded PROJECTS array duplicates the generator's data contract.
PROJECTS(ids/titles/descriptions) is hand-maintained here, duplicatingMETAingenerate_data.pyand the generatedshowcase/data.json. If the eval batch is rerun with different descriptions or a new frontend case is added, this file will silently drift out of sync since it never readsdata.json.Consider fetching
../showcase/data.json(or a site-local copy) at load time and building the list from theprojectsarray instead of hardcoding it, so this page always reflects the latest generated results.Copies that run's index.html into showcase/projects/<case_id>/ and writes showcase/data.json with per-project metadata + aggregate metrics.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@agent-eval/site/showcase.html` around lines 66 - 113, The hardcoded PROJECTS list in the showcase page duplicates the generated data contract and can drift from the latest batch output. Update the logic around PROJECTS/openModal and the projects rendering block to load and build entries from showcase/data.json (or a local equivalent) instead of embedding ids/titles/descriptions inline. Use the fetched projects array to populate the cards, iframe srcs, and modal actions so the page always stays in sync with generate_data.py output.agent-eval/site/projects/fe_landing_hero/index.html (1)
1-456: 🗄️ Data Integrity & Integration | 🔵 Trivial | ⚡ Quick winKeep the site and showcase project copies in sync.
agent-eval/showcase/generate_data.pyonly writesshowcase/projects/<case_id>/index.html, whilesite/projects/<case_id>/index.htmlis maintained separately. If both are meant to stay mirrored, have the generator update both paths or derive one from the other so regenerations don't drift.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@agent-eval/site/projects/fe_landing_hero/index.html` around lines 1 - 456, The site and showcase copies are drifting because this landing page exists separately from the generated showcase copy. Update the generation flow so the same source content populates both copies, either by writing to both output paths or by making one path consume the other, and keep the shared landing page markup in sync in this index.html so regenerations do not diverge.agent-eval/showcase/projects/fe_analytics_dashboard/index.html (1)
1-767: 📐 Maintainability & Code Quality | 🔵 Trivial | 🏗️ Heavy liftDuplicated demo asset across
showcase/projectsandsite/projects.This file is byte-for-byte duplicated at
agent-eval/site/projects/fe_analytics_dashboard/index.html, and the same pattern repeats across all 6 demo projects (12 files total). Any future fix or tweak to a demo must be applied twice, and the two copies will silently drift if only one is updated (as already partially observed withMETA/PROJECTSdisplay data). Consider a small build/sync step (or symlinks, if the deployment target supports it) that generates both output locations from one canonical source.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@agent-eval/showcase/projects/fe_analytics_dashboard/index.html` around lines 1 - 767, The issue is that the same demo asset is maintained in both showcase and site outputs, which will drift over time. Update the build/publish flow for the affected demo pages (including the fe_analytics_dashboard index.html) so both locations are generated from one canonical source instead of being edited separately. If you keep both outputs, add a sync step or shared source path for all demo project files so future changes automatically propagate to both trees.agent-eval/showcase/generate_data.py (2)
22-47: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winFrontend cases missing from
METAare silently dropped.The loop only iterates
META.items(), so anycase_idpresent inall_records.jsonunder tierfrontendbut absent fromMETAis silently excluded fromdata.jsonwith no warning. If a new frontend test case is added totestcases.jsonwithout a correspondingMETAentry, it disappears from the showcase without anyone noticing.Consider logging unmatched case_ids so drift between
testcases.jsonandMETAis caught early.♻️ Suggested diff
runs_n = len(fe) pass_n = sum(1 for r in fe if r.get("task_passed")) + known_ids = set(META.keys()) + unmatched = {r["case_id"] for r in fe} - known_ids + if unmatched: + print(f"warning: frontend case_ids not in META, skipped: {sorted(unmatched)}")Also applies to: 78-101
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@agent-eval/showcase/generate_data.py` around lines 22 - 47, The frontend showcase generation in generate_data.py is silently skipping any frontend case_id that exists in all_records.json but not in META. Update the logic around the META-driven iteration to detect unmatched frontend case_ids and emit a warning or log entry when testcases.json/all_records.json contains cases not present in META, using the existing generate_data.py flow so drift is visible during data generation.
1-119: 🗄️ Data Integrity & Integration | 🔵 Trivial | ⚡ Quick win
showcase/data.jsonis dead outputshowcase/index.htmlonly redirects to../site/showcase.html, andsite/showcase.htmlhardcodes its ownPROJECTSlist. Either have the page read the generated JSON or stop writing it to avoid the two lists drifting.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@agent-eval/showcase/generate_data.py` around lines 1 - 119, The generated showcase metadata is not being used because showcase/index.html redirects to site/showcase.html, which hardcodes its own PROJECTS list, so generate_data.py is producing dead output. Update the showcase flow so the page reads the generated data.json (using the logic around main() and the projects payload) or remove the data.json write entirely if the site will keep a static PROJECTS list, and make the source of truth consistent to avoid drift.agent-eval/site/docs/assets/js/just-the-docs.js (1)
1-602: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueVendored Just-the-Docs theme script — static analysis findings are largely false positives here.
This is the stock Just-the-Docs
just-the-docs.jsasset (unmodified vendor code). TheinnerHTMLXSS warnings operate ondoc.title/doc.contentsourced from the site's own build-timesearch-data.json(not user input), the "SQL injection" hit onindex.query(...)is a lunr.js full-text query API being misclassified, and the "React useState" hits onsetTimeoutcalls are unrelated to this vanilla-JS file — all safe to disregard.The
var active/var nextdeclarations insideswitchcases (flagged by Biome at Lines 422, 433, 449) are a legitimate lint concern in isolation, but sincevaris function-scoped (not block-scoped), there's no actual cross-case leakage bug here — just a style nit in vendored code that typically shouldn't be hand-edited.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@agent-eval/site/docs/assets/js/just-the-docs.js` around lines 1 - 602, This is vendored Just-the-Docs code, so the XSS and lunr-related findings in `initSearch`/`searchLoaded` should be treated as false positives and not changed in the asset itself. If Biome still needs a cleanup, address only the `var active`/`var next` declarations in the `searchInput` keydown switch by scoping them safely within each case or by wrapping the cases in blocks, while leaving the rest of the vendor script untouched.Source: Linters/SAST tools
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@agent-eval/analysis/report.py`:
- Around line 57-117: `render_trajectory` is rendering tool-call `rawInput` and
`rawOutput` directly into the report, which leaks host-specific details like
absolute filesystem paths and usernames. Add sanitization/redaction in
`render_trajectory` before building `rows` so tool I/O is normalized and
sensitive path-like or environment-specific values are removed or replaced with
placeholders, while keeping the HTML escaping in place. Use the existing
`render_trajectory` flow and the `rawInput`/`rawOutput` handling branches as the
place to apply the redaction.
In `@agent-eval/harness/main.go`:
- Around line 201-352: The main harness flow in main() lacks signal handling, so
an external SIGTERM/SIGINT can terminate the harness before subCancel() and
cmd.Wait() run, leaving the jcode acp subprocess orphaned. Add a
signal.Notify-based handler in main() that listens for termination signals,
cancels the subprocess context (subCtx via subCancel), and records a terminal
HARNESS_ERROR/TIMEOUT-style result before exiting. Make sure the cleanup path
still reaches the exec.CommandContext, conn.Cancel, and result finalization
logic even when interrupted.
- Around line 82-85: The client struct has an unused sandbox field that will
trip the unused linter. Remove client.sandbox from the struct and any
construction/assignment in the client initialization path, or wire it into an
actual read in the client methods if it is meant to be used; check the client
type and its constructor/setup code to keep the fields consistent.
- Around line 297-333: The timeout handling in the Prompt flow can still hang
because the best-effort `conn.Cancel` call uses an unbounded
`context.Background()`. Update the timeout branch in `main.go` so the graceful
cancel uses a short bounded context (or reuses the existing `promptCtx` budget)
before the later `subCancel()`/`cmd.Wait()` cleanup, and keep the change
localized around the `conn.Prompt`/`conn.Cancel` timeout path.
In `@agent-eval/README.md`:
- Around line 70-77: The reproduction steps in README use analyze.py and
report.py with an output path that lands in the git-ignored runs directory
instead of the checked-in report artifact location. Update the documented
command, or align analyze.py’s --out default, so the generated analysis.json
matches the expected agent-eval/report/analysis.json path used by the generated
analysis/report artifacts and the report.py invocation.
In `@agent-eval/site/docs/assets/css/just-the-docs-head-nav.css`:
- Line 1: The just-the-docs-head-nav stylesheet asset is being generated as a
full HTML document instead of CSS, so fix the build/export step that writes this
file and ensure it emits only valid stylesheet rules. Use the asset target
referenced by just-the-docs-head-nav.css and verify the output matches the other
CSS assets in the same directory, with no HTML head/body markup or embedded page
content.
In `@agent-eval/site/docs/configuration.html`:
- Line 1: The Configuration page has a broken relative link for MCP Integration
in the `mcp_servers` section. Update the anchor in the configuration docs to
point to the actual MCP page path used elsewhere in the file, matching the
`Overview`/`MCP Integration` nav target. Use the surrounding `mcp_servers`
documentation block and the `MCP Integration` link text to locate and replace
the incorrect href so it resolves correctly from `configuration.html`.
In `@agent-eval/site/docs/get-started.html`:
- Line 1: The install command in the Get Started docs uses the wrong Go module
path, pointing to cnjack/docs instead of the actual jcode repository. Update the
install instruction in the Get Started page to use the same repository path as
the later git clone guidance, so the command resolves the correct module for
jcode.
In `@agent-eval/site/showcase.html`:
- Line 61: The footer contains stray ICP registration boilerplate that appears
unrelated to this site. Remove the hardcoded ICP text from the footer content in
the showcase page markup so only relevant project/footer information remains,
and keep the affected footer element consistent with the rest of the page
structure.
In `@agent-eval/suite/orchestrate.py`:
- Around line 61-76: The per-run HOME setup is persisting live provider
credentials in config.json via build_home, and _prune_home is keeping that file
after the run. Update build_home to redact or omit the providers block when
writing the run-local config, or add a post-run cleanup step in _prune_home to
strip secrets before preserving config.json. Keep only the data needed by
analyze.py and report.py (usage, sessions, debug.log), and ensure the final
persisted config no longer contains API keys.
---
Nitpick comments:
In `@agent-eval/analysis/analyze.py`:
- Around line 29-37: The load_records function is swallowing every exception
while parsing record.json, which hides malformed runs and skews the aggregate
stats. Update load_records to handle json parsing failures explicitly and emit a
warning or error that includes the run directory from rd.parent before skipping
that record. Keep the _dir tagging for successfully parsed entries so the final
report can still trace which runs were included.
- Around line 40-62: The malformed `events.jsonl` parsing in `detect_loops` is
silently swallowing corrupted lines, which can hide loop signals and make a bad
run look clean. Update `detect_loops` so JSON decode failures are not ignored;
either surface the parse error or mark the run as suspect while preserving the
existing loop-count logic for valid `session_update` / `tool_call` entries. Use
the `detect_loops` function and its `events.jsonl` read loop as the location to
adjust the error handling.
- Around line 87-99: The fuzzy fallback matching in est_cost can select the
wrong pricing entry because it uses substring containment between the pricing
key and the model id. Update the matching logic in est_cost to prefer exact
matches and, for fallback, only use a stricter anchored/suffix-segment
comparison so models like gpt-4 and gpt-4o-mini do not cross-match. Keep the
change localized to est_cost and its pricing lookup loop.
In `@agent-eval/analysis/report.py`:
- Around line 40-62: The event-stream parsing logic in render_trajectory
duplicates the same events.jsonl scanning pattern used by detect_loops, so move
the shared “read/skip/parse/filter session_update” behavior into a common helper
such as iter_session_updates in a shared module. Update render_trajectory and
detect_loops to consume that helper instead of maintaining separate silent
try/continue loops, keeping the events.jsonl contract in one place.
- Around line 64-71: The trajectory reader in report.py is silently swallowing
JSON parse failures in the loop that reads ev lines, which can hide corrupted
event data and truncate the rendered output. Update the parsing in the same
read_text/json.loads flow to avoid a broad except Exception and instead handle
decode errors explicitly in the renderer path, logging or surfacing the bad line
while continuing only when that behavior is intentional. Use the surrounding
trajectory rendering logic in the report module to keep the failure visible
rather than silently ignored.
In `@agent-eval/showcase/generate_data.py`:
- Around line 22-47: The frontend showcase generation in generate_data.py is
silently skipping any frontend case_id that exists in all_records.json but not
in META. Update the logic around the META-driven iteration to detect unmatched
frontend case_ids and emit a warning or log entry when
testcases.json/all_records.json contains cases not present in META, using the
existing generate_data.py flow so drift is visible during data generation.
- Around line 1-119: The generated showcase metadata is not being used because
showcase/index.html redirects to site/showcase.html, which hardcodes its own
PROJECTS list, so generate_data.py is producing dead output. Update the showcase
flow so the page reads the generated data.json (using the logic around main()
and the projects payload) or remove the data.json write entirely if the site
will keep a static PROJECTS list, and make the source of truth consistent to
avoid drift.
In `@agent-eval/showcase/projects/fe_analytics_dashboard/index.html`:
- Around line 1-767: The issue is that the same demo asset is maintained in both
showcase and site outputs, which will drift over time. Update the build/publish
flow for the affected demo pages (including the fe_analytics_dashboard
index.html) so both locations are generated from one canonical source instead of
being edited separately. If you keep both outputs, add a sync step or shared
source path for all demo project files so future changes automatically propagate
to both trees.
In `@agent-eval/site/docs/assets/js/just-the-docs.js`:
- Around line 1-602: This is vendored Just-the-Docs code, so the XSS and
lunr-related findings in `initSearch`/`searchLoaded` should be treated as false
positives and not changed in the asset itself. If Biome still needs a cleanup,
address only the `var active`/`var next` declarations in the `searchInput`
keydown switch by scoping them safely within each case or by wrapping the cases
in blocks, while leaving the rest of the vendor script untouched.
In `@agent-eval/site/projects/fe_landing_hero/index.html`:
- Around line 1-456: The site and showcase copies are drifting because this
landing page exists separately from the generated showcase copy. Update the
generation flow so the same source content populates both copies, either by
writing to both output paths or by making one path consume the other, and keep
the shared landing page markup in sync in this index.html so regenerations do
not diverge.
In `@agent-eval/site/showcase.html`:
- Around line 66-113: The hardcoded PROJECTS list in the showcase page
duplicates the generated data contract and can drift from the latest batch
output. Update the logic around PROJECTS/openModal and the projects rendering
block to load and build entries from showcase/data.json (or a local equivalent)
instead of embedding ids/titles/descriptions inline. Use the fetched projects
array to populate the cards, iframe srcs, and modal actions so the page always
stays in sync with generate_data.py output.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 6ce7d758-e99f-4cb4-b6ac-efe25a0a54f4
⛔ Files ignored due to path filters (5)
agent-eval/harness/go.sumis excluded by!**/*.sumagent-eval/site/docs/assets/css/just-the-docs-dark.css.mapis excluded by!**/*.mapagent-eval/site/docs/assets/css/just-the-docs-default.css.mapis excluded by!**/*.mapagent-eval/site/docs/assets/css/just-the-docs-light.css.mapis excluded by!**/*.mapagent-eval/site/docs/assets/js/vendor/lunr.min.jsis excluded by!**/*.min.js
📒 Files selected for processing (59)
agent-eval/.gitignoreagent-eval/README.mdagent-eval/analysis/analyze.pyagent-eval/analysis/findings.jsonagent-eval/analysis/report.pyagent-eval/harness/go.modagent-eval/harness/main.goagent-eval/report/analysis.jsonagent-eval/report/report.htmlagent-eval/roundtable/roundtable.jsonagent-eval/showcase/data.jsonagent-eval/showcase/generate_data.pyagent-eval/showcase/index.htmlagent-eval/showcase/projects/fe_analytics_dashboard/index.htmlagent-eval/showcase/projects/fe_canvas_particles/index.htmlagent-eval/showcase/projects/fe_landing_hero/index.htmlagent-eval/showcase/projects/fe_pricing_calculator/index.htmlagent-eval/showcase/projects/fe_svg_dataviz/index.htmlagent-eval/showcase/projects/fe_todo_app/index.htmlagent-eval/site/css/style.cssagent-eval/site/docs/assets/css/just-the-docs-dark.cssagent-eval/site/docs/assets/css/just-the-docs-default.cssagent-eval/site/docs/assets/css/just-the-docs-head-nav.cssagent-eval/site/docs/assets/css/just-the-docs-light.cssagent-eval/site/docs/assets/js/just-the-docs.jsagent-eval/site/docs/assets/js/search-data.jsonagent-eval/site/docs/commands.htmlagent-eval/site/docs/configuration.htmlagent-eval/site/docs/get-started.htmlagent-eval/site/docs/index.htmlagent-eval/site/docs/overview.htmlagent-eval/site/docs/overview/agent-teams.htmlagent-eval/site/docs/overview/agent.htmlagent-eval/site/docs/overview/context-memory.htmlagent-eval/site/docs/overview/mcp.htmlagent-eval/site/docs/overview/models.htmlagent-eval/site/docs/overview/plan-mode.htmlagent-eval/site/docs/overview/sessions.htmlagent-eval/site/docs/overview/skills.htmlagent-eval/site/docs/overview/ssh.htmlagent-eval/site/docs/overview/subagents.htmlagent-eval/site/docs/tools.htmlagent-eval/site/docs/tools/execute.htmlagent-eval/site/docs/tools/file-tools.htmlagent-eval/site/docs/tools/search-tools.htmlagent-eval/site/docs/tools/task-management.htmlagent-eval/site/docs/web-interface.htmlagent-eval/site/index.htmlagent-eval/site/js/site.jsagent-eval/site/projects/fe_analytics_dashboard/index.htmlagent-eval/site/projects/fe_canvas_particles/index.htmlagent-eval/site/projects/fe_landing_hero/index.htmlagent-eval/site/projects/fe_pricing_calculator/index.htmlagent-eval/site/projects/fe_svg_dataviz/index.htmlagent-eval/site/projects/fe_todo_app/index.htmlagent-eval/site/showcase.htmlagent-eval/suite/orchestrate.pyagent-eval/suite/testcases.jsonagent-eval/suite/verify.py
| def render_trajectory(rundir): | ||
| ev = Path(rundir) / "events.jsonl" | ||
| if not ev.exists(): | ||
| return "<p class='muted'>no event log</p>" | ||
| calls = {} | ||
| order = [] | ||
| final = [] | ||
| for line in ev.read_text(errors="ignore").splitlines(): | ||
| line = line.strip() | ||
| if not line: | ||
| continue | ||
| try: | ||
| d = json.loads(line) | ||
| except Exception: | ||
| continue | ||
| if d.get("kind") != "session_update": | ||
| continue | ||
| u = d.get("data", {}) | ||
| su = u.get("sessionUpdate") | ||
| if su == "tool_call": | ||
| tid = u.get("toolCallId") | ||
| calls[tid] = {"title": u.get("title", ""), "kind": u.get("kind", "other"), | ||
| "input": u.get("rawInput"), "status": u.get("status", ""), | ||
| "output": None} | ||
| order.append(tid) | ||
| elif su == "tool_call_update": | ||
| tid = u.get("toolCallId") | ||
| if tid in calls: | ||
| if u.get("status"): | ||
| calls[tid]["status"] = u["status"] | ||
| if u.get("rawOutput") is not None: | ||
| calls[tid]["output"] = u["rawOutput"] | ||
| elif su == "agent_message_chunk": | ||
| t = (u.get("content") or {}).get("text") | ||
| if t: | ||
| final.append(t) | ||
| rows = [] | ||
| for i, tid in enumerate(order, 1): | ||
| c = calls[tid] | ||
| icon = KIND_ICON.get(c["kind"], "🔧") | ||
| inp = json.dumps(c["input"])[:160] if c["input"] is not None else "" | ||
| out = c["output"] | ||
| if isinstance(out, (dict, list)): | ||
| out = json.dumps(out) | ||
| out = (str(out)[:180] if out is not None else "") | ||
| stat = c["status"] | ||
| stat_c = {"completed": "#73d13d", "failed": "#ff4d4f", "in_progress": "#ffc53d"}.get(stat, "#888") | ||
| rows.append(f""" | ||
| <div class="tstep"> | ||
| <div class="tnum">{i}</div> | ||
| <div class="tbody"> | ||
| <div class="ttitle">{icon} <b>{esc(c['title'])}</b> | ||
| <span class="tstat" style="color:{stat_c}">{esc(stat)}</span></div> | ||
| {f'<div class="tio">→ {esc(inp)}</div>' if inp else ''} | ||
| {f'<div class="tio out">← {esc(out)}</div>' if out else ''} | ||
| </div> | ||
| </div>""") | ||
| finaltext = esc("".join(final))[:1200] | ||
| return f"""<div class="traj">{''.join(rows)} | ||
| <div class="tfinal"><div class="tfinal-h">final answer</div>{finaltext}</div></div>""" | ||
|
|
There was a problem hiding this comment.
🔒 Security & Privacy | 🟠 Major | ⚡ Quick win
Tool-call rawInput/rawOutput are rendered verbatim, leaking local filesystem paths and a real username into the report.
render_trajectory HTML-escapes but does not sanitize rawInput/rawOutput before embedding them. The generated agent-eval/report/report.html in this PR shows full absolute paths like /private/tmp/claude-501/-Users-jack-workpath-jjj-jcode/..., exposing the developer's real machine username. Since this report is designed to feed the public showcase/marketing site (per the PR stack), shipping raw host paths (and any other environment specifics captured in tool I/O) in a public artifact is a privacy leak that should be redacted before rendering.
🔒 Suggested mitigation
+import re
+
+_HOME_PATH_RE = re.compile(r"/(?:Users|home)/[^/\s\"]+")
+
+def _redact(s):
+ return _HOME_PATH_RE.sub("~", s) if isinstance(s, str) else s
+
def render_trajectory(rundir):
...
- inp = json.dumps(c["input"])[:160] if c["input"] is not None else ""
+ inp = _redact(json.dumps(c["input"]))[:160] if c["input"] is not None else ""
out = c["output"]
if isinstance(out, (dict, list)):
out = json.dumps(out)
- out = (str(out)[:180] if out is not None else "")
+ out = _redact(str(out))[:180] if out is not None else ""📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| def render_trajectory(rundir): | |
| ev = Path(rundir) / "events.jsonl" | |
| if not ev.exists(): | |
| return "<p class='muted'>no event log</p>" | |
| calls = {} | |
| order = [] | |
| final = [] | |
| for line in ev.read_text(errors="ignore").splitlines(): | |
| line = line.strip() | |
| if not line: | |
| continue | |
| try: | |
| d = json.loads(line) | |
| except Exception: | |
| continue | |
| if d.get("kind") != "session_update": | |
| continue | |
| u = d.get("data", {}) | |
| su = u.get("sessionUpdate") | |
| if su == "tool_call": | |
| tid = u.get("toolCallId") | |
| calls[tid] = {"title": u.get("title", ""), "kind": u.get("kind", "other"), | |
| "input": u.get("rawInput"), "status": u.get("status", ""), | |
| "output": None} | |
| order.append(tid) | |
| elif su == "tool_call_update": | |
| tid = u.get("toolCallId") | |
| if tid in calls: | |
| if u.get("status"): | |
| calls[tid]["status"] = u["status"] | |
| if u.get("rawOutput") is not None: | |
| calls[tid]["output"] = u["rawOutput"] | |
| elif su == "agent_message_chunk": | |
| t = (u.get("content") or {}).get("text") | |
| if t: | |
| final.append(t) | |
| rows = [] | |
| for i, tid in enumerate(order, 1): | |
| c = calls[tid] | |
| icon = KIND_ICON.get(c["kind"], "🔧") | |
| inp = json.dumps(c["input"])[:160] if c["input"] is not None else "" | |
| out = c["output"] | |
| if isinstance(out, (dict, list)): | |
| out = json.dumps(out) | |
| out = (str(out)[:180] if out is not None else "") | |
| stat = c["status"] | |
| stat_c = {"completed": "#73d13d", "failed": "#ff4d4f", "in_progress": "#ffc53d"}.get(stat, "#888") | |
| rows.append(f""" | |
| <div class="tstep"> | |
| <div class="tnum">{i}</div> | |
| <div class="tbody"> | |
| <div class="ttitle">{icon} <b>{esc(c['title'])}</b> | |
| <span class="tstat" style="color:{stat_c}">{esc(stat)}</span></div> | |
| {f'<div class="tio">→ {esc(inp)}</div>' if inp else ''} | |
| {f'<div class="tio out">← {esc(out)}</div>' if out else ''} | |
| </div> | |
| </div>""") | |
| finaltext = esc("".join(final))[:1200] | |
| return f"""<div class="traj">{''.join(rows)} | |
| <div class="tfinal"><div class="tfinal-h">final answer</div>{finaltext}</div></div>""" | |
| import re | |
| _HOME_PATH_RE = re.compile(r"/(?:Users|home)/[^/\s\"]+") | |
| def _redact(s): | |
| return _HOME_PATH_RE.sub("~", s) if isinstance(s, str) else s | |
| def render_trajectory(rundir): | |
| ev = Path(rundir) / "events.jsonl" | |
| if not ev.exists(): | |
| return "<p class='muted'>no event log</p>" | |
| calls = {} | |
| order = [] | |
| final = [] | |
| for line in ev.read_text(errors="ignore").splitlines(): | |
| line = line.strip() | |
| if not line: | |
| continue | |
| try: | |
| d = json.loads(line) | |
| except Exception: | |
| continue | |
| if d.get("kind") != "session_update": | |
| continue | |
| u = d.get("data", {}) | |
| su = u.get("sessionUpdate") | |
| if su == "tool_call": | |
| tid = u.get("toolCallId") | |
| calls[tid] = {"title": u.get("title", ""), "kind": u.get("kind", "other"), | |
| "input": u.get("rawInput"), "status": u.get("status", ""), | |
| "output": None} | |
| order.append(tid) | |
| elif su == "tool_call_update": | |
| tid = u.get("toolCallId") | |
| if tid in calls: | |
| if u.get("status"): | |
| calls[tid]["status"] = u["status"] | |
| if u.get("rawOutput") is not None: | |
| calls[tid]["output"] = u["rawOutput"] | |
| elif su == "agent_message_chunk": | |
| t = (u.get("content") or {}).get("text") | |
| if t: | |
| final.append(t) | |
| rows = [] | |
| for i, tid in enumerate(order, 1): | |
| c = calls[tid] | |
| icon = KIND_ICON.get(c["kind"], "🔧") | |
| inp = _redact(json.dumps(c["input"]))[:160] if c["input"] is not None else "" | |
| out = c["output"] | |
| if isinstance(out, (dict, list)): | |
| out = json.dumps(out) | |
| out = _redact(str(out))[:180] if out is not None else "" | |
| stat = c["status"] | |
| stat_c = {"completed": "`#73d13d`", "failed": "`#ff4d4f`", "in_progress": "`#ffc53d`"}.get(stat, "`#888`") | |
| rows.append(f""" | |
| <div class="tstep"> | |
| <div class="tnum">{i}</div> | |
| <div class="tbody"> | |
| <div class="ttitle">{icon} <b>{esc(c['title'])}</b> | |
| <span class="tstat" style="color:{stat_c}">{esc(stat)}</span></div> | |
| {f'<div class="tio">→ {esc(inp)}</div>' if inp else ''} | |
| {f'<div class="tio out">← {esc(out)}</div>' if out else ''} | |
| </div> | |
| </div>""") | |
| finaltext = esc("".join(final))[:1200] | |
| return f"""<div class="traj">{''.join(rows)} | |
| <div class="tfinal"><div class="tfinal-h">final answer</div>{finaltext}</div></div>""" |
🧰 Tools
🪛 ast-grep (0.44.0)
[info] 96-96: use jsonify instead of json.dumps for JSON output
Context: json.dumps(c["input"])
Note: [CWE-116] Improper Encoding or Escaping of Output.
(use-jsonify)
[info] 99-99: use jsonify instead of json.dumps for JSON output
Context: json.dumps(out)
Note: [CWE-116] Improper Encoding or Escaping of Output.
(use-jsonify)
🪛 Ruff (0.15.20)
[error] 70-71: try-except-continue detected, consider logging the exception
(S112)
[warning] 70-70: Do not catch blind exception: Exception
(BLE001)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@agent-eval/analysis/report.py` around lines 57 - 117, `render_trajectory` is
rendering tool-call `rawInput` and `rawOutput` directly into the report, which
leaks host-specific details like absolute filesystem paths and usernames. Add
sanitization/redaction in `render_trajectory` before building `rows` so tool I/O
is normalized and sensitive path-like or environment-specific values are removed
or replaced with placeholders, while keeping the HTML escaping in place. Use the
existing `render_trajectory` flow and the `rawInput`/`rawOutput` handling
branches as the place to apply the redaction.
| type client struct { | ||
| rec *recorder | ||
| sandbox string | ||
| } |
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick win
Unused sandbox field.
client.sandbox is written at construction but never read. Given .golangci.yml enforces the unused linter, this is likely to fail CI as-is.
♻️ Proposed fix
type client struct {
rec *recorder
- sandbox string
}- conn := acp.NewClientSideConnection(&client{rec: rec, sandbox: *cwd}, stdin, stdout)
+ conn := acp.NewClientSideConnection(&client{rec: rec}, stdin, stdout)Also applies to: 262-262
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@agent-eval/harness/main.go` around lines 82 - 85, The client struct has an
unused sandbox field that will trip the unused linter. Remove client.sandbox
from the struct and any construction/assignment in the client initialization
path, or wire it into an actual read in the client methods if it is meant to be
used; check the client type and its constructor/setup code to keep the fields
consistent.
| func main() { | ||
| var ( | ||
| bin = flag.String("bin", "", "path to jcode binary") | ||
| cwd = flag.String("cwd", "", "session working directory (sandbox, absolute)") | ||
| promptStr = flag.String("prompt", "", "prompt text (or use -promptfile)") | ||
| promptFile = flag.String("promptfile", "", "file containing the prompt text") | ||
| outPath = flag.String("out", "events.jsonl", "event log output path") | ||
| model = flag.String("model", "", "model label recorded in the result") | ||
| modeStr = flag.String("mode", "full_access", "session mode: approval|plan|full_access") | ||
| timeoutSec = flag.Int("timeout", 300, "prompt turn timeout in seconds") | ||
| setupSec = flag.Int("setup-timeout", 90, "initialize+new-session timeout in seconds") | ||
| ) | ||
| flag.Parse() | ||
|
|
||
| if *promptFile != "" { | ||
| b, err := os.ReadFile(*promptFile) | ||
| if err != nil { | ||
| die(map[string]any{"stop_reason": "HARNESS_ERROR", "error": "read promptfile: " + err.Error(), "model": *model}) | ||
| } | ||
| *promptStr = string(b) | ||
| } | ||
| if *bin == "" || *cwd == "" || *promptStr == "" { | ||
| die(map[string]any{"stop_reason": "HARNESS_ERROR", "error": "missing -bin/-cwd/-prompt", "model": *model}) | ||
| } | ||
|
|
||
| f, err := os.Create(*outPath) | ||
| if err != nil { | ||
| die(map[string]any{"stop_reason": "HARNESS_ERROR", "error": "create out: " + err.Error(), "model": *model}) | ||
| } | ||
| defer f.Close() | ||
| rec := newRecorder(f) | ||
|
|
||
| result := map[string]any{"model": *model, "cwd": *cwd, "mode": *modeStr} | ||
| start := time.Now() | ||
|
|
||
| // Launch the jcode ACP server. HOME/env is inherited from the caller, which | ||
| // is expected to have already pointed HOME at an isolated throwaway dir. | ||
| subCtx, subCancel := context.WithCancel(context.Background()) | ||
| defer subCancel() | ||
| cmd := exec.CommandContext(subCtx, *bin, "acp") | ||
| cmd.Env = os.Environ() | ||
| cmd.Dir = *cwd | ||
| stdin, err := cmd.StdinPipe() | ||
| if err != nil { | ||
| finish(rec, result, "HARNESS_ERROR", "stdin pipe: "+err.Error(), start) | ||
| return | ||
| } | ||
| stdout, err := cmd.StdoutPipe() | ||
| if err != nil { | ||
| finish(rec, result, "HARNESS_ERROR", "stdout pipe: "+err.Error(), start) | ||
| return | ||
| } | ||
| if stderrF, ferr := os.Create(*outPath + ".stderr"); ferr == nil { | ||
| cmd.Stderr = stderrF | ||
| defer stderrF.Close() | ||
| } | ||
| if err := cmd.Start(); err != nil { | ||
| finish(rec, result, "HARNESS_ERROR", "start jcode: "+err.Error(), start) | ||
| return | ||
| } | ||
|
|
||
| conn := acp.NewClientSideConnection(&client{rec: rec, sandbox: *cwd}, stdin, stdout) | ||
|
|
||
| // Phase 1: initialize + new session, under a setup timeout. | ||
| setupCtx, setupCancel := context.WithTimeout(context.Background(), time.Duration(*setupSec)*time.Second) | ||
| defer setupCancel() | ||
|
|
||
| initResp, err := conn.Initialize(setupCtx, acp.InitializeRequest{ | ||
| ProtocolVersion: acp.ProtocolVersionNumber, | ||
| ClientInfo: &acp.Implementation{Name: "jcode-acp-harness", Version: "0.1.0"}, | ||
| }) | ||
| if err != nil { | ||
| subCancel() | ||
| _ = cmd.Wait() | ||
| finish(rec, result, "INIT_ERROR", "initialize: "+err.Error(), start) | ||
| return | ||
| } | ||
| rec.line("initialized", initResp) | ||
|
|
||
| ns, err := conn.NewSession(setupCtx, acp.NewSessionRequest{Cwd: *cwd, McpServers: []acp.McpServer{}}) | ||
| if err != nil { | ||
| subCancel() | ||
| _ = cmd.Wait() | ||
| finish(rec, result, "NEWSESSION_ERROR", "new session: "+err.Error(), start) | ||
| return | ||
| } | ||
| sid := ns.SessionId | ||
| result["sessionId"] = string(sid) | ||
| rec.line("session_new", map[string]any{"sessionId": string(sid)}) | ||
|
|
||
| if *modeStr != "" { | ||
| if _, merr := conn.SetSessionMode(setupCtx, acp.SetSessionModeRequest{SessionId: sid, ModeId: acp.SessionModeId(*modeStr)}); merr != nil { | ||
| rec.line("setmode_error", map[string]any{"err": merr.Error()}) | ||
| } | ||
| } | ||
|
|
||
| // Phase 2: run the prompt turn under a wall-clock timeout. | ||
| promptCtx, promptCancel := context.WithTimeout(context.Background(), time.Duration(*timeoutSec)*time.Second) | ||
| defer promptCancel() | ||
|
|
||
| presp, perr := conn.Prompt(promptCtx, acp.PromptRequest{ | ||
| SessionId: sid, | ||
| Prompt: []acp.ContentBlock{acp.TextBlock(*promptStr)}, | ||
| }) | ||
| elapsed := time.Since(start) | ||
|
|
||
| // Attach summary counters gathered from the stream. | ||
| rec.mu.Lock() | ||
| result["tool_calls"] = rec.toolCalls | ||
| result["tool_updates"] = rec.toolUpdates | ||
| result["tool_names"] = rec.toolNames | ||
| result["tool_kind"] = rec.toolKind | ||
| result["tool_titles"] = rec.toolTitles | ||
| result["tool_status_end"] = rec.toolStatusEnd | ||
| result["thought_chunks"] = rec.thoughtChunks | ||
| result["agent_chunks"] = rec.agentChunks | ||
| result["agent_text_len"] = rec.agentTextLen | ||
| result["permission_reqs"] = rec.permissionN | ||
| result["plans"] = rec.plans | ||
| result["final_text"] = string(rec.finalText) | ||
| if rec.lastUsage != nil { | ||
| result["usage_update"] = json.RawMessage(rec.lastUsage) | ||
| } | ||
| rec.mu.Unlock() | ||
|
|
||
| result["elapsed_ms"] = elapsed.Milliseconds() | ||
|
|
||
| switch { | ||
| case perr != nil && promptCtx.Err() == context.DeadlineExceeded: | ||
| result["stop_reason"] = "TIMEOUT" | ||
| result["error"] = fmt.Sprintf("prompt turn exceeded %ds wall-clock", *timeoutSec) | ||
| // best-effort graceful cancel before killing | ||
| _ = conn.Cancel(context.Background(), acp.CancelNotification{SessionId: sid}) | ||
| case perr != nil: | ||
| result["stop_reason"] = "PROMPT_ERROR" | ||
| result["error"] = perr.Error() | ||
| default: | ||
| result["stop_reason"] = string(presp.StopReason) | ||
| if presp.Usage != nil { | ||
| result["prompt_usage"] = presp.Usage | ||
| } | ||
| } | ||
|
|
||
| rec.line("result", result) | ||
|
|
||
| // Tear down the subprocess. | ||
| subCancel() | ||
| _ = cmd.Wait() | ||
|
|
||
| out, _ := json.Marshal(result) | ||
| fmt.Println(string(out)) | ||
| } |
There was a problem hiding this comment.
🩺 Stability & Availability | 🟠 Major | 🏗️ Heavy lift
No signal handling — external SIGTERM (from orchestrate.py's outer timeout wrapper) can orphan the jcode acp subprocess.
orchestrate.py wraps this harness with the timeout coreutil as a backstop (see orchestrate.py line 191-192). timeout signals only its direct child (this harness), not further descendants. If this process is killed by that outer SIGTERM before reaching its own subCancel()/cmd.Wait() cleanup (e.g., because the earlier unbounded conn.Cancel is what caused the outer timeout to fire), the jcode acp grandchild subprocess is never signaled and can keep running indefinitely — exactly the "agent can hang" failure mode (F3) this harness is meant to detect and bound. Consider adding a signal.Notify handler for SIGTERM/SIGINT that cancels subCtx (killing the child) and flushes a terminal result before exiting.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@agent-eval/harness/main.go` around lines 201 - 352, The main harness flow in
main() lacks signal handling, so an external SIGTERM/SIGINT can terminate the
harness before subCancel() and cmd.Wait() run, leaving the jcode acp subprocess
orphaned. Add a signal.Notify-based handler in main() that listens for
termination signals, cancels the subprocess context (subCtx via subCancel), and
records a terminal HARNESS_ERROR/TIMEOUT-style result before exiting. Make sure
the cleanup path still reaches the exec.CommandContext, conn.Cancel, and result
finalization logic even when interrupted.
| // Phase 2: run the prompt turn under a wall-clock timeout. | ||
| promptCtx, promptCancel := context.WithTimeout(context.Background(), time.Duration(*timeoutSec)*time.Second) | ||
| defer promptCancel() | ||
|
|
||
| presp, perr := conn.Prompt(promptCtx, acp.PromptRequest{ | ||
| SessionId: sid, | ||
| Prompt: []acp.ContentBlock{acp.TextBlock(*promptStr)}, | ||
| }) | ||
| elapsed := time.Since(start) | ||
|
|
||
| // Attach summary counters gathered from the stream. | ||
| rec.mu.Lock() | ||
| result["tool_calls"] = rec.toolCalls | ||
| result["tool_updates"] = rec.toolUpdates | ||
| result["tool_names"] = rec.toolNames | ||
| result["tool_kind"] = rec.toolKind | ||
| result["tool_titles"] = rec.toolTitles | ||
| result["tool_status_end"] = rec.toolStatusEnd | ||
| result["thought_chunks"] = rec.thoughtChunks | ||
| result["agent_chunks"] = rec.agentChunks | ||
| result["agent_text_len"] = rec.agentTextLen | ||
| result["permission_reqs"] = rec.permissionN | ||
| result["plans"] = rec.plans | ||
| result["final_text"] = string(rec.finalText) | ||
| if rec.lastUsage != nil { | ||
| result["usage_update"] = json.RawMessage(rec.lastUsage) | ||
| } | ||
| rec.mu.Unlock() | ||
|
|
||
| result["elapsed_ms"] = elapsed.Milliseconds() | ||
|
|
||
| switch { | ||
| case perr != nil && promptCtx.Err() == context.DeadlineExceeded: | ||
| result["stop_reason"] = "TIMEOUT" | ||
| result["error"] = fmt.Sprintf("prompt turn exceeded %ds wall-clock", *timeoutSec) | ||
| // best-effort graceful cancel before killing | ||
| _ = conn.Cancel(context.Background(), acp.CancelNotification{SessionId: sid}) |
There was a problem hiding this comment.
🩺 Stability & Availability | 🟠 Major | ⚡ Quick win
Unbounded conn.Cancel on timeout can hang the very timeout it's implementing.
When the prompt turn times out, the "best-effort graceful cancel" uses context.Background() with no deadline. If the agent/subprocess is genuinely unresponsive (the scenario this timeout exists to catch, cf. README's finding F3 about hangs), this call can block indefinitely, delaying subCancel()/cmd.Wait() that would actually terminate the subprocess.
🐛 Proposed fix: bound the cancel call
case perr != nil && promptCtx.Err() == context.DeadlineExceeded:
result["stop_reason"] = "TIMEOUT"
result["error"] = fmt.Sprintf("prompt turn exceeded %ds wall-clock", *timeoutSec)
// best-effort graceful cancel before killing
- _ = conn.Cancel(context.Background(), acp.CancelNotification{SessionId: sid})
+ cancelCtx, cancelCtxCancel := context.WithTimeout(context.Background(), 5*time.Second)
+ _ = conn.Cancel(cancelCtx, acp.CancelNotification{SessionId: sid})
+ cancelCtxCancel()📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| // Phase 2: run the prompt turn under a wall-clock timeout. | |
| promptCtx, promptCancel := context.WithTimeout(context.Background(), time.Duration(*timeoutSec)*time.Second) | |
| defer promptCancel() | |
| presp, perr := conn.Prompt(promptCtx, acp.PromptRequest{ | |
| SessionId: sid, | |
| Prompt: []acp.ContentBlock{acp.TextBlock(*promptStr)}, | |
| }) | |
| elapsed := time.Since(start) | |
| // Attach summary counters gathered from the stream. | |
| rec.mu.Lock() | |
| result["tool_calls"] = rec.toolCalls | |
| result["tool_updates"] = rec.toolUpdates | |
| result["tool_names"] = rec.toolNames | |
| result["tool_kind"] = rec.toolKind | |
| result["tool_titles"] = rec.toolTitles | |
| result["tool_status_end"] = rec.toolStatusEnd | |
| result["thought_chunks"] = rec.thoughtChunks | |
| result["agent_chunks"] = rec.agentChunks | |
| result["agent_text_len"] = rec.agentTextLen | |
| result["permission_reqs"] = rec.permissionN | |
| result["plans"] = rec.plans | |
| result["final_text"] = string(rec.finalText) | |
| if rec.lastUsage != nil { | |
| result["usage_update"] = json.RawMessage(rec.lastUsage) | |
| } | |
| rec.mu.Unlock() | |
| result["elapsed_ms"] = elapsed.Milliseconds() | |
| switch { | |
| case perr != nil && promptCtx.Err() == context.DeadlineExceeded: | |
| result["stop_reason"] = "TIMEOUT" | |
| result["error"] = fmt.Sprintf("prompt turn exceeded %ds wall-clock", *timeoutSec) | |
| // best-effort graceful cancel before killing | |
| _ = conn.Cancel(context.Background(), acp.CancelNotification{SessionId: sid}) | |
| // Phase 2: run the prompt turn under a wall-clock timeout. | |
| promptCtx, promptCancel := context.WithTimeout(context.Background(), time.Duration(*timeoutSec)*time.Second) | |
| defer promptCancel() | |
| presp, perr := conn.Prompt(promptCtx, acp.PromptRequest{ | |
| SessionId: sid, | |
| Prompt: []acp.ContentBlock{acp.TextBlock(*promptStr)}, | |
| }) | |
| elapsed := time.Since(start) | |
| // Attach summary counters gathered from the stream. | |
| rec.mu.Lock() | |
| result["tool_calls"] = rec.toolCalls | |
| result["tool_updates"] = rec.toolUpdates | |
| result["tool_names"] = rec.toolNames | |
| result["tool_kind"] = rec.toolKind | |
| result["tool_titles"] = rec.toolTitles | |
| result["tool_status_end"] = rec.toolStatusEnd | |
| result["thought_chunks"] = rec.thoughtChunks | |
| result["agent_chunks"] = rec.agentChunks | |
| result["agent_text_len"] = rec.agentTextLen | |
| result["permission_reqs"] = rec.permissionN | |
| result["plans"] = rec.plans | |
| result["final_text"] = string(rec.finalText) | |
| if rec.lastUsage != nil { | |
| result["usage_update"] = json.RawMessage(rec.lastUsage) | |
| } | |
| rec.mu.Unlock() | |
| result["elapsed_ms"] = elapsed.Milliseconds() | |
| switch { | |
| case perr != nil && promptCtx.Err() == context.DeadlineExceeded: | |
| result["stop_reason"] = "TIMEOUT" | |
| result["error"] = fmt.Sprintf("prompt turn exceeded %ds wall-clock", *timeoutSec) | |
| // best-effort graceful cancel before killing | |
| cancelCtx, cancelCtxCancel := context.WithTimeout(context.Background(), 5*time.Second) | |
| _ = conn.Cancel(cancelCtx, acp.CancelNotification{SessionId: sid}) | |
| cancelCtxCancel() |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@agent-eval/harness/main.go` around lines 297 - 333, The timeout handling in
the Prompt flow can still hang because the best-effort `conn.Cancel` call uses
an unbounded `context.Background()`. Update the timeout branch in `main.go` so
the graceful cancel uses a short bounded context (or reuses the existing
`promptCtx` budget) before the later `subCancel()`/`cmd.Wait()` cleanup, and
keep the change localized around the `conn.Prompt`/`conn.Cancel` timeout path.
| # 3. analyze + render the report | ||
| python3 agent-eval/analysis/analyze.py --runs-dir agent-eval/runs --out agent-eval/runs/analysis.json | ||
| python3 agent-eval/analysis/report.py \ | ||
| --analysis agent-eval/runs/analysis.json \ | ||
| --roundtable agent-eval/roundtable/roundtable.json \ | ||
| --findings agent-eval/analysis/findings.json \ | ||
| --runs-dir agent-eval/runs --out agent-eval/report/report.html | ||
| ``` |
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win
Reproduction command writes analysis.json to the wrong (git-ignored) location.
analyze.py --out agent-eval/runs/analysis.json writes into runs/, which this same PR's .gitignore excludes. But the PR stack's checked-in generated artifact lives at agent-eval/report/analysis.json (per the "Generated analysis and report artifacts" layer). Following these exact instructions won't reproduce the committed report artifact path — worth aligning the doc (or the actual --out default) with where results are actually meant to land.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@agent-eval/README.md` around lines 70 - 77, The reproduction steps in README
use analyze.py and report.py with an output path that lands in the git-ignored
runs directory instead of the checked-in report artifact location. Update the
documented command, or align analyze.py’s --out default, so the generated
analysis.json matches the expected agent-eval/report/analysis.json path used by
the generated analysis/report artifacts and the report.py invocation.
| @@ -0,0 +1 @@ | |||
| <!DOCTYPE html> <html lang="en-US"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=Edge"> <link rel="stylesheet" href="/docs/assets/css/just-the-docs-default.css"> <link rel="stylesheet" href="/docs/assets/css/just-the-docs-head-nav.css" id="jtd-head-nav-stylesheet"> <style id="jtd-nav-activation"> .site-nav ul li a { background-image: none; } </style> <script src="/docs/assets/js/vendor/lunr.min.js"></script> <script src="/docs/assets/js/just-the-docs.js"></script> <meta name="viewport" content="width=device-width, initial-scale=1"> <!-- Begin Jekyll SEO tag v2.8.0 --> <title>jcode | Think it. Code it.</title> <meta name="generator" content="Jekyll v4.4.1" /> <meta property="og:title" content="jcode" /> <meta property="og:locale" content="en_US" /> <meta name="description" content="jcode — Your AI Coding Companion. An intelligent coding agent that lives in your terminal." /> <meta property="og:description" content="jcode — Your AI Coding Companion. An intelligent coding agent that lives in your terminal." /> <link rel="canonical" href="/docs/assets/css/just-the-docs-head-nav.css" /> <meta property="og:url" content="/docs/assets/css/just-the-docs-head-nav.css" /> <meta property="og:site_name" content="jcode" /> <meta property="og:type" content="website" /> <meta name="twitter:card" content="summary" /> <meta property="twitter:title" content="jcode" /> <script type="application/ld+json"> {"@context":"https://schema.org","@type":"WebPage","description":"jcode — Your AI Coding Companion. An intelligent coding agent that lives in your terminal.","headline":"jcode","url":"/docs/assets/css/just-the-docs-head-nav.css"}</script> <!-- End Jekyll SEO tag --> </head> <body> <a class="skip-to-main" href="#main-content">Skip to main content</a> <svg xmlns="http://www.w3.org/2000/svg" class="d-none"> <symbol id="svg-link" viewBox="0 0 24 24"> <title>Link</title> <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-link"> <path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"></path><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"></path> </svg> </symbol> <symbol id="svg-menu" viewBox="0 0 24 24"> <title>Menu</title> <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-menu"> <line x1="3" y1="12" x2="21" y2="12"></line><line x1="3" y1="6" x2="21" y2="6"></line><line x1="3" y1="18" x2="21" y2="18"></line> </svg> </symbol> <symbol id="svg-arrow-right" viewBox="0 0 24 24"> <title>Expand</title> <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-chevron-right"> <polyline points="9 18 15 12 9 6"></polyline> </svg> </symbol> <!-- Feather. MIT License: https://github.com/feathericons/feather/blob/master/LICENSE --> <symbol id="svg-external-link" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-external-link"> <title id="svg-external-link-title">(external link)</title> <path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"></path><polyline points="15 3 21 3 21 9"></polyline><line x1="10" y1="14" x2="21" y2="3"></line> </symbol> <symbol id="svg-doc" viewBox="0 0 24 24"> <title>Document</title> <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-file"> <path d="M13 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V9z"></path><polyline points="13 2 13 9 20 9"></polyline> </svg> </symbol> <symbol id="svg-search" viewBox="0 0 24 24"> <title>Search</title> <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-search"> <circle cx="11" cy="11" r="8"></circle><line x1="21" y1="21" x2="16.65" y2="16.65"></line> </svg> </symbol> <!-- Bootstrap Icons. MIT License: https://github.com/twbs/icons/blob/main/LICENSE.md --> <symbol id="svg-copy" viewBox="0 0 16 16"> <title>Copy</title> <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-clipboard" viewBox="0 0 16 16"> <path d="M4 1.5H3a2 2 0 0 0-2 2V14a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2V3.5a2 2 0 0 0-2-2h-1v1h1a1 1 0 0 1 1 1V14a1 1 0 0 1-1 1H3a1 1 0 0 1-1-1V3.5a1 1 0 0 1 1-1h1v-1z"/> <path d="M9.5 1a.5.5 0 0 1 .5.5v1a.5.5 0 0 1-.5.5h-3a.5.5 0 0 1-.5-.5v-1a.5.5 0 0 1 .5-.5h3zm-3-1A1.5 1.5 0 0 0 5 1.5v1A1.5 1.5 0 0 0 6.5 4h3A1.5 1.5 0 0 0 11 2.5v-1A1.5 1.5 0 0 0 9.5 0h-3z"/> </svg> </symbol> <symbol id="svg-copied" viewBox="0 0 16 16"> <title>Copied</title> <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-clipboard-check-fill" viewBox="0 0 16 16"> <path d="M6.5 0A1.5 1.5 0 0 0 5 1.5v1A1.5 1.5 0 0 0 6.5 4h3A1.5 1.5 0 0 0 11 2.5v-1A1.5 1.5 0 0 0 9.5 0h-3Zm3 1a.5.5 0 0 1 .5.5v1a.5.5 0 0 1-.5.5h-3a.5.5 0 0 1-.5-.5v-1a.5.5 0 0 1 .5-.5h3Z"/> <path d="M4 1.5H3a2 2 0 0 0-2 2V14a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2V3.5a2 2 0 0 0-2-2h-1v1A2.5 2.5 0 0 1 9.5 5h-3A2.5 2.5 0 0 1 4 2.5v-1Zm6.854 7.354-3 3a.5.5 0 0 1-.708 0l-1.5-1.5a.5.5 0 0 1 .708-.708L7.5 10.793l2.646-2.647a.5.5 0 0 1 .708.708Z"/> </svg> </symbol> </svg> <header class="side-bar"> <div class="site-header"> <a href="/docs/" class="site-title lh-tight"> jcode </a> <button id="menu-button" class="site-button btn-reset" aria-label="Menu" aria-expanded="false"> <svg viewBox="0 0 24 24" class="icon" aria-hidden="true"><use xlink:href="#svg-menu"></use></svg> </button> </div> <nav aria-label="Main" id="site-nav" class="site-nav"> <ul class="nav-list"><li class="nav-list-item"><a href="/docs/get-started.html" class="nav-list-link">Get Started</a></li><li class="nav-list-item"><button class="nav-list-expander btn-reset" aria-label="Overview submenu" aria-expanded="false"> <svg viewBox="0 0 24 24" aria-hidden="true"><use xlink:href="#svg-arrow-right"></use></svg> </button><a href="/docs/overview.html" class="nav-list-link">Overview</a><ul class="nav-list"><li class="nav-list-item"><a href="/docs/overview/models.html" class="nav-list-link">Model Providers & Models</a></li><li class="nav-list-item"><a href="/docs/overview/agent.html" class="nav-list-link">Agent</a></li><li class="nav-list-item"><a href="/docs/overview/subagents.html" class="nav-list-link">Subagents</a></li><li class="nav-list-item"><a href="/docs/overview/agent-teams.html" class="nav-list-link">Agent Teams</a></li><li class="nav-list-item"><a href="/docs/overview/skills.html" class="nav-list-link">Skills</a></li><li class="nav-list-item"><a href="/docs/overview/plan-mode.html" class="nav-list-link">Plan Mode</a></li><li class="nav-list-item"><a href="/docs/overview/ssh.html" class="nav-list-link">SSH & Remote Work</a></li><li class="nav-list-item"><a href="/docs/overview/sessions.html" class="nav-list-link">Sessions & Resume</a></li><li class="nav-list-item"><a href="/docs/overview/context-memory.html" class="nav-list-link">Context & Memory</a></li><li class="nav-list-item"><a href="/docs/overview/mcp.html" class="nav-list-link">MCP Integration</a></li></ul></li><li class="nav-list-item"><button class="nav-list-expander btn-reset" aria-label="Tools submenu" aria-expanded="false"> <svg viewBox="0 0 24 24" aria-hidden="true"><use xlink:href="#svg-arrow-right"></use></svg> </button><a href="/docs/tools.html" class="nav-list-link">Tools</a><ul class="nav-list"><li class="nav-list-item"><a href="/docs/tools/file-tools.html" class="nav-list-link">File Tools</a></li><li class="nav-list-item"><a href="/docs/tools/search-tools.html" class="nav-list-link">Search Tools</a></li><li class="nav-list-item"><a href="/docs/tools/execute.html" class="nav-list-link">Execute</a></li><li class="nav-list-item"><a href="/docs/tools/task-management.html" class="nav-list-link">Task Management</a></li></ul></li><li class="nav-list-item"><a href="/docs/web-interface.html" class="nav-list-link">Web Interface</a></li><li class="nav-list-item"><a href="/docs/configuration.html" class="nav-list-link">Configuration</a></li><li class="nav-list-item"><a href="/docs/commands.html" class="nav-list-link">Commands & Shortcuts</a></li></ul> </nav> <div class="d-md-block d-none site-footer"> This site uses <a href="https://github.com/just-the-docs/just-the-docs">Just the Docs</a>, a documentation theme for Jekyll. </div> </header> <div class="main" id="top"> <div id="main-header" class="main-header"> <div class="search" role="search"> <div class="search-input-wrap"> <input type="text" id="search-input" class="search-input" tabindex="0" placeholder="Search jcode" autocomplete="off"> <label for="search-input" class="search-label"> <span class="sr-only">Search jcode</span> <svg viewBox="0 0 24 24" class="search-icon" aria-hidden="true"><use xlink:href="#svg-search"></use></svg> </label> </div> <div id="search-results" class="search-results"></div> </div> </div> <div class="main-content-wrap"> <div id="main-content" class="main-content"> <main> <h.site-nav ul li a { background-image: linear-gradient(-90deg, rgb(234.8, 236.82, 244.9) 0%, rgba(234.8, 236.82, 244.9, 0.8) 80%, rgba(234.8, 236.82, 244.9, 0) 100%); } </main> <hr> <footer> <p><a href="#top" id="back-to-top">Back to top</a></p> <div class="d-md-none mt-4 fs-2"> This site uses <a href="https://github.com/just-the-docs/just-the-docs">Just the Docs</a>, a documentation theme for Jekyll. </div> </footer> </div> </div> <div class="search-overlay"></div> </div> </body> </html> | |||
There was a problem hiding this comment.
🎯 Functional Correctness | 🟠 Major | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Description: Confirm every page's head-nav CSS file is similarly corrupted or if this is isolated.
fd -e css . agent-eval/site/docs/assets/css --exec sh -c 'echo "=== {} ==="; head -c 200 "{}"'Repository: cnjack/jcode
Length of output: 1210
agent-eval/site/docs/assets/css/just-the-docs-head-nav.css is not CSS
This asset contains a full HTML document, so the nav-highlighting stylesheet can’t be parsed or applied. The other files in agent-eval/site/docs/assets/css are normal CSS, so this looks isolated to the generator/build step that wrote the wrong artifact here.
🧰 Tools
🪛 Stylelint (17.14.0)
[error] 1-1: Missed semicolon (CssSyntaxError)
(CssSyntaxError)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@agent-eval/site/docs/assets/css/just-the-docs-head-nav.css` at line 1, The
just-the-docs-head-nav stylesheet asset is being generated as a full HTML
document instead of CSS, so fix the build/export step that writes this file and
ensure it emits only valid stylesheet rules. Use the asset target referenced by
just-the-docs-head-nav.css and verify the output matches the other CSS assets in
the same directory, with no HTML head/body markup or embedded page content.
Source: Linters/SAST tools
| @@ -0,0 +1,89 @@ | |||
| <!DOCTYPE html> <html lang="en-US"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=Edge"> <link rel="stylesheet" href="/docs/assets/css/just-the-docs-default.css"> <link rel="stylesheet" href="/docs/assets/css/just-the-docs-head-nav.css" id="jtd-head-nav-stylesheet"> <style id="jtd-nav-activation"> .site-nav > ul.nav-list:first-child > li:not(:nth-child(5)) > a, .site-nav > ul.nav-list:first-child > li > ul > li a { background-image: none; } .site-nav > ul.nav-list:not(:first-child) a, .site-nav li.external a { background-image: none; } .site-nav > ul.nav-list:first-child > li:nth-child(5) > a { font-weight: 600; text-decoration: none; }.site-nav > ul.nav-list:first-child > li:nth-child(5) > button svg { transform: rotate(-90deg); }.site-nav > ul.nav-list:first-child > li.nav-list-item:nth-child(5) > ul.nav-list { display: block; } </style> <script src="/docs/assets/js/vendor/lunr.min.js"></script> <script src="/docs/assets/js/just-the-docs.js"></script> <meta name="viewport" content="width=device-width, initial-scale=1"> <!-- Begin Jekyll SEO tag v2.8.0 --> <title>Configuration | jcode</title> <meta name="generator" content="Jekyll v4.4.1" /> <meta property="og:title" content="Configuration" /> <meta property="og:locale" content="en_US" /> <meta name="description" content="jcode — Your AI Coding Companion. An intelligent coding agent that lives in your terminal." /> <meta property="og:description" content="jcode — Your AI Coding Companion. An intelligent coding agent that lives in your terminal." /> <link rel="canonical" href="/docs/configuration.html" /> <meta property="og:url" content="/docs/configuration.html" /> <meta property="og:site_name" content="jcode" /> <meta property="og:type" content="website" /> <meta name="twitter:card" content="summary" /> <meta property="twitter:title" content="Configuration" /> <script type="application/ld+json"> {"@context":"https://schema.org","@type":"WebPage","description":"jcode — Your AI Coding Companion. An intelligent coding agent that lives in your terminal.","headline":"Configuration","url":"/docs/configuration.html"}</script> <!-- End Jekyll SEO tag --> </head> <body> <a class="skip-to-main" href="#main-content">Skip to main content</a> <svg xmlns="http://www.w3.org/2000/svg" class="d-none"> <symbol id="svg-link" viewBox="0 0 24 24"> <title>Link</title> <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-link"> <path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"></path><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"></path> </svg> </symbol> <symbol id="svg-menu" viewBox="0 0 24 24"> <title>Menu</title> <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-menu"> <line x1="3" y1="12" x2="21" y2="12"></line><line x1="3" y1="6" x2="21" y2="6"></line><line x1="3" y1="18" x2="21" y2="18"></line> </svg> </symbol> <symbol id="svg-arrow-right" viewBox="0 0 24 24"> <title>Expand</title> <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-chevron-right"> <polyline points="9 18 15 12 9 6"></polyline> </svg> </symbol> <!-- Feather. MIT License: https://github.com/feathericons/feather/blob/master/LICENSE --> <symbol id="svg-external-link" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-external-link"> <title id="svg-external-link-title">(external link)</title> <path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"></path><polyline points="15 3 21 3 21 9"></polyline><line x1="10" y1="14" x2="21" y2="3"></line> </symbol> <symbol id="svg-doc" viewBox="0 0 24 24"> <title>Document</title> <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-file"> <path d="M13 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V9z"></path><polyline points="13 2 13 9 20 9"></polyline> </svg> </symbol> <symbol id="svg-search" viewBox="0 0 24 24"> <title>Search</title> <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-search"> <circle cx="11" cy="11" r="8"></circle><line x1="21" y1="21" x2="16.65" y2="16.65"></line> </svg> </symbol> <!-- Bootstrap Icons. MIT License: https://github.com/twbs/icons/blob/main/LICENSE.md --> <symbol id="svg-copy" viewBox="0 0 16 16"> <title>Copy</title> <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-clipboard" viewBox="0 0 16 16"> <path d="M4 1.5H3a2 2 0 0 0-2 2V14a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2V3.5a2 2 0 0 0-2-2h-1v1h1a1 1 0 0 1 1 1V14a1 1 0 0 1-1 1H3a1 1 0 0 1-1-1V3.5a1 1 0 0 1 1-1h1v-1z"/> <path d="M9.5 1a.5.5 0 0 1 .5.5v1a.5.5 0 0 1-.5.5h-3a.5.5 0 0 1-.5-.5v-1a.5.5 0 0 1 .5-.5h3zm-3-1A1.5 1.5 0 0 0 5 1.5v1A1.5 1.5 0 0 0 6.5 4h3A1.5 1.5 0 0 0 11 2.5v-1A1.5 1.5 0 0 0 9.5 0h-3z"/> </svg> </symbol> <symbol id="svg-copied" viewBox="0 0 16 16"> <title>Copied</title> <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-clipboard-check-fill" viewBox="0 0 16 16"> <path d="M6.5 0A1.5 1.5 0 0 0 5 1.5v1A1.5 1.5 0 0 0 6.5 4h3A1.5 1.5 0 0 0 11 2.5v-1A1.5 1.5 0 0 0 9.5 0h-3Zm3 1a.5.5 0 0 1 .5.5v1a.5.5 0 0 1-.5.5h-3a.5.5 0 0 1-.5-.5v-1a.5.5 0 0 1 .5-.5h3Z"/> <path d="M4 1.5H3a2 2 0 0 0-2 2V14a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2V3.5a2 2 0 0 0-2-2h-1v1A2.5 2.5 0 0 1 9.5 5h-3A2.5 2.5 0 0 1 4 2.5v-1Zm6.854 7.354-3 3a.5.5 0 0 1-.708 0l-1.5-1.5a.5.5 0 0 1 .708-.708L7.5 10.793l2.646-2.647a.5.5 0 0 1 .708.708Z"/> </svg> </symbol> </svg> <header class="side-bar"> <div class="site-header"> <a href="/docs/" class="site-title lh-tight"> jcode </a> <button id="menu-button" class="site-button btn-reset" aria-label="Menu" aria-expanded="false"> <svg viewBox="0 0 24 24" class="icon" aria-hidden="true"><use xlink:href="#svg-menu"></use></svg> </button> </div> <nav aria-label="Main" id="site-nav" class="site-nav"> <ul class="nav-list"><li class="nav-list-item"><a href="/docs/get-started.html" class="nav-list-link">Get Started</a></li><li class="nav-list-item"><button class="nav-list-expander btn-reset" aria-label="Overview submenu" aria-expanded="false"> <svg viewBox="0 0 24 24" aria-hidden="true"><use xlink:href="#svg-arrow-right"></use></svg> </button><a href="/docs/overview.html" class="nav-list-link">Overview</a><ul class="nav-list"><li class="nav-list-item"><a href="/docs/overview/models.html" class="nav-list-link">Model Providers & Models</a></li><li class="nav-list-item"><a href="/docs/overview/agent.html" class="nav-list-link">Agent</a></li><li class="nav-list-item"><a href="/docs/overview/subagents.html" class="nav-list-link">Subagents</a></li><li class="nav-list-item"><a href="/docs/overview/agent-teams.html" class="nav-list-link">Agent Teams</a></li><li class="nav-list-item"><a href="/docs/overview/skills.html" class="nav-list-link">Skills</a></li><li class="nav-list-item"><a href="/docs/overview/plan-mode.html" class="nav-list-link">Plan Mode</a></li><li class="nav-list-item"><a href="/docs/overview/ssh.html" class="nav-list-link">SSH & Remote Work</a></li><li class="nav-list-item"><a href="/docs/overview/sessions.html" class="nav-list-link">Sessions & Resume</a></li><li class="nav-list-item"><a href="/docs/overview/context-memory.html" class="nav-list-link">Context & Memory</a></li><li class="nav-list-item"><a href="/docs/overview/mcp.html" class="nav-list-link">MCP Integration</a></li></ul></li><li class="nav-list-item"><button class="nav-list-expander btn-reset" aria-label="Tools submenu" aria-expanded="false"> <svg viewBox="0 0 24 24" aria-hidden="true"><use xlink:href="#svg-arrow-right"></use></svg> </button><a href="/docs/tools.html" class="nav-list-link">Tools</a><ul class="nav-list"><li class="nav-list-item"><a href="/docs/tools/file-tools.html" class="nav-list-link">File Tools</a></li><li class="nav-list-item"><a href="/docs/tools/search-tools.html" class="nav-list-link">Search Tools</a></li><li class="nav-list-item"><a href="/docs/tools/execute.html" class="nav-list-link">Execute</a></li><li class="nav-list-item"><a href="/docs/tools/task-management.html" class="nav-list-link">Task Management</a></li></ul></li><li class="nav-list-item"><a href="/docs/web-interface.html" class="nav-list-link">Web Interface</a></li><li class="nav-list-item"><a href="/docs/configuration.html" class="nav-list-link">Configuration</a></li><li class="nav-list-item"><a href="/docs/commands.html" class="nav-list-link">Commands & Shortcuts</a></li></ul> </nav> <div class="d-md-block d-none site-footer"> This site uses <a href="https://github.com/just-the-docs/just-the-docs">Just the Docs</a>, a documentation theme for Jekyll. </div> </header> <div class="main" id="top"> <div id="main-header" class="main-header"> <div class="search" role="search"> <div class="search-input-wrap"> <input type="text" id="search-input" class="search-input" tabindex="0" placeholder="Search jcode" autocomplete="off"> <label for="search-input" class="search-label"> <span class="sr-only">Search jcode</span> <svg viewBox="0 0 24 24" class="search-icon" aria-hidden="true"><use xlink:href="#svg-search"></use></svg> </label> </div> <div id="search-results" class="search-results"></div> </div> </div> <div class="main-content-wrap"> <div id="main-content" class="main-content"> <main> <h1 id="configuration"> <a href="#configuration" class="anchor-heading" aria-labelledby="configuration"><svg viewBox="0 0 16 16" aria-hidden="true"><use xlink:href="#svg-link"></use></svg></a> Configuration </h1> <p>jcode stores all configuration in a single JSON file at <code class="language-plaintext highlighter-rouge">~/.jcode/config.json</code>. The setup wizard creates this file on first launch.</p> <h2 id="config-file-location"> <a href="#config-file-location" class="anchor-heading" aria-labelledby="config-file-location"><svg viewBox="0 0 16 16" aria-hidden="true"><use xlink:href="#svg-link"></use></svg></a> Config File Location </h2> <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>~/.jcode/ | |||
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
Broken relative link to MCP Integration page.
The mcp_servers section links with <a href="mcp">MCP Integration</a>. Relative to /docs/configuration.html, this resolves to /docs/mcp, but the actual page is at /docs/overview/mcp.html (per the nav links elsewhere in this same file). This link will 404.
🔗 Proposed fix
-<p>MCP server definitions. See <a href="mcp">MCP Integration</a>.</p>
+<p>MCP server definitions. See <a href="/docs/overview/mcp.html">MCP Integration</a>.</p>📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| <!DOCTYPE html> <html lang="en-US"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=Edge"> <link rel="stylesheet" href="/docs/assets/css/just-the-docs-default.css"> <link rel="stylesheet" href="/docs/assets/css/just-the-docs-head-nav.css" id="jtd-head-nav-stylesheet"> <style id="jtd-nav-activation"> .site-nav > ul.nav-list:first-child > li:not(:nth-child(5)) > a, .site-nav > ul.nav-list:first-child > li > ul > li a { background-image: none; } .site-nav > ul.nav-list:not(:first-child) a, .site-nav li.external a { background-image: none; } .site-nav > ul.nav-list:first-child > li:nth-child(5) > a { font-weight: 600; text-decoration: none; }.site-nav > ul.nav-list:first-child > li:nth-child(5) > button svg { transform: rotate(-90deg); }.site-nav > ul.nav-list:first-child > li.nav-list-item:nth-child(5) > ul.nav-list { display: block; } </style> <script src="/docs/assets/js/vendor/lunr.min.js"></script> <script src="/docs/assets/js/just-the-docs.js"></script> <meta name="viewport" content="width=device-width, initial-scale=1"> <!-- Begin Jekyll SEO tag v2.8.0 --> <title>Configuration | jcode</title> <meta name="generator" content="Jekyll v4.4.1" /> <meta property="og:title" content="Configuration" /> <meta property="og:locale" content="en_US" /> <meta name="description" content="jcode — Your AI Coding Companion. An intelligent coding agent that lives in your terminal." /> <meta property="og:description" content="jcode — Your AI Coding Companion. An intelligent coding agent that lives in your terminal." /> <link rel="canonical" href="/docs/configuration.html" /> <meta property="og:url" content="/docs/configuration.html" /> <meta property="og:site_name" content="jcode" /> <meta property="og:type" content="website" /> <meta name="twitter:card" content="summary" /> <meta property="twitter:title" content="Configuration" /> <script type="application/ld+json"> {"@context":"https://schema.org","@type":"WebPage","description":"jcode — Your AI Coding Companion. An intelligent coding agent that lives in your terminal.","headline":"Configuration","url":"/docs/configuration.html"}</script> <!-- End Jekyll SEO tag --> </head> <body> <a class="skip-to-main" href="#main-content">Skip to main content</a> <svg xmlns="http://www.w3.org/2000/svg" class="d-none"> <symbol id="svg-link" viewBox="0 0 24 24"> <title>Link</title> <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-link"> <path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"></path><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"></path> </svg> </symbol> <symbol id="svg-menu" viewBox="0 0 24 24"> <title>Menu</title> <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-menu"> <line x1="3" y1="12" x2="21" y2="12"></line><line x1="3" y1="6" x2="21" y2="6"></line><line x1="3" y1="18" x2="21" y2="18"></line> </svg> </symbol> <symbol id="svg-arrow-right" viewBox="0 0 24 24"> <title>Expand</title> <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-chevron-right"> <polyline points="9 18 15 12 9 6"></polyline> </svg> </symbol> <!-- Feather. MIT License: https://github.com/feathericons/feather/blob/master/LICENSE --> <symbol id="svg-external-link" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-external-link"> <title id="svg-external-link-title">(external link)</title> <path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"></path><polyline points="15 3 21 3 21 9"></polyline><line x1="10" y1="14" x2="21" y2="3"></line> </symbol> <symbol id="svg-doc" viewBox="0 0 24 24"> <title>Document</title> <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-file"> <path d="M13 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V9z"></path><polyline points="13 2 13 9 20 9"></polyline> </svg> </symbol> <symbol id="svg-search" viewBox="0 0 24 24"> <title>Search</title> <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-search"> <circle cx="11" cy="11" r="8"></circle><line x1="21" y1="21" x2="16.65" y2="16.65"></line> </svg> </symbol> <!-- Bootstrap Icons. MIT License: https://github.com/twbs/icons/blob/main/LICENSE.md --> <symbol id="svg-copy" viewBox="0 0 16 16"> <title>Copy</title> <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-clipboard" viewBox="0 0 16 16"> <path d="M4 1.5H3a2 2 0 0 0-2 2V14a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2V3.5a2 2 0 0 0-2-2h-1v1h1a1 1 0 0 1 1 1V14a1 1 0 0 1-1 1H3a1 1 0 0 1-1-1V3.5a1 1 0 0 1 1-1h1v-1z"/> <path d="M9.5 1a.5.5 0 0 1 .5.5v1a.5.5 0 0 1-.5.5h-3a.5.5 0 0 1-.5-.5v-1a.5.5 0 0 1 .5-.5h3zm-3-1A1.5 1.5 0 0 0 5 1.5v1A1.5 1.5 0 0 0 6.5 4h3A1.5 1.5 0 0 0 11 2.5v-1A1.5 1.5 0 0 0 9.5 0h-3z"/> </svg> </symbol> <symbol id="svg-copied" viewBox="0 0 16 16"> <title>Copied</title> <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-clipboard-check-fill" viewBox="0 0 16 16"> <path d="M6.5 0A1.5 1.5 0 0 0 5 1.5v1A1.5 1.5 0 0 0 6.5 4h3A1.5 1.5 0 0 0 11 2.5v-1A1.5 1.5 0 0 0 9.5 0h-3Zm3 1a.5.5 0 0 1 .5.5v1a.5.5 0 0 1-.5.5h-3a.5.5 0 0 1-.5-.5v-1a.5.5 0 0 1 .5-.5h3Z"/> <path d="M4 1.5H3a2 2 0 0 0-2 2V14a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2V3.5a2 2 0 0 0-2-2h-1v1A2.5 2.5 0 0 1 9.5 5h-3A2.5 2.5 0 0 1 4 2.5v-1Zm6.854 7.354-3 3a.5.5 0 0 1-.708 0l-1.5-1.5a.5.5 0 0 1 .708-.708L7.5 10.793l2.646-2.647a.5.5 0 0 1 .708.708Z"/> </svg> </symbol> </svg> <header class="side-bar"> <div class="site-header"> <a href="/docs/" class="site-title lh-tight"> jcode </a> <button id="menu-button" class="site-button btn-reset" aria-label="Menu" aria-expanded="false"> <svg viewBox="0 0 24 24" class="icon" aria-hidden="true"><use xlink:href="#svg-menu"></use></svg> </button> </div> <nav aria-label="Main" id="site-nav" class="site-nav"> <ul class="nav-list"><li class="nav-list-item"><a href="/docs/get-started.html" class="nav-list-link">Get Started</a></li><li class="nav-list-item"><button class="nav-list-expander btn-reset" aria-label="Overview submenu" aria-expanded="false"> <svg viewBox="0 0 24 24" aria-hidden="true"><use xlink:href="#svg-arrow-right"></use></svg> </button><a href="/docs/overview.html" class="nav-list-link">Overview</a><ul class="nav-list"><li class="nav-list-item"><a href="/docs/overview/models.html" class="nav-list-link">Model Providers & Models</a></li><li class="nav-list-item"><a href="/docs/overview/agent.html" class="nav-list-link">Agent</a></li><li class="nav-list-item"><a href="/docs/overview/subagents.html" class="nav-list-link">Subagents</a></li><li class="nav-list-item"><a href="/docs/overview/agent-teams.html" class="nav-list-link">Agent Teams</a></li><li class="nav-list-item"><a href="/docs/overview/skills.html" class="nav-list-link">Skills</a></li><li class="nav-list-item"><a href="/docs/overview/plan-mode.html" class="nav-list-link">Plan Mode</a></li><li class="nav-list-item"><a href="/docs/overview/ssh.html" class="nav-list-link">SSH & Remote Work</a></li><li class="nav-list-item"><a href="/docs/overview/sessions.html" class="nav-list-link">Sessions & Resume</a></li><li class="nav-list-item"><a href="/docs/overview/context-memory.html" class="nav-list-link">Context & Memory</a></li><li class="nav-list-item"><a href="/docs/overview/mcp.html" class="nav-list-link">MCP Integration</a></li></ul></li><li class="nav-list-item"><button class="nav-list-expander btn-reset" aria-label="Tools submenu" aria-expanded="false"> <svg viewBox="0 0 24 24" aria-hidden="true"><use xlink:href="#svg-arrow-right"></use></svg> </button><a href="/docs/tools.html" class="nav-list-link">Tools</a><ul class="nav-list"><li class="nav-list-item"><a href="/docs/tools/file-tools.html" class="nav-list-link">File Tools</a></li><li class="nav-list-item"><a href="/docs/tools/search-tools.html" class="nav-list-link">Search Tools</a></li><li class="nav-list-item"><a href="/docs/tools/execute.html" class="nav-list-link">Execute</a></li><li class="nav-list-item"><a href="/docs/tools/task-management.html" class="nav-list-link">Task Management</a></li></ul></li><li class="nav-list-item"><a href="/docs/web-interface.html" class="nav-list-link">Web Interface</a></li><li class="nav-list-item"><a href="/docs/configuration.html" class="nav-list-link">Configuration</a></li><li class="nav-list-item"><a href="/docs/commands.html" class="nav-list-link">Commands & Shortcuts</a></li></ul> </nav> <div class="d-md-block d-none site-footer"> This site uses <a href="https://github.com/just-the-docs/just-the-docs">Just the Docs</a>, a documentation theme for Jekyll. </div> </header> <div class="main" id="top"> <div id="main-header" class="main-header"> <div class="search" role="search"> <div class="search-input-wrap"> <input type="text" id="search-input" class="search-input" tabindex="0" placeholder="Search jcode" autocomplete="off"> <label for="search-input" class="search-label"> <span class="sr-only">Search jcode</span> <svg viewBox="0 0 24 24" class="search-icon" aria-hidden="true"><use xlink:href="#svg-search"></use></svg> </label> </div> <div id="search-results" class="search-results"></div> </div> </div> <div class="main-content-wrap"> <div id="main-content" class="main-content"> <main> <h1 id="configuration"> <a href="#configuration" class="anchor-heading" aria-labelledby="configuration"><svg viewBox="0 0 16 16" aria-hidden="true"><use xlink:href="#svg-link"></use></svg></a> Configuration </h1> <p>jcode stores all configuration in a single JSON file at <code class="language-plaintext highlighter-rouge">~/.jcode/config.json</code>. The setup wizard creates this file on first launch.</p> <h2 id="config-file-location"> <a href="#config-file-location" class="anchor-heading" aria-labelledby="config-file-location"><svg viewBox="0 0 16 16" aria-hidden="true"><use xlink:href="#svg-link"></use></svg></a> Config File Location </h2> <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>~/.jcode/ | |
| <p>MCP server definitions. See <a href="/docs/overview/mcp.html">MCP Integration</a>.</p> |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@agent-eval/site/docs/configuration.html` at line 1, The Configuration page
has a broken relative link for MCP Integration in the `mcp_servers` section.
Update the anchor in the configuration docs to point to the actual MCP page path
used elsewhere in the file, matching the `Overview`/`MCP Integration` nav
target. Use the surrounding `mcp_servers` documentation block and the `MCP
Integration` link text to locate and replace the incorrect href so it resolves
correctly from `configuration.html`.
| @@ -0,0 +1,19 @@ | |||
| <!DOCTYPE html> <html lang="en-US"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=Edge"> <link rel="stylesheet" href="/docs/assets/css/just-the-docs-default.css"> <link rel="stylesheet" href="/docs/assets/css/just-the-docs-head-nav.css" id="jtd-head-nav-stylesheet"> <style id="jtd-nav-activation"> .site-nav > ul.nav-list:first-child > li:not(:nth-child(1)) > a, .site-nav > ul.nav-list:first-child > li > ul > li a { background-image: none; } .site-nav > ul.nav-list:not(:first-child) a, .site-nav li.external a { background-image: none; } .site-nav > ul.nav-list:first-child > li:nth-child(1) > a { font-weight: 600; text-decoration: none; }.site-nav > ul.nav-list:first-child > li:nth-child(1) > button svg { transform: rotate(-90deg); }.site-nav > ul.nav-list:first-child > li.nav-list-item:nth-child(1) > ul.nav-list { display: block; } </style> <script src="/docs/assets/js/vendor/lunr.min.js"></script> <script src="/docs/assets/js/just-the-docs.js"></script> <meta name="viewport" content="width=device-width, initial-scale=1"> <!-- Begin Jekyll SEO tag v2.8.0 --> <title>Get Started | jcode</title> <meta name="generator" content="Jekyll v4.4.1" /> <meta property="og:title" content="Get Started" /> <meta property="og:locale" content="en_US" /> <meta name="description" content="jcode — Your AI Coding Companion. An intelligent coding agent that lives in your terminal." /> <meta property="og:description" content="jcode — Your AI Coding Companion. An intelligent coding agent that lives in your terminal." /> <link rel="canonical" href="/docs/get-started.html" /> <meta property="og:url" content="/docs/get-started.html" /> <meta property="og:site_name" content="jcode" /> <meta property="og:type" content="website" /> <meta name="twitter:card" content="summary" /> <meta property="twitter:title" content="Get Started" /> <script type="application/ld+json"> {"@context":"https://schema.org","@type":"WebPage","description":"jcode — Your AI Coding Companion. An intelligent coding agent that lives in your terminal.","headline":"Get Started","url":"/docs/get-started.html"}</script> <!-- End Jekyll SEO tag --> </head> <body> <a class="skip-to-main" href="#main-content">Skip to main content</a> <svg xmlns="http://www.w3.org/2000/svg" class="d-none"> <symbol id="svg-link" viewBox="0 0 24 24"> <title>Link</title> <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-link"> <path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"></path><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"></path> </svg> </symbol> <symbol id="svg-menu" viewBox="0 0 24 24"> <title>Menu</title> <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-menu"> <line x1="3" y1="12" x2="21" y2="12"></line><line x1="3" y1="6" x2="21" y2="6"></line><line x1="3" y1="18" x2="21" y2="18"></line> </svg> </symbol> <symbol id="svg-arrow-right" viewBox="0 0 24 24"> <title>Expand</title> <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-chevron-right"> <polyline points="9 18 15 12 9 6"></polyline> </svg> </symbol> <!-- Feather. MIT License: https://github.com/feathericons/feather/blob/master/LICENSE --> <symbol id="svg-external-link" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-external-link"> <title id="svg-external-link-title">(external link)</title> <path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"></path><polyline points="15 3 21 3 21 9"></polyline><line x1="10" y1="14" x2="21" y2="3"></line> </symbol> <symbol id="svg-doc" viewBox="0 0 24 24"> <title>Document</title> <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-file"> <path d="M13 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V9z"></path><polyline points="13 2 13 9 20 9"></polyline> </svg> </symbol> <symbol id="svg-search" viewBox="0 0 24 24"> <title>Search</title> <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-search"> <circle cx="11" cy="11" r="8"></circle><line x1="21" y1="21" x2="16.65" y2="16.65"></line> </svg> </symbol> <!-- Bootstrap Icons. MIT License: https://github.com/twbs/icons/blob/main/LICENSE.md --> <symbol id="svg-copy" viewBox="0 0 16 16"> <title>Copy</title> <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-clipboard" viewBox="0 0 16 16"> <path d="M4 1.5H3a2 2 0 0 0-2 2V14a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2V3.5a2 2 0 0 0-2-2h-1v1h1a1 1 0 0 1 1 1V14a1 1 0 0 1-1 1H3a1 1 0 0 1-1-1V3.5a1 1 0 0 1 1-1h1v-1z"/> <path d="M9.5 1a.5.5 0 0 1 .5.5v1a.5.5 0 0 1-.5.5h-3a.5.5 0 0 1-.5-.5v-1a.5.5 0 0 1 .5-.5h3zm-3-1A1.5 1.5 0 0 0 5 1.5v1A1.5 1.5 0 0 0 6.5 4h3A1.5 1.5 0 0 0 11 2.5v-1A1.5 1.5 0 0 0 9.5 0h-3z"/> </svg> </symbol> <symbol id="svg-copied" viewBox="0 0 16 16"> <title>Copied</title> <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-clipboard-check-fill" viewBox="0 0 16 16"> <path d="M6.5 0A1.5 1.5 0 0 0 5 1.5v1A1.5 1.5 0 0 0 6.5 4h3A1.5 1.5 0 0 0 11 2.5v-1A1.5 1.5 0 0 0 9.5 0h-3Zm3 1a.5.5 0 0 1 .5.5v1a.5.5 0 0 1-.5.5h-3a.5.5 0 0 1-.5-.5v-1a.5.5 0 0 1 .5-.5h3Z"/> <path d="M4 1.5H3a2 2 0 0 0-2 2V14a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2V3.5a2 2 0 0 0-2-2h-1v1A2.5 2.5 0 0 1 9.5 5h-3A2.5 2.5 0 0 1 4 2.5v-1Zm6.854 7.354-3 3a.5.5 0 0 1-.708 0l-1.5-1.5a.5.5 0 0 1 .708-.708L7.5 10.793l2.646-2.647a.5.5 0 0 1 .708.708Z"/> </svg> </symbol> </svg> <header class="side-bar"> <div class="site-header"> <a href="/docs/" class="site-title lh-tight"> jcode </a> <button id="menu-button" class="site-button btn-reset" aria-label="Menu" aria-expanded="false"> <svg viewBox="0 0 24 24" class="icon" aria-hidden="true"><use xlink:href="#svg-menu"></use></svg> </button> </div> <nav aria-label="Main" id="site-nav" class="site-nav"> <ul class="nav-list"><li class="nav-list-item"><a href="/docs/get-started.html" class="nav-list-link">Get Started</a></li><li class="nav-list-item"><button class="nav-list-expander btn-reset" aria-label="Overview submenu" aria-expanded="false"> <svg viewBox="0 0 24 24" aria-hidden="true"><use xlink:href="#svg-arrow-right"></use></svg> </button><a href="/docs/overview.html" class="nav-list-link">Overview</a><ul class="nav-list"><li class="nav-list-item"><a href="/docs/overview/models.html" class="nav-list-link">Model Providers & Models</a></li><li class="nav-list-item"><a href="/docs/overview/agent.html" class="nav-list-link">Agent</a></li><li class="nav-list-item"><a href="/docs/overview/subagents.html" class="nav-list-link">Subagents</a></li><li class="nav-list-item"><a href="/docs/overview/agent-teams.html" class="nav-list-link">Agent Teams</a></li><li class="nav-list-item"><a href="/docs/overview/skills.html" class="nav-list-link">Skills</a></li><li class="nav-list-item"><a href="/docs/overview/plan-mode.html" class="nav-list-link">Plan Mode</a></li><li class="nav-list-item"><a href="/docs/overview/ssh.html" class="nav-list-link">SSH & Remote Work</a></li><li class="nav-list-item"><a href="/docs/overview/sessions.html" class="nav-list-link">Sessions & Resume</a></li><li class="nav-list-item"><a href="/docs/overview/context-memory.html" class="nav-list-link">Context & Memory</a></li><li class="nav-list-item"><a href="/docs/overview/mcp.html" class="nav-list-link">MCP Integration</a></li></ul></li><li class="nav-list-item"><button class="nav-list-expander btn-reset" aria-label="Tools submenu" aria-expanded="false"> <svg viewBox="0 0 24 24" aria-hidden="true"><use xlink:href="#svg-arrow-right"></use></svg> </button><a href="/docs/tools.html" class="nav-list-link">Tools</a><ul class="nav-list"><li class="nav-list-item"><a href="/docs/tools/file-tools.html" class="nav-list-link">File Tools</a></li><li class="nav-list-item"><a href="/docs/tools/search-tools.html" class="nav-list-link">Search Tools</a></li><li class="nav-list-item"><a href="/docs/tools/execute.html" class="nav-list-link">Execute</a></li><li class="nav-list-item"><a href="/docs/tools/task-management.html" class="nav-list-link">Task Management</a></li></ul></li><li class="nav-list-item"><a href="/docs/web-interface.html" class="nav-list-link">Web Interface</a></li><li class="nav-list-item"><a href="/docs/configuration.html" class="nav-list-link">Configuration</a></li><li class="nav-list-item"><a href="/docs/commands.html" class="nav-list-link">Commands & Shortcuts</a></li></ul> </nav> <div class="d-md-block d-none site-footer"> This site uses <a href="https://github.com/just-the-docs/just-the-docs">Just the Docs</a>, a documentation theme for Jekyll. </div> </header> <div class="main" id="top"> <div id="main-header" class="main-header"> <div class="search" role="search"> <div class="search-input-wrap"> <input type="text" id="search-input" class="search-input" tabindex="0" placeholder="Search jcode" autocomplete="off"> <label for="search-input" class="search-label"> <span class="sr-only">Search jcode</span> <svg viewBox="0 0 24 24" class="search-icon" aria-hidden="true"><use xlink:href="#svg-search"></use></svg> </label> </div> <div id="search-results" class="search-results"></div> </div> </div> <div class="main-content-wrap"> <div id="main-content" class="main-content"> <main> <h1 id="get-started"> <a href="#get-started" class="anchor-heading" aria-labelledby="get-started"><svg viewBox="0 0 16 16" aria-hidden="true"><use xlink:href="#svg-link"></use></svg></a> Get Started </h1> <h2 id="prerequisites"> <a href="#prerequisites" class="anchor-heading" aria-labelledby="prerequisites"><svg viewBox="0 0 16 16" aria-hidden="true"><use xlink:href="#svg-link"></use></svg></a> Prerequisites </h2> <ul> <li><strong>Go 1.22+</strong> installed</li> <li>An <strong>API key</strong> from an OpenAI-compatible provider (OpenAI, Anthropic, Azure, etc.)</li> </ul> <h2 id="install"> <a href="#install" class="anchor-heading" aria-labelledby="install"><svg viewBox="0 0 16 16" aria-hidden="true"><use xlink:href="#svg-link"></use></svg></a> Install </h2> <div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>go <span class="nb">install </span>github.com/cnjack/docs/cmd/jcode@latest | |||
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
Incorrect Go module path in install instructions.
go install github.com/cnjack/docs/cmd/jcode@latest references the cnjack/docs repository, but the actual repository (per the git clone instruction later in the same file and the PR URL) is cnjack/jcode. This will fail for anyone following the docs.
🔗 Proposed fix
-go install github.com/cnjack/docs/cmd/jcode@latest
+go install github.com/cnjack/jcode/cmd/jcode@latest📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| <!DOCTYPE html> <html lang="en-US"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=Edge"> <link rel="stylesheet" href="/docs/assets/css/just-the-docs-default.css"> <link rel="stylesheet" href="/docs/assets/css/just-the-docs-head-nav.css" id="jtd-head-nav-stylesheet"> <style id="jtd-nav-activation"> .site-nav > ul.nav-list:first-child > li:not(:nth-child(1)) > a, .site-nav > ul.nav-list:first-child > li > ul > li a { background-image: none; } .site-nav > ul.nav-list:not(:first-child) a, .site-nav li.external a { background-image: none; } .site-nav > ul.nav-list:first-child > li:nth-child(1) > a { font-weight: 600; text-decoration: none; }.site-nav > ul.nav-list:first-child > li:nth-child(1) > button svg { transform: rotate(-90deg); }.site-nav > ul.nav-list:first-child > li.nav-list-item:nth-child(1) > ul.nav-list { display: block; } </style> <script src="/docs/assets/js/vendor/lunr.min.js"></script> <script src="/docs/assets/js/just-the-docs.js"></script> <meta name="viewport" content="width=device-width, initial-scale=1"> <!-- Begin Jekyll SEO tag v2.8.0 --> <title>Get Started | jcode</title> <meta name="generator" content="Jekyll v4.4.1" /> <meta property="og:title" content="Get Started" /> <meta property="og:locale" content="en_US" /> <meta name="description" content="jcode — Your AI Coding Companion. An intelligent coding agent that lives in your terminal." /> <meta property="og:description" content="jcode — Your AI Coding Companion. An intelligent coding agent that lives in your terminal." /> <link rel="canonical" href="/docs/get-started.html" /> <meta property="og:url" content="/docs/get-started.html" /> <meta property="og:site_name" content="jcode" /> <meta property="og:type" content="website" /> <meta name="twitter:card" content="summary" /> <meta property="twitter:title" content="Get Started" /> <script type="application/ld+json"> {"@context":"https://schema.org","@type":"WebPage","description":"jcode — Your AI Coding Companion. An intelligent coding agent that lives in your terminal.","headline":"Get Started","url":"/docs/get-started.html"}</script> <!-- End Jekyll SEO tag --> </head> <body> <a class="skip-to-main" href="#main-content">Skip to main content</a> <svg xmlns="http://www.w3.org/2000/svg" class="d-none"> <symbol id="svg-link" viewBox="0 0 24 24"> <title>Link</title> <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-link"> <path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"></path><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"></path> </svg> </symbol> <symbol id="svg-menu" viewBox="0 0 24 24"> <title>Menu</title> <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-menu"> <line x1="3" y1="12" x2="21" y2="12"></line><line x1="3" y1="6" x2="21" y2="6"></line><line x1="3" y1="18" x2="21" y2="18"></line> </svg> </symbol> <symbol id="svg-arrow-right" viewBox="0 0 24 24"> <title>Expand</title> <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-chevron-right"> <polyline points="9 18 15 12 9 6"></polyline> </svg> </symbol> <!-- Feather. MIT License: https://github.com/feathericons/feather/blob/master/LICENSE --> <symbol id="svg-external-link" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-external-link"> <title id="svg-external-link-title">(external link)</title> <path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"></path><polyline points="15 3 21 3 21 9"></polyline><line x1="10" y1="14" x2="21" y2="3"></line> </symbol> <symbol id="svg-doc" viewBox="0 0 24 24"> <title>Document</title> <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-file"> <path d="M13 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V9z"></path><polyline points="13 2 13 9 20 9"></polyline> </svg> </symbol> <symbol id="svg-search" viewBox="0 0 24 24"> <title>Search</title> <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-search"> <circle cx="11" cy="11" r="8"></circle><line x1="21" y1="21" x2="16.65" y2="16.65"></line> </svg> </symbol> <!-- Bootstrap Icons. MIT License: https://github.com/twbs/icons/blob/main/LICENSE.md --> <symbol id="svg-copy" viewBox="0 0 16 16"> <title>Copy</title> <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-clipboard" viewBox="0 0 16 16"> <path d="M4 1.5H3a2 2 0 0 0-2 2V14a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2V3.5a2 2 0 0 0-2-2h-1v1h1a1 1 0 0 1 1 1V14a1 1 0 0 1-1 1H3a1 1 0 0 1-1-1V3.5a1 1 0 0 1 1-1h1v-1z"/> <path d="M9.5 1a.5.5 0 0 1 .5.5v1a.5.5 0 0 1-.5.5h-3a.5.5 0 0 1-.5-.5v-1a.5.5 0 0 1 .5-.5h3zm-3-1A1.5 1.5 0 0 0 5 1.5v1A1.5 1.5 0 0 0 6.5 4h3A1.5 1.5 0 0 0 11 2.5v-1A1.5 1.5 0 0 0 9.5 0h-3z"/> </svg> </symbol> <symbol id="svg-copied" viewBox="0 0 16 16"> <title>Copied</title> <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-clipboard-check-fill" viewBox="0 0 16 16"> <path d="M6.5 0A1.5 1.5 0 0 0 5 1.5v1A1.5 1.5 0 0 0 6.5 4h3A1.5 1.5 0 0 0 11 2.5v-1A1.5 1.5 0 0 0 9.5 0h-3Zm3 1a.5.5 0 0 1 .5.5v1a.5.5 0 0 1-.5.5h-3a.5.5 0 0 1-.5-.5v-1a.5.5 0 0 1 .5-.5h3Z"/> <path d="M4 1.5H3a2 2 0 0 0-2 2V14a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2V3.5a2 2 0 0 0-2-2h-1v1A2.5 2.5 0 0 1 9.5 5h-3A2.5 2.5 0 0 1 4 2.5v-1Zm6.854 7.354-3 3a.5.5 0 0 1-.708 0l-1.5-1.5a.5.5 0 0 1 .708-.708L7.5 10.793l2.646-2.647a.5.5 0 0 1 .708.708Z"/> </svg> </symbol> </svg> <header class="side-bar"> <div class="site-header"> <a href="/docs/" class="site-title lh-tight"> jcode </a> <button id="menu-button" class="site-button btn-reset" aria-label="Menu" aria-expanded="false"> <svg viewBox="0 0 24 24" class="icon" aria-hidden="true"><use xlink:href="#svg-menu"></use></svg> </button> </div> <nav aria-label="Main" id="site-nav" class="site-nav"> <ul class="nav-list"><li class="nav-list-item"><a href="/docs/get-started.html" class="nav-list-link">Get Started</a></li><li class="nav-list-item"><button class="nav-list-expander btn-reset" aria-label="Overview submenu" aria-expanded="false"> <svg viewBox="0 0 24 24" aria-hidden="true"><use xlink:href="#svg-arrow-right"></use></svg> </button><a href="/docs/overview.html" class="nav-list-link">Overview</a><ul class="nav-list"><li class="nav-list-item"><a href="/docs/overview/models.html" class="nav-list-link">Model Providers & Models</a></li><li class="nav-list-item"><a href="/docs/overview/agent.html" class="nav-list-link">Agent</a></li><li class="nav-list-item"><a href="/docs/overview/subagents.html" class="nav-list-link">Subagents</a></li><li class="nav-list-item"><a href="/docs/overview/agent-teams.html" class="nav-list-link">Agent Teams</a></li><li class="nav-list-item"><a href="/docs/overview/skills.html" class="nav-list-link">Skills</a></li><li class="nav-list-item"><a href="/docs/overview/plan-mode.html" class="nav-list-link">Plan Mode</a></li><li class="nav-list-item"><a href="/docs/overview/ssh.html" class="nav-list-link">SSH & Remote Work</a></li><li class="nav-list-item"><a href="/docs/overview/sessions.html" class="nav-list-link">Sessions & Resume</a></li><li class="nav-list-item"><a href="/docs/overview/context-memory.html" class="nav-list-link">Context & Memory</a></li><li class="nav-list-item"><a href="/docs/overview/mcp.html" class="nav-list-link">MCP Integration</a></li></ul></li><li class="nav-list-item"><button class="nav-list-expander btn-reset" aria-label="Tools submenu" aria-expanded="false"> <svg viewBox="0 0 24 24" aria-hidden="true"><use xlink:href="#svg-arrow-right"></use></svg> </button><a href="/docs/tools.html" class="nav-list-link">Tools</a><ul class="nav-list"><li class="nav-list-item"><a href="/docs/tools/file-tools.html" class="nav-list-link">File Tools</a></li><li class="nav-list-item"><a href="/docs/tools/search-tools.html" class="nav-list-link">Search Tools</a></li><li class="nav-list-item"><a href="/docs/tools/execute.html" class="nav-list-link">Execute</a></li><li class="nav-list-item"><a href="/docs/tools/task-management.html" class="nav-list-link">Task Management</a></li></ul></li><li class="nav-list-item"><a href="/docs/web-interface.html" class="nav-list-link">Web Interface</a></li><li class="nav-list-item"><a href="/docs/configuration.html" class="nav-list-link">Configuration</a></li><li class="nav-list-item"><a href="/docs/commands.html" class="nav-list-link">Commands & Shortcuts</a></li></ul> </nav> <div class="d-md-block d-none site-footer"> This site uses <a href="https://github.com/just-the-docs/just-the-docs">Just the Docs</a>, a documentation theme for Jekyll. </div> </header> <div class="main" id="top"> <div id="main-header" class="main-header"> <div class="search" role="search"> <div class="search-input-wrap"> <input type="text" id="search-input" class="search-input" tabindex="0" placeholder="Search jcode" autocomplete="off"> <label for="search-input" class="search-label"> <span class="sr-only">Search jcode</span> <svg viewBox="0 0 24 24" class="search-icon" aria-hidden="true"><use xlink:href="#svg-search"></use></svg> </label> </div> <div id="search-results" class="search-results"></div> </div> </div> <div class="main-content-wrap"> <div id="main-content" class="main-content"> <main> <h1 id="get-started"> <a href="#get-started" class="anchor-heading" aria-labelledby="get-started"><svg viewBox="0 0 16 16" aria-hidden="true"><use xlink:href="#svg-link"></use></svg></a> Get Started </h1> <h2 id="prerequisites"> <a href="#prerequisites" class="anchor-heading" aria-labelledby="prerequisites"><svg viewBox="0 0 16 16" aria-hidden="true"><use xlink:href="#svg-link"></use></svg></a> Prerequisites </h2> <ul> <li><strong>Go 1.22+</strong> installed</li> <li>An <strong>API key</strong> from an OpenAI-compatible provider (OpenAI, Anthropic, Azure, etc.)</li> </ul> <h2 id="install"> <a href="#install" class="anchor-heading" aria-labelledby="install"><svg viewBox="0 0 16 16" aria-hidden="true"><use xlink:href="#svg-link"></use></svg></a> Install </h2> <div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>go <span class="nb">install </span>github.com/cnjack/docs/cmd/jcode@latest | |
| go <span class="nb">install </span>github.com/cnjack/jcode/cmd/jcode@latest |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@agent-eval/site/docs/get-started.html` at line 1, The install command in the
Get Started docs uses the wrong Go module path, pointing to cnjack/docs instead
of the actual jcode repository. Update the install instruction in the Get
Started page to use the same repository path as the later git clone guidance, so
the command resolves the correct module for jcode.
| <a href="docs/">Documentation</a> · | ||
| <a href="index.html">Home</a> | ||
| </p> | ||
| <p style="margin-top:10px;font-size:.85rem;color:var(--muted);">津ICP备13004281号-4</p> |
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win
Stray/unrelated ICP registration footer text.
津ICP备13004281号-4 in the footer looks like leftover boilerplate unrelated to this repo (jcode/GitHub project), not an actual registration for this site. If this is placeholder/copied content, remove it before publishing to avoid misleading legal/compliance info.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@agent-eval/site/showcase.html` at line 61, The footer contains stray ICP
registration boilerplate that appears unrelated to this site. Remove the
hardcoded ICP text from the footer content in the showcase page markup so only
relevant project/footer information remains, and keep the affected footer
element consistent with the rest of the page structure.
| def build_home(home_dir: Path, model_id: str, max_iter: int): | ||
| (home_dir / ".jcode" / "cache").mkdir(parents=True, exist_ok=True) | ||
| cfg = json.loads(REAL_CFG.read_text()) | ||
| provs = cfg.get("providers") or cfg.get("models") or {} | ||
| out = { | ||
| "providers": provs, | ||
| "model": model_id, | ||
| "auto_approve": True, | ||
| "default_mode": "full_access", | ||
| "max_iterations": max_iter, | ||
| } | ||
| (home_dir / ".jcode" / "config.json").write_text(json.dumps(out, indent=2)) | ||
| if REAL_CACHE.exists(): | ||
| shutil.copy(REAL_CACHE, home_dir / ".jcode" / "cache" / "models_dev.json") | ||
| if REAL_MODELSTATE.exists(): | ||
| shutil.copy(REAL_MODELSTATE, home_dir / ".jcode" / "model_state.json") |
There was a problem hiding this comment.
🔒 Security & Privacy | 🟠 Major | ⚡ Quick win
Live provider API keys are copied into every per-run HOME and retained post-run.
build_home copies the real config's providers (i.e., live API keys per the README) into each throwaway HOME. _prune_home (Line 296) explicitly keeps config.json, so those live credentials persist on disk in every run directory produced by a sweep (potentially dozens per model×tier). While runs/ is git-ignored, this still multiplies the exposure surface of live secrets across many directories that could end up in backups, debug archives, or shared for troubleshooting. Since downstream consumers (analyze.py/report.py) only need usage, sessions, and debug.log, consider redacting the provider credentials from the persisted config.json (or dropping it) once a run completes.
🔒 Proposed fix: redact credentials before pruning
def _prune_home(home_dir: Path):
keep = {"usage", "sessions", "debug.log", "config.json"}
jc = home_dir / ".jcode"
if not jc.exists():
return
+ cfg_path = jc / "config.json"
+ if cfg_path.exists():
+ try:
+ cfg = json.loads(cfg_path.read_text())
+ cfg["providers"] = "REDACTED"
+ cfg_path.write_text(json.dumps(cfg, indent=2))
+ except Exception:
+ pass
for child in jc.iterdir():
if child.name not in keep:🧰 Tools
🪛 ast-grep (0.44.0)
[info] 71-71: use jsonify instead of json.dumps for JSON output
Context: json.dumps(out, indent=2)
Note: [CWE-116] Improper Encoding or Escaping of Output.
(use-jsonify)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@agent-eval/suite/orchestrate.py` around lines 61 - 76, The per-run HOME setup
is persisting live provider credentials in config.json via build_home, and
_prune_home is keeping that file after the run. Update build_home to redact or
omit the providers block when writing the run-local config, or add a post-run
cleanup step in _prune_home to strip secrets before preserving config.json. Keep
only the data needed by analyze.py and report.py (usage, sessions, debug.log),
and ensure the final persisted config no longer contains API keys.
Summary by CodeRabbit
New Features
Documentation