Skip to content

feat(agent): add Gemini CLI as an install target#236

Open
Tasfia-17 wants to merge 4 commits into
TestSprite:mainfrom
Tasfia-17:feat/agent-gemini
Open

feat(agent): add Gemini CLI as an install target#236
Tasfia-17 wants to merge 4 commits into
TestSprite:mainfrom
Tasfia-17:feat/agent-gemini

Conversation

@Tasfia-17

@Tasfia-17 Tasfia-17 commented Jul 10, 2026

Copy link
Copy Markdown
Contributor

Summary

CONTRIBUTING.md explicitly lists gemini as an accepted, in-progress
target with no existing PR. This adds it.

Gemini CLI reads project-level instructions from a GEMINI.md file in
the repo root, loaded at the start of every session (always-on, no
on-demand mode). Because all installed skills share a single root file,
the target uses managed-section mode -- the same approach as the
codex/AGENTS.md target -- writing only a sentinel-delimited section so
existing user content in GEMINI.md is never clobbered.

Changes

  • src/lib/agent-targets.ts -- Added gemini to AgentTarget union,
    GEMINI.md case in pathFor, and a gemini entry in TARGETS using
    managed-section mode.
  • src/lib/agent-targets.test.ts -- Updated key count, experimental
    status, managed-section assertions, and a dedicated
    renderForTarget("gemini") describe block.
  • src/commands/agent.ts -- Updated command description and --target
    help text to include gemini.
  • src/commands/agent.test.ts -- Updated runList row count to reflect
    the new target.
  • test/e2e/agent-install.e2e.test.ts -- Updated matrix guard, added
    gemini content assertions, added dedicated GEMINI.md managed-section
    test.
  • test/e2e/setup.e2e.test.ts -- Updated matrix guard.
  • test/__snapshots__/help.snapshot.test.ts.snap -- Updated 4 snapshots.

Design decisions

  • managed-section over own-file: both testsprite-verify and
    testsprite-onboard resolve to the same GEMINI.md path. Using
    own-file mode causes a conflict error on the second skill write.
    managed-section aggregates all skills into one sentinel-delimited
    block, consistent with how codex handles AGENTS.md.
  • No custom frontmatter: GEMINI.md is plain Markdown. The wrap function
    is a no-op, matching codex.

Tests

All 1865 tests pass. Coverage stays above 80%.

Closes #235

Summary by CodeRabbit

  • New Features
    • Added Gemini as a supported agent target; generates GEMINI.md as plain Markdown (no YAML/frontmatter).
    • Supports managed-section installs for Gemini, updating only the managed block while preserving surrounding user content.
  • Bug Fixes
    • Improved recognition of legacy managed-section markers for correct replace/append/corrupt status.
  • Documentation
    • Updated agent CLI help text to include Gemini and clarify managed-section behavior for codex/gemini.
  • Tests
    • Expanded unit and end-to-end coverage for Gemini rendering, install verification, idempotency, and listing output.

@coderabbitai

coderabbitai Bot commented Jul 10, 2026

Copy link
Copy Markdown

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

Walkthrough

The CLI adds Gemini as a managed-section target writing to GEMINI.md, supports legacy managed-section markers, updates CLI help and Copilot rendering configuration, and expands unit and end-to-end coverage.

Changes

Gemini agent target

Layer / File(s) Summary
Target registry and managed markers
src/lib/agent-targets.ts
Registers Gemini at GEMINI.md with plain Markdown managed sections and preserves legacy marker recognition.
Managed-section classification and CLI contracts
src/commands/agent.ts
Recognizes current and legacy begin markers and updates help text for Gemini and managed-section replacement behavior.
Rendering, installation, and coverage
src/lib/agent-targets.test.ts, src/commands/agent.test.ts, test/e2e/agent-install.e2e.test.ts, test/e2e/setup.e2e.test.ts
Validates Gemini rendering, managed-section idempotency, content preservation, expanded target counts, and matrix coverage.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Sequence Diagram(s)

sequenceDiagram
  participant CLI
  participant TARGETS
  participant pathFor
  participant GEMINImd
  CLI->>TARGETS: select gemini target
  TARGETS->>pathFor: resolve skill path
  pathFor-->>CLI: return GEMINI.md
  CLI->>GEMINImd: write managed Markdown section
Loading

Possibly related PRs

Suggested reviewers: ruili-testsprite

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly states the main change: adding Gemini CLI as an install target.
Linked Issues check ✅ Passed The PR adds gemini support, writes to GEMINI.md in managed-section mode, preserves user content, and supports install/setup commands.
Out of Scope Changes check ✅ Passed The changed tests, help text, and sentinel compatibility updates all support Gemini target installation.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 4

🤖 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 `@src/commands/agent.ts`:
- Around line 1073-1075: Update the --force option description in the agent
command to document that both Gemini and Codex use managed sections, while
explicitly preserving the guarantee that user content outside the
managed-section sentinels is never overwritten.

In `@src/lib/agent-targets.ts`:
- Around line 254-276: Update the shared managed-section sentinel used by the
managed-section writer to a target-neutral label instead of “testsprite agent
install codex,” while preserving recognition of the existing Codex marker for
backward compatibility. Locate the sentinel constants and managed-section
parsing/writing logic, and ensure new GEMINI.md and Codex files use the neutral
marker without breaking cleanup or updates of legacy Codex files.

In `@test/e2e/agent-install.e2e.test.ts`:
- Around line 275-304: Add deterministic offline coverage around the existing
Gemini installation test by pre-populating GEMINI.md with user content before
installing both skills, then rerun installation and assert the user content
remains unchanged, exactly one MANAGED_SECTION_BEGIN/END pair exists, and only
the content between those sentinels is replaced. Reuse the existing runCli,
freshTmpDir, TARGETS, and sentinel constants, and compare the preserved
prefix/suffix or expected managed section across runs.
- Around line 275-280: The test `gemini GEMINI.md contains ONE managed section
with verify and onboard content` ignores the CLI result. Capture the `runCli`
return value, assert a zero exit status, parse `stdout` as JSON and validate the
expected response, and assert diagnostics are emitted only on `stderr` before
reading the generated file.
🪄 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: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 4af5ce26-4c1b-4c2a-88ec-1d663051e8a7

📥 Commits

Reviewing files that changed from the base of the PR and between 60d55e4 and 54df468.

⛔ Files ignored due to path filters (1)
  • test/__snapshots__/help.snapshot.test.ts.snap is excluded by !**/*.snap, !**/*.snap
📒 Files selected for processing (6)
  • src/commands/agent.test.ts
  • src/commands/agent.ts
  • src/lib/agent-targets.test.ts
  • src/lib/agent-targets.ts
  • test/e2e/agent-install.e2e.test.ts
  • test/e2e/setup.e2e.test.ts

Comment thread src/commands/agent.ts
Comment thread src/lib/agent-targets.ts
Comment on lines +275 to +280
it('gemini GEMINI.md contains ONE managed section with verify and onboard content', () => {
const tmpDir = freshTmpDir();
runCli(['agent', 'install', '--target=gemini', '--dir', tmpDir, '--output', 'json']);

const filePath = join(tmpDir, TARGETS.gemini.path);
const content = readFileSync(filePath, 'utf8');

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Assert the CLI exit code and JSON output.

The runCli result is ignored, so a failed install that leaves a readable file could still let this test pass. Assert a zero exit status, parse stdout as JSON, and verify diagnostics remain on stderr.

As per path instructions, tests must cover exit-code paths and preserve machine-readable JSON output discipline.

🤖 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 `@test/e2e/agent-install.e2e.test.ts` around lines 275 - 280, The test `gemini
GEMINI.md contains ONE managed section with verify and onboard content` ignores
the CLI result. Capture the `runCli` return value, assert a zero exit status,
parse `stdout` as JSON and validate the expected response, and assert
diagnostics are emitted only on `stderr` before reading the generated file.

Source: Path instructions

Comment thread test/e2e/agent-install.e2e.test.ts
zeshi-du
zeshi-du previously approved these changes Jul 18, 2026

@zeshi-du zeshi-du left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Gemini target accepted — and the managed-section choice (single root GEMINI.md, mirroring the codex/AGENTS.md pattern) is the correct call for Gemini CLI conventions; the PR body's rationale for deviating from the copilot own-file shape is exactly right. Thin diff following the TARGETS pattern, full matrix coverage in unit + e2e + help snapshots. This supersedes the recovered #247 (closed with credit to its original author). Thanks @Tasfia-17!

@zeshi-du

Copy link
Copy Markdown
Contributor

One-step rebase needed: your other PR #234 merged first and they overlap in the help-snapshot / e2e suites, so this went conflicting. Approval stands — rebase onto current main (re-running the snapshot update if needed) and it merges straight away.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 2

♻️ Duplicate comments (2)
test/e2e/agent-install.e2e.test.ts (2)

277-277: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Assert the CLI exit code and JSON output.

The runCli result is still ignored, meaning a failed install could pass the test if a readable file is left behind. Capture the runCli return value, assert a zero exit status, and parse stdout as JSON to validate the expected response. As per path instructions, tests must cover exit-code paths and maintain JSON output discipline.

🐛 Proposed fix to assert CLI results
-    runCli(['agent', 'install', '--target=gemini', '--dir', tmpDir, '--output', 'json']);
+    const result = runCli(['agent', 'install', '--target=gemini', '--dir', tmpDir, '--output', 'json']);
+    expect(result.status).toBe(0);
+    expect(() => JSON.parse(result.stdout)).not.toThrow();
🤖 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 `@test/e2e/agent-install.e2e.test.ts` at line 277, Update the agent install
test around runCli to capture its result, assert that the CLI exits
successfully, and parse stdout as JSON to validate the expected response. Keep
the existing file verification, but ensure the test covers both exit-code
handling and the command’s JSON output.

Source: Path instructions


275-304: 🗄️ Data Integrity & Integration | 🟠 Major | 🏗️ Heavy lift

Cover managed-section preservation and reruns.

The current test validates a fresh installation but does not verify the managed-section behavior. As per path instructions, DOCUMENTATION.md specifies that in managed-section mode, agent install writes a sentinel-delimited section while always preserving user content outside the sentinels, and re-running replaces that section in-place. Please add a test or expand this one to pre-populate GEMINI.md with user content, run the installation, and assert that the user content remains unchanged outside the sentinels.

🤖 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 `@test/e2e/agent-install.e2e.test.ts` around lines 275 - 304, Expand the Gemini
installation test around the existing `runCli` and sentinel assertions to
pre-populate GEMINI.md with user content, run `agent install`, and verify that
content outside `MANAGED_SECTION_BEGIN` and `MANAGED_SECTION_END` remains
unchanged. Also rerun installation and assert the managed section is replaced in
place without duplicating sentinels, while preserving the existing content and
command assertions.

Source: Path instructions

🧹 Nitpick comments (2)
test/e2e/agent-install.e2e.test.ts (1)

283-285: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Simplify string counting.

Using dynamically constructed regular expressions triggers static analysis warnings for potentially inefficient regex complexity. You can simplify this and avoid escaping logic entirely by using String.prototype.split.

♻️ Proposed refactor
-    const escRe = (s: string) => s.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
-    const beginCount = (content.match(new RegExp(escRe(MANAGED_SECTION_BEGIN), 'g')) ?? []).length;
-    const endCount = (content.match(new RegExp(escRe(MANAGED_SECTION_END), 'g')) ?? []).length;
+    const beginCount = content.split(MANAGED_SECTION_BEGIN).length - 1;
+    const endCount = content.split(MANAGED_SECTION_END).length - 1;
🤖 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 `@test/e2e/agent-install.e2e.test.ts` around lines 283 - 285, Replace the
dynamic RegExp-based counting in the managed-section test with
String.prototype.split using MANAGED_SECTION_BEGIN and MANAGED_SECTION_END
directly. Remove the escRe helper and preserve the existing beginCount and
endCount values by deriving each count from the resulting split-array length.

Source: Linters/SAST tools

src/commands/init.ts (1)

207-210: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Simplify profile reading.

You can eliminate the ternary by passing deps.credentialsPath directly to readProfile, as options.path natively falls back to the default when it is undefined.

♻️ Proposed refactor
-  const credentialsPath = deps.credentialsPath;
-  const savedKey = credentialsPath
-    ? readProfile(opts.profile, { path: credentialsPath })?.apiKey
-    : readProfile(opts.profile)?.apiKey;
+  const savedKey = readProfile(opts.profile, { path: deps.credentialsPath })?.apiKey;
🤖 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 `@src/commands/init.ts` around lines 207 - 210, Update the savedKey
initialization in the profile-reading flow to call readProfile once with
deps.credentialsPath passed as the options.path value, relying on readProfile’s
native default when it is undefined; remove the intermediate credentialsPath
variable and ternary while preserving opts.profile and .apiKey access.
🤖 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 `@src/commands/auth.ts`:
- Around line 145-151: Update the early-return branch in the skipIfConfigured
flow to report the endpoint actually persisted in existingProfile rather than
the override-resolved apiUrl. Fall back to the configured default only when the
saved profile has no endpoint, while preserving the existing already_configured
output and avoiding any profile write.

In `@src/commands/init.ts`:
- Around line 239-246: Update the key-source reporting expression in the init
command to use the computed skipWillApply boolean instead of
opts.skipIfConfigured. Preserve the existing precedence for apiKey, fromEnv, and
prompt so dry-run output matches the runtime behavior when no saved key exists.

---

Duplicate comments:
In `@test/e2e/agent-install.e2e.test.ts`:
- Line 277: Update the agent install test around runCli to capture its result,
assert that the CLI exits successfully, and parse stdout as JSON to validate the
expected response. Keep the existing file verification, but ensure the test
covers both exit-code handling and the command’s JSON output.
- Around line 275-304: Expand the Gemini installation test around the existing
`runCli` and sentinel assertions to pre-populate GEMINI.md with user content,
run `agent install`, and verify that content outside `MANAGED_SECTION_BEGIN` and
`MANAGED_SECTION_END` remains unchanged. Also rerun installation and assert the
managed section is replaced in place without duplicating sentinels, while
preserving the existing content and command assertions.

---

Nitpick comments:
In `@src/commands/init.ts`:
- Around line 207-210: Update the savedKey initialization in the profile-reading
flow to call readProfile once with deps.credentialsPath passed as the
options.path value, relying on readProfile’s native default when it is
undefined; remove the intermediate credentialsPath variable and ternary while
preserving opts.profile and .apiKey access.

In `@test/e2e/agent-install.e2e.test.ts`:
- Around line 283-285: Replace the dynamic RegExp-based counting in the
managed-section test with String.prototype.split using MANAGED_SECTION_BEGIN and
MANAGED_SECTION_END directly. Remove the escRe helper and preserve the existing
beginCount and endCount values by deriving each count from the resulting
split-array length.
🪄 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: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 93ca362b-59a1-4072-aadc-765d3fa6e55c

📥 Commits

Reviewing files that changed from the base of the PR and between 54df468 and 6eeae99.

⛔ Files ignored due to path filters (1)
  • test/__snapshots__/help.snapshot.test.ts.snap is excluded by !**/*.snap, !**/*.snap
📒 Files selected for processing (10)
  • src/commands/agent.test.ts
  • src/commands/agent.ts
  • src/commands/auth.test.ts
  • src/commands/auth.ts
  • src/commands/init.test.ts
  • src/commands/init.ts
  • src/lib/agent-targets.test.ts
  • src/lib/agent-targets.ts
  • test/e2e/agent-install.e2e.test.ts
  • test/e2e/setup.e2e.test.ts
🚧 Files skipped from review as they are similar to previous changes (4)
  • src/commands/agent.ts
  • src/commands/agent.test.ts
  • src/lib/agent-targets.test.ts
  • src/lib/agent-targets.ts

Comment thread src/commands/auth.ts
Comment on lines +145 to +151
if (opts.skipIfConfigured && existingProfile?.apiKey) {
out.print({ profile: opts.profile, apiUrl, status: 'already_configured' }, data => {
const d = data as { profile: string; apiUrl: string };
return `Profile "${d.profile}" already configured. Endpoint: ${d.apiUrl}`;
});
return;
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Report the actual saved endpoint when skipping configuration.

When returning early due to --skip-if-configured, the apiUrl variable includes overrides from opts.endpointUrl and envApiUrl. Because writeProfile is intentionally skipped on this path, those overrides are never persisted to disk. Passing them to out.print creates misleading output (e.g., claiming the profile is already configured with a new endpoint that hasn't actually been saved).

Consider reporting the endpoint that is actually stored in the profile (or the default) to accurately reflect the preserved state.

💚 Proposed fix
-    if (opts.skipIfConfigured && existingProfile?.apiKey) {
-      out.print({ profile: opts.profile, apiUrl, status: 'already_configured' }, data => {
-        const d = data as { profile: string; apiUrl: string };
-        return `Profile "${d.profile}" already configured. Endpoint: ${d.apiUrl}`;
-      });
-      return;
-    }
+    if (opts.skipIfConfigured && existingProfile?.apiKey) {
+      const activeApiUrl = existingProfile.apiUrl ?? DEFAULT_API_URL;
+      out.print({ profile: opts.profile, apiUrl: activeApiUrl, status: 'already_configured' }, data => {
+        const d = data as { profile: string; apiUrl: string };
+        return `Profile "${d.profile}" already configured. Endpoint: ${d.apiUrl}`;
+      });
+      return;
+    }
📝 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.

Suggested change
if (opts.skipIfConfigured && existingProfile?.apiKey) {
out.print({ profile: opts.profile, apiUrl, status: 'already_configured' }, data => {
const d = data as { profile: string; apiUrl: string };
return `Profile "${d.profile}" already configured. Endpoint: ${d.apiUrl}`;
});
return;
}
if (opts.skipIfConfigured && existingProfile?.apiKey) {
const activeApiUrl = existingProfile.apiUrl ?? DEFAULT_API_URL;
out.print({ profile: opts.profile, apiUrl: activeApiUrl, status: 'already_configured' }, data => {
const d = data as { profile: string; apiUrl: string };
return `Profile "${d.profile}" already configured. Endpoint: ${d.apiUrl}`;
});
return;
}
🤖 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 `@src/commands/auth.ts` around lines 145 - 151, Update the early-return branch
in the skipIfConfigured flow to report the endpoint actually persisted in
existingProfile rather than the override-resolved apiUrl. Fall back to the
configured default only when the saved profile has no endpoint, while preserving
the existing already_configured output and avoiding any profile write.

Comment thread src/commands/init.ts
Comment on lines +239 to 246
opts.apiKey
? 'flag'
: opts.fromEnv
? 'env'
: opts.skipIfConfigured
? 'skip-if-configured'
: 'prompt'
})`,

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Use skipWillApply for accurate dry-run reporting.

In --dry-run mode, the reported key source uses opts.skipIfConfigured directly. However, if the flag is passed but no saved key exists, the actual run will fall back to prompting. Using the already computed skipWillApply boolean ensures the dry-run preview accurately reflects the runtime behavior.

💚 Proposed fix
       `[dry-run] would configure profile="${opts.profile}" (key source: ${
         opts.apiKey
           ? 'flag'
           : opts.fromEnv
             ? 'env'
-            : opts.skipIfConfigured
+            : skipWillApply
               ? 'skip-if-configured'
               : 'prompt'
       })`,
📝 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.

Suggested change
opts.apiKey
? 'flag'
: opts.fromEnv
? 'env'
: opts.skipIfConfigured
? 'skip-if-configured'
: 'prompt'
})`,
opts.apiKey
? 'flag'
: opts.fromEnv
? 'env'
: skipWillApply
? 'skip-if-configured'
: 'prompt'
})`,
🤖 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 `@src/commands/init.ts` around lines 239 - 246, Update the key-source reporting
expression in the init command to use the computed skipWillApply boolean instead
of opts.skipIfConfigured. Preserve the existing precedence for apiKey, fromEnv,
and prompt so dry-run output matches the runtime behavior when no saved key
exists.

@zeshi-du

Copy link
Copy Markdown
Contributor

@Tasfia-17 status check on this one — the 07-18 push didn't actually resolve it:

  1. The branch is still conflicting against main. The single commit you pushed looks like a re-push rather than a rebase — GitHub still reports the help-snapshot conflict from fix(init): skip API key prompt when credentials already exist #234's merge. What's needed: git fetch upstream && git rebase upstream/main, regenerate the help snapshot (npm test -- -u on the snapshot suite), resolve, force-push to your branch.
  2. CodeRabbit's follow-up is a real gap: the e2e install test ignores runCli's exit code and JSON output, so a failed install would still pass. Assert on both (the Copilot target's e2e in the same directory is the pattern to copy).

One transparency note so you can decide where to spend effort: #270/#271 propose migrating all agent targets to the Agent Skills standard (.agents/skills/), under which Gemini CLI would be covered natively and per-target PRs like this one become unnecessary. That direction is under discussion now. If it's accepted, we'd close this PR in favor of it — so you may prefer to hold off on the rebase until that lands or stalls. Your call; the approval stands if you rebase before any such migration merges.

Adds `gemini` to the supported agent-install targets. Gemini CLI reads
project-level context from a GEMINI.md file in the repo root, which is
loaded at the start of every session (always-on, no on-demand mode).

Because all installed skills share a single GEMINI.md file in the project
root, the target uses managed-section mode -- the same approach as the
codex/AGENTS.md target -- writing only a sentinel-delimited section so
any existing user content in GEMINI.md is never clobbered.

The landing path is GEMINI.md (repo root). Both testsprite-verify and
testsprite-onboard are aggregated into one managed section, consistent
with how codex aggregates skills into AGENTS.md.

Slots into the existing TARGETS machinery: agent list, setup --agent,
and skill-nudge install-detection all pick it up automatically. Updates
the AgentTarget union, pathFor, TARGETS, agent command description,
help text, unit tests, e2e matrix guards, and the help snapshot.

Contributes to CONTRIBUTING.md accepted target: gemini
@Tasfia-17
Tasfia-17 force-pushed the feat/agent-gemini branch from 6eeae99 to 3df4a37 Compare July 23, 2026 22:11

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 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 `@src/lib/agent-targets.test.ts`:
- Around line 410-414: Update the “renders the verify body content” test to
assert that Gemini output includes both required managed-section start and end
sentinels, using the existing marker helper or constants rather than hardcoded
values. Keep the existing body-content assertion.
🪄 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: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 21e6c363-6306-47ce-94b1-177a14091cdd

📥 Commits

Reviewing files that changed from the base of the PR and between 6eeae99 and 3df4a37.

⛔ Files ignored due to path filters (1)
  • test/__snapshots__/help.snapshot.test.ts.snap is excluded by !**/*.snap, !**/*.snap
📒 Files selected for processing (6)
  • src/commands/agent.test.ts
  • src/commands/agent.ts
  • src/lib/agent-targets.test.ts
  • src/lib/agent-targets.ts
  • test/e2e/agent-install.e2e.test.ts
  • test/e2e/setup.e2e.test.ts
🚧 Files skipped from review as they are similar to previous changes (4)
  • src/commands/agent.test.ts
  • test/e2e/setup.e2e.test.ts
  • src/commands/agent.ts
  • src/lib/agent-targets.ts

Comment thread src/lib/agent-targets.test.ts
- Make MANAGED_SECTION_BEGIN target-neutral ('testsprite agent install')
  instead of 'testsprite agent install codex'; add MANAGED_SECTION_BEGIN_LEGACY
  for backward-compat recognition of existing AGENTS.md files
- classifySection now accepts both the new and legacy BEGIN sentinel
- Add exit-code and JSON output assertions to Gemini e2e install test
- Add managed-section user-content preservation test: pre-populates
  GEMINI.md, runs install twice, asserts prefix/suffix intact and
  section byte-identical across runs
- Clarify renderForTarget unit test: sentinel wrapping is an install-time
  concern, not a renderForTarget concern

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 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 `@test/e2e/agent-install.e2e.test.ts`:
- Around line 354-370: Strengthen the managed-section assertions in the re-run
test by verifying the already computed sectionAfterSecond does not contain
userPrefix.trimEnd() or userSuffix.trim(). Keep the existing whole-file
preservation checks and byte-identical section comparison unchanged, and make
the new assertions deterministic and offline.
🪄 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: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 30f545b6-9065-4817-aff4-ec264daf0046

📥 Commits

Reviewing files that changed from the base of the PR and between 3df4a37 and cdfb146.

📒 Files selected for processing (4)
  • src/commands/agent.ts
  • src/lib/agent-targets.test.ts
  • src/lib/agent-targets.ts
  • test/e2e/agent-install.e2e.test.ts
🚧 Files skipped from review as they are similar to previous changes (2)
  • src/lib/agent-targets.test.ts
  • src/lib/agent-targets.ts

Comment thread test/e2e/agent-install.e2e.test.ts
- Add two-line assertion that sectionAfterSecond does not contain user
  prefix/suffix, proving user content stayed outside the managed section
  and was not absorbed into it during re-run
- Add dedicated sentinel-contract test for managed-section targets:
  verifies MANAGED_SECTION_BEGIN is target-neutral (no 'codex') and that
  MANAGED_SECTION_BEGIN_LEGACY exists for backward compat
- Import MANAGED_SECTION_BEGIN_LEGACY in agent-targets.test.ts
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Feature] Add Gemini CLI as an agent install target

2 participants