Skip to content

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

Open
Tasfia-17 wants to merge 1 commit into
TestSprite:mainfrom
Tasfia-17:feat/agent-gemini
Open

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

Conversation

@Tasfia-17

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

Copy link
Copy Markdown

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.
    • Gemini skills are written to GEMINI.md using plain Markdown and managed sections.
    • Updated agent command help and installation guidance to include Gemini.
  • Tests

    • Expanded coverage for Gemini rendering, installation, onboarding, and lifecycle behavior.
    • Updated agent listing expectations to account for the additional target.

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
@coderabbitai

coderabbitai Bot commented Jul 10, 2026

Copy link
Copy Markdown

Review Change Stack

Walkthrough

Gemini is added as a managed-section installation target using GEMINI.md. The registry, rendering behavior, CLI help, target counts, and unit/e2e coverage are updated, including plain-Markdown and sentinel-delimited section assertions.

Changes

Gemini agent target

Layer / File(s) Summary
Target registry and path
src/lib/agent-targets.ts
Adds gemini to the target type and registry, resolves it to GEMINI.md, and configures managed-section rendering with plain Markdown.
Rendering and CLI contracts
src/lib/agent-targets.test.ts, src/commands/agent.ts, src/commands/agent.test.ts
Tests Gemini rendering and mode registration, and updates CLI help and JSON list expectations for the expanded target set.
Installation and matrix coverage
test/e2e/agent-install.e2e.test.ts, test/e2e/setup.e2e.test.ts
Validates Gemini file content, managed-section lifecycle, dynamic list sizing, and target matrix coverage.

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

Sequence Diagram(s)

sequenceDiagram
  participant CLI
  participant AgentTargets
  participant GEMINImd
  CLI->>AgentTargets: install target gemini
  AgentTargets->>GEMINImd: resolve GEMINI.md
  AgentTargets->>GEMINImd: write sentinel-delimited Markdown section
  GEMINImd-->>CLI: updated installation content
Loading

Possibly related PRs

Suggested reviewers: ruili-testsprite, zeshi-du

🚥 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 and concisely describes the main change: adding Gemini as an agent install target.
Linked Issues check ✅ Passed The PR adds gemini support, writes to GEMINI.md in managed-section mode, and updates CLI/tests to match issue #235.
Out of Scope Changes check ✅ Passed The changes stay focused on Gemini target support and related tests/help text, with no obvious unrelated additions.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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 on lines 1073 to +1075
.option(
'--target <t>',
'Agent target(s): claude, cursor, cline, antigravity, kiro, windsurf, copilot, codex (comma-separated or repeated)',
'Agent target(s): claude, cursor, cline, antigravity, kiro, windsurf, copilot, gemini, codex (comma-separated or repeated)',

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

Document Gemini in the managed-section --force behavior.

The target help includes gemini, but the existing --force description still says only codex is managed-section. Update it to mention both targets or all managed-section targets, while retaining the no-clobber guarantee.

As per path instructions, managed-section targets’ user content outside the sentinels must remain explicitly protected.

🤖 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/agent.ts` around lines 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.

Source: Path instructions

Comment thread src/lib/agent-targets.ts
Comment on lines +254 to +276
/**
* gemini target -- managed-section mode (GEMINI.md).
*
* Gemini CLI reads project-level instructions from a `GEMINI.md` file in
* the repo root. The file is plain Markdown, loaded at the start of every
* session (always-on). Because all installed skills share this single file
* we use managed-section mode -- the same approach as codex/AGENTS.md --
* writing only a sentinel-delimited section so any existing user content
* in GEMINI.md is never clobbered.
*
* The compact body is used (same reasoning as windsurf/copilot): GEMINI.md
* is always-injected, so keeping it small reduces context cost.
*
* --force replaces the managed section unconditionally but never touches
* content outside the sentinels.
*/
gemini: {
status: 'experimental',
path: pathFor('gemini', SKILL_NAME),
mode: 'managed-section',
// GEMINI.md is plain Markdown; wrap is a no-op (no frontmatter).
wrap: (_name, _description, body) => body,
},

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Use a target-neutral managed-section sentinel.

Gemini uses the shared managed-section writer, but MANAGED_SECTION_BEGIN currently says testsprite agent install codex. A generated GEMINI.md will therefore label its managed content as Codex, which is misleading for users and future cleanup tooling. Rename the shared marker to be target-neutral while preserving compatibility with existing Codex files.

🤖 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/lib/agent-targets.ts` around lines 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.

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 on lines +275 to +304
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');

// (a) Exactly ONE pair of sentinels
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;
expect(beginCount, 'exactly one BEGIN sentinel').toBe(1);
expect(endCount, 'exactly one END sentinel').toBe(1);

// BEGIN must come before END
expect(content.indexOf(MANAGED_SECTION_BEGIN)).toBeLessThan(
content.indexOf(MANAGED_SECTION_END),
);

// (b) Load-bearing command strings from the compact verify body
expect(content).toContain('testsprite test run');
expect(content).toContain('--wait');
expect(content).toContain('test artifact get');

// (c) Onboard one-liner must be present
expect(content).toContain('First-time setup');

// (d) No frontmatter fence -- GEMINI.md is plain prose
expect(content.startsWith('---'), 'gemini: must NOT start with ---').toBe(false);
});

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

Cover managed-section preservation and reruns.

This test starts from an empty GEMINI.md and verifies only a single install. Add coverage that pre-populates user content outside the sentinels, installs both skills, then reruns installation and asserts that user content remains intact, exactly one section exists, and only the managed section is replaced.

As per path instructions, tests must cover the new behavior deterministically and offline.

🧰 Tools
🪛 ast-grep (0.44.1)

[warning] 283-283: Do not use variable for regular expressions
Context: new RegExp(escRe(MANAGED_SECTION_BEGIN), 'g')
Note: [CWE-1333] Inefficient Regular Expression Complexity. Security best practice.

(regexp-non-literal-typescript)


[warning] 284-284: Do not use variable for regular expressions
Context: new RegExp(escRe(MANAGED_SECTION_END), 'g')
Note: [CWE-1333] Inefficient Regular Expression Complexity. Security best practice.

(regexp-non-literal-typescript)

🤖 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, 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.

Source: Path instructions

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

1 participant