Skip to content

Add agent integration layer for AI coding assistants#153

Open
ArtemisMucaj wants to merge 5 commits into
mainfrom
claude/graphify-feature-review-wuRe8
Open

Add agent integration layer for AI coding assistants#153
ArtemisMucaj wants to merge 5 commits into
mainfrom
claude/graphify-feature-review-wuRe8

Conversation

@ArtemisMucaj

@ArtemisMucaj ArtemisMucaj commented Jun 8, 2026

Copy link
Copy Markdown
Owner

Summary

Introduces a comprehensive agent integration system that wires codesearch into AI coding assistants (Claude Code, OpenCode, Pi, Zed) so they reach for semantic search instead of grepping. The system consists of two main components:

  1. Agent hooks — Platform-specific integrations that nudge assistants toward codesearch search/context/impact when they attempt to grep or read source files
  2. Git hookspost-commit and post-checkout automation that keeps the index fresh in the background

Key Changes

New Modules

  • src/connector/api/agent/mod.rs — Main orchestration layer for install/uninstall across all platforms, with shared filesystem and JSON helpers
  • src/connector/api/agent/marker.rs — Per-project indexing marker (.codesearch/project.json) that gates nudges to indexed repositories only
  • src/connector/api/agent/hook_check.rs — Decision logic for evaluating PreToolUse payloads and deciding when to nudge; reused across all platforms via codesearch hook-check command
  • src/connector/api/agent/git_hooks.rs — Git post-commit and post-checkout hook installation/uninstall with smart merging into existing user hooks
  • src/connector/api/agent/claude.rs — Claude Code integration via PreToolUse hooks in settings.json
  • src/connector/api/agent/opencode.rs — OpenCode integration via tool.execute.before/after plugin
  • src/connector/api/agent/pi.rs — Pi coding agent integration via TypeScript extension with tool_call/tool_result hooks
  • src/connector/api/agent/zed.rs — Zed integration via .rules guidance block and MCP context_servers registration

CLI Changes

  • src/cli/mod.rs — Added AgentPlatform enum (Claude, Opencode, Pi, Zed, All) and HooksSubcommand enum (Install, Uninstall, Status)
  • src/main.rs — Early dispatch of lightweight commands (hook-check, install, uninstall, hooks) before logging initialization to keep stdout clean for JSON output
  • src/connector/api/router.rs — Routed agent commands to the new module

Index Integration

  • src/connector/api/controller/index_controller.rs — After successful indexing, writes the project marker so installed hooks know the repository is indexed

Testing

  • tests/agent_install_tests.rs — End-to-end tests for install/uninstall across all platforms and hook-check behavior with/without markers

Implementation Details

  • Marker-gated nudges: Nudges only fire when .codesearch/project.json exists, preventing spam in freshly cloned or never-indexed repositories
  • Smart hook merging: Git hooks append to existing user hooks rather than replacing them, with marker-based deduplication to prevent duplicate installs
  • Fail-open design: All hook logic is wrapped in error handling; parse errors or missing fields result in no output, never blocking tool calls
  • Reusable decision logic: hook_check::evaluate() centralizes the nudge decision and is called by both the CLI command and platform-specific integrations
  • Platform-specific approaches: Each platform uses its native extension/hook mechanism (PreToolUse for Claude, plugins for OpenCode, TypeScript for Pi, .rules for Zed)
  • Background re-indexing: Git hooks launch codesearch index . in the background (detached, non-blocking) and skip during rebase/merge/cherry-pick operations

https://claude.ai/code/session_01H7BrS8BtStu56KPWcTBQv4

Summary by CodeRabbit

Release Notes

  • New Features

    • Added commands to install and uninstall integrations with Claude, OpenCode, Pi, and Zed.
    • Git hook management for automatic indexing on commit and checkout.
    • Integrated agent guidance system to steer assistant tools toward code search.
  • Tests

    • Added end-to-end tests for agent integration installation and operation.

Add `codesearch install <platform>`, `uninstall`, and `hooks` commands that
wire codesearch into AI coding assistants so they reach for semantic search
instead of grepping or reading files one by one.

Two layers:
- Agent hooks that nudge toward codesearch search/context/impact when the
  assistant is about to grep or read source files. Claude Code gets PreToolUse
  hooks in settings.json; OpenCode an auto-loaded tool.execute plugin; Pi a
  live TypeScript extension (tool_result); Zed always-on .rules plus an MCP
  context_servers registration (Zed has no payload pre-tool hook).
- Git hooks (post-commit/post-checkout) that re-index in the background so the
  nudge always points at fresh data.

A new `codesearch hook-check` command centralises the nudge decision (reading
the tool payload on stdin), and `codesearch index` drops a per-project
.codesearch/project.json marker so hooks only fire in indexed repositories.
Every hook fails open and only adds context, never blocking a tool call.
@coderabbitai

coderabbitai Bot commented Jun 8, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 107af455-94a0-4524-959a-d4423d503593

📥 Commits

Reviewing files that changed from the base of the PR and between ec58877 and 814b77c.

📒 Files selected for processing (13)
  • src/agent/install/claude.rs
  • src/agent/install/git_hooks.rs
  • src/agent/install/mod.rs
  • src/agent/install/opencode.rs
  • src/agent/install/pi.rs
  • src/agent/install/zed.rs
  • src/agent/mod.rs
  • src/agent/pre_tool_call.rs
  • src/connector/api/controller/index_controller.rs
  • src/connector/marker.rs
  • src/connector/mod.rs
  • src/lib.rs
  • src/main.rs
💤 Files with no reviewable changes (6)
  • src/agent/install/pi.rs
  • src/agent/install/zed.rs
  • src/agent/install/claude.rs
  • src/agent/install/opencode.rs
  • src/connector/marker.rs
  • src/agent/install/git_hooks.rs
✅ Files skipped from review due to trivial changes (1)
  • src/connector/mod.rs
🚧 Files skipped from review as they are similar to previous changes (3)
  • src/lib.rs
  • src/connector/api/controller/index_controller.rs
  • src/main.rs

📝 Walkthrough

Walkthrough

This PR introduces a complete agent integration framework enabling codesearch to integrate with multiple AI platforms (Claude, OpenCode, Pi, Zed). It adds CLI commands for installing/uninstalling platform-specific hooks and plugins, a persistent project indexing marker system, runtime tool-call evaluation that nudges assistants toward codesearch, and git hook management for automatic repository indexing.

Changes

Agent integration framework and CLI wiring

Layer / File(s) Summary
CLI command surface and public module exports
src/cli/mod.rs, src/lib.rs
New AgentPlatform enum with variants Claude, Opencode, Pi, Zed, All; new HooksSubcommand with Install, Uninstall, Status; extended Commands with Install/Uninstall/Hooks/PreToolCall variants; re-exported new types from library.
Agent module, install dispatch, and shared file/JSON helpers
src/agent/mod.rs, src/agent/install/mod.rs
Agent module entrypoint; Scope enum for global vs project installation; dispatch router for CLI commands; shared helpers for home/scope directory resolution, path rendering, JSON loading/writing with change detection, idempotent file updates.
Project marker model and index-time persistence
src/connector/marker.rs, src/connector/mod.rs, src/connector/api/controller/index_controller.rs
ProjectMarker struct with repository metadata and timestamp; marker path/write/ancestor-discovery functions; best-effort marker write integrated into indexing; marker module exported from connector.
Pre-tool-call hook evaluation and output generation
src/agent/pre_tool_call.rs
Evaluates tool-call JSON payloads against indexed-marker presence; detects search/bash/grep/read operations via command-token and path-extension filtering; renders Claude-compatible PreToolUse hook output; includes comprehensive unit tests.
Git post-commit and post-checkout hook management
src/agent/install/git_hooks.rs
Installs marker-delimited shell scripts triggering incremental codesearch index; detects repository via git rev-parse; implements idempotent append/removal with user-content preservation; status reporting distinguishes installed/present/absent states.
Claude Code settings and PreToolUse hook management
src/agent/install/claude.rs
Manages Claude settings.json; detects module-owned PreToolUse hooks; idempotently appends two hook matchers targeting Bash and Read|Grep|Glob patterns; preserves foreign hooks; unit-tested for idempotent install and selective removal.
OpenCode plugin installer
src/agent/install/opencode.rs
Writes JavaScript plugin; detects indexing via .codesearch/project.json; nudges bash grep-like commands and appends guidance to grep/glob/read outputs; idempotent via change-detection file writes.
Pi extension installer
src/agent/install/pi.rs
Writes TypeScript extension; walks parent directories for indexed marker; appends nudge text to tool_result events for search and source-file reads; scope-aware path resolution.
Zed rules and context server configuration
src/agent/install/zed.rs
Upserting marker-delimited blocks in Zed rules to steer agent preference; registering/unregistering MCP context_servers entries in settings; idempotent upsert and selective removal; unit-tested for block deduplication and removal.
Main entry-point command handling and router enforcement
src/main.rs, src/connector/api/router.rs
Routes agent commands away from main router; early main dispatch for pre-tool-call/install/uninstall/hooks before logger setup.
End-to-end CLI and integration tests
tests/agent_install_tests.rs
Binary-spawning tests: verifies install all --project creates and uninstall removes platform artifacts; pre-tool-call gated by marker; hooks install requires git repo and writes executable scripts.

Sequence Diagram(s)

sequenceDiagram
  participant User as User/CLI
  participant Main as main
  participant PreTool as pre_tool_call
  participant Dispatch as install::dispatch
  participant Platform as Platform module
  participant Marker as marker
  participant GitHook as git_hooks
  
  rect rgba(200, 150, 100, 0.5)
    note over User,GitHook: Pre-tool-call nudge flow
    User->>Main: codesearch pre-tool-call
    Main->>PreTool: run() stdin JSON
    PreTool->>Marker: find_marker(cwd)
    Marker-->>PreTool: marker path or None
    alt marker exists and tool matches
      PreTool-->>User: nudge PreToolUse output
    else
      PreTool-->>User: (silent, tool proceeds)
    end
  end

  rect rgba(150, 200, 150, 0.5)
    note over User,GitHook: Platform install/uninstall flow
    User->>Main: codesearch install/uninstall --platform all
    Main->>Dispatch: dispatch(Install/Uninstall)
    Dispatch->>Platform: loop for each platform
    Platform->>Marker: reads/writes marker
    Platform-->>Dispatch: status messages
    Dispatch-->>User: formatted report
  end

  rect rgba(100, 150, 200, 0.5)
    note over User,GitHook: Git hook management flow
    User->>Main: codesearch hooks install
    Main->>Dispatch: dispatch(Hooks)
    Dispatch->>GitHook: dispatch(Install)
    GitHook->>GitHook: git rev-parse hooks dir
    GitHook->>GitHook: write post-commit/post-checkout
    GitHook-->>Dispatch: hook status
    Dispatch-->>User: summary
  end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~50 minutes

This PR introduces a substantial agent integration framework spanning platform-specific installers, JSON/file management helpers, marker persistence, tool-call evaluation heuristics, git hook scripts, and end-to-end integration tests. Heterogeneous changes across five platform modules, pre-tool-call logic with command/path filtering, git hook shell scripting, and comprehensive test coverage demand careful review of each functional checkpoint to validate behavior, idempotency, error handling, and inter-component dependencies.

Possibly related PRs

  • ArtemisMucaj/codesearch#14: Introduces the initial router-based command dispatch mechanism that this PR extends with explicit Commands::Install/Uninstall/Hooks/PreToolCall handling.

Poem

🐰 A rabbit hops through agent land,
installing hooks with careful hand,
Claude and Zed and Pi unite,
nudging searches left and right,
markers bloom in .codesearch ground,
codesearch whispers all around! 🌟

🚥 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 "Add agent integration layer for AI coding assistants" accurately describes the main objective of the PR, which introduces a comprehensive agent integration system connecting codesearch with multiple AI assistants.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch claude/graphify-feature-review-wuRe8

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 and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 5

🤖 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/connector/api/agent/git_hooks.rs`:
- Around line 90-96: The IO calls in git_hooks.rs (e.g., the read_to_string and
write in the hook installation flow and the remove_file / set_permissions calls
referenced elsewhere) are being propagated as bare errors; wrap each fallible
filesystem call with anyhow::Context to add call-site operation+path information
before propagating (for example, use .with_context(|| format!("failed to read
hook file {}", path.display())) on read_to_string, similarly "failed to write
hook file {path}", "failed to remove hook file {path}", "failed to set
permissions for hook file {path}") so errors include the operation and the hook
path; ensure anyhow::Context is imported at the top of the module and apply this
pattern to the functions/methods that call read_to_string, write, remove_file,
and set_permissions.
- Around line 89-100: When appending to an existing hook the code writes merged
content but never ensures the file is executable; after writing the merged
content to path in the branch that returns Ok(format!("{name}: appended to
existing hook")), call set_executable(&path)? to make the hook executable (same
helper used in the install branch), and propagate any error so the function
returns a Result as before; update the block around path.exists() where content
is read/merged (using variables marker, script, path) to invoke
set_executable(&path)? immediately after std::fs::write(&path, merged)?.

In `@src/connector/api/agent/mod.rs`:
- Around line 165-172: The function load_json_object currently swallows read and
parse/type errors and returns an empty Map, which can silently erase config;
change load_json_object to propagate errors instead of returning {} — update its
signature to return a Result<Map<String, Value>, Box<dyn std::error::Error>> (or
a concrete error type used in the project), read the file with
std::fs::read_to_string, parse with serde_json::from_str::<Value>, and on
success convert to an object with v.as_object().cloned().ok_or(...) returning a
clear error for non-object JSON; callers that expect a Map (e.g.,
installer/uninstaller paths) should be updated to handle the Result (bubble up
or surface a user-facing error) rather than writing back an empty map.

In `@src/connector/api/controller/index_controller.rs`:
- Around line 47-53: The marker is being written to the canonicalized input path
which may be a subdirectory; instead resolve the repository worktree root and
write the marker there: before calling write_marker (and before use_case.execute
if appropriate) derive the git top-level directory (e.g., via running `git
rev-parse --show-toplevel` or using the repo library) and canonicalize that
worktree root, then create ProjectMarker and call write_marker(&worktree_root,
&marker) so the marker ends up at the actual repo root; alternatively, enforce
callers to pass repo root but prefer deriving the root in this module (affecting
use_case.execute, write_marker, and write_project_marker flows).
- Around line 41-59: write_project_marker performs synchronous filesystem I/O
(std::fs::canonicalize and marker::write_marker) and is currently called from
the async IndexController::index, so move that blocking work into a blocking
task: change callers (IndexController::index) to spawn and await a
tokio::task::spawn_blocking that invokes write_project_marker (or move the fs
logic into a new blocking helper invoked inside spawn_blocking), ensure any use
of self/container state passed into the closure is cloned or made 'static (e.g.,
repo.id/name/namespace or container.memory_storage() check), and propagate or
log errors after awaiting the spawned task; keep the original
write_project_marker signature or create write_project_marker_blocking to
contain only synchronous fs operations (canonicalize and marker::write_marker).
🪄 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: 6209feb4-49d5-4064-8f0f-e039eb804088

📥 Commits

Reviewing files that changed from the base of the PR and between 80bf520 and b2bed71.

📒 Files selected for processing (15)
  • src/cli/mod.rs
  • src/connector/api/agent/claude.rs
  • src/connector/api/agent/git_hooks.rs
  • src/connector/api/agent/hook_check.rs
  • src/connector/api/agent/marker.rs
  • src/connector/api/agent/mod.rs
  • src/connector/api/agent/opencode.rs
  • src/connector/api/agent/pi.rs
  • src/connector/api/agent/zed.rs
  • src/connector/api/controller/index_controller.rs
  • src/connector/api/mod.rs
  • src/connector/api/router.rs
  • src/lib.rs
  • src/main.rs
  • tests/agent_install_tests.rs

Comment thread src/agent/install/git_hooks.rs
Comment thread src/connector/api/agent/git_hooks.rs Outdated
Comment thread src/connector/api/agent/mod.rs Outdated
Comment thread src/connector/api/controller/index_controller.rs Outdated
Comment on lines +47 to +53
let root = std::fs::canonicalize(path).unwrap_or_else(|_| std::path::PathBuf::from(path));
let marker = ProjectMarker::new(
repo.id().to_string(),
repo.name().to_string(),
repo.namespace().map(str::to_string),
);
if let Err(e) = write_marker(&root, &marker) {

@coderabbitai coderabbitai Bot Jun 8, 2026

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.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Verify whether Repository exposes a root/path field and how index use case resolves input path.
# Expected: evidence that marker target path is repo root in all successful index flows.

set -euo pipefail

echo "== Locate Repository definition =="
fd -i 'repository.rs|mod.rs' src | xargs -r rg -n -C2 'struct\s+Repository|impl\s+Repository|fn\s+path\s*\(|fn\s+root\s*\('

echo "== Locate index use case execute signature/implementation =="
rg -n -C3 'fn\s+execute\s*\(.*path|execute\s*\(&path' src

echo "== Locate any canonicalization/root-resolution in indexing pipeline =="
rg -n -C3 'canonicalize|repo root|repository root|worktree|git rev-parse|current_dir' src/connector src/domain src/usecase

Repository: ArtemisMucaj/codesearch

Length of output: 10202


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== Inspect index_controller.rs around write_project_marker and marker write call =="
sed -n '1,140p' src/connector/api/controller/index_controller.rs

echo "== Inspect marker.rs (MARKER_DIR/MARKER_FILE/marker_path/write_marker) =="
sed -n '1,220p' src/connector/api/agent/marker.rs

echo "== Locate index use case implementation and how it resolves input path =="
rg -n "index_use_case" src/connector src/domain src/usecase 2>/dev/null || true
rg -n "fn\s+execute\s*\(\s*&.*path\s*," src 2>/dev/null || true
rg -n "execute\s*\(\s*&path\s*," src 2>/dev/null || true
fd -t f 'index*usecase*|*index*use*case*|*index*' src | head -n 200

Repository: ArtemisMucaj/codesearch

Length of output: 7313


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== Find IndexRepositoryUseCase type =="
rg -n "IndexRepositoryUseCase" src/connector src/domain src/usecase

echo "== Find execute implementation for the index use case =="
rg -n "impl\s+.*IndexRepositoryUseCase|impl\s+.*Index.*UseCase|fn\s+execute\s*\(.*&.*path" src/connector src/domain src/usecase

echo "== Inspect connector/api/container.rs index_use_case wiring =="
sed -n '400,520p' src/connector/api/container.rs

echo "== Inspect Repository model around path() and construction =="
sed -n '1,220p' src/domain/models/repository.rs

echo "== Find where Repository::new(name, path) is called =="
rg -n "Repository::new\(" src/connector src/domain src/usecase

echo "== Inspect hook_check marker lookup behavior (relative to repo root expectations) =="
sed -n '90,180p' src/connector/api/agent/hook_check.rs

Repository: ArtemisMucaj/codesearch

Length of output: 464


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== List src top-level directories =="
ls -la src

echo "== Search for IndexRepositoryUseCase definition/impl =="
rg -n "struct\s+IndexRepositoryUseCase|enum\s+IndexRepositoryUseCase" src || true
rg -n "impl\s+.*IndexRepositoryUseCase" src || true
rg -n "IndexRepositoryUseCase::new" src || true

echo "== Inspect container.rs around index_use_case() =="
sed -n '420,520p' src/connector/api/container.rs

echo "== Inspect repository model around path() semantics =="
sed -n '1,220p' src/domain/models/repository.rs

echo "== Find where Repository::new(name, path) is called =="
rg -n "Repository::new\s*\(" src || true

echo "== Inspect hook_check marker lookup behavior =="
sed -n '90,200p' src/connector/api/agent/hook_check.rs

Repository: ArtemisMucaj/codesearch

Length of output: 14994


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== Inspect src/application/use_cases/index_repository.rs around execute =="
sed -n '1,220p' src/application/use_cases/index_repository.rs

rg -n "fn\s+execute|canonicalize|worktree|rev-parse|repo\s+root|repository\s+root|current_dir" src/application/use_cases/index_repository.rs

echo "== Inspect further down for path resolution =="
sed -n '220,520p' src/application/use_cases/index_repository.rs

echo "== Find any helper that resolves repository root from input path (used by indexing) =="
rg -n "worktree|rev-parse|git\s+rev-parse|current_dir|canonicalize|resolve.*(root|repo)|repo.*(root|path)" src/connector src/application src/domain | head -n 200

Repository: ArtemisMucaj/codesearch

Length of output: 30173


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== Inspect git_hooks.rs to see how hook_check runs / what cwd is =="
sed -n '1,140p' src/connector/api/agent/git_hooks.rs
sed -n '140,260p' src/connector/api/agent/git_hooks.rs

echo "== Search for hook_check invocation =="
rg -n "hook_check|hook-check|hookcheck" src/connector/api/agent src/connector/api/controller src/application || true

echo "== Inspect any hook install logic (looking for post-checkout) =="
rg -n "post-checkout|post checkout|post_checkout" src/connector/api/agent src/connector/api || true

Repository: ArtemisMucaj/codesearch

Length of output: 10015


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== Search for git repo root resolution (show-toplevel/worktree) =="
rg -n "show-toplevel|rev-parse --show-toplevel|git rev-parse --git-dir|git rev-parse.*toplevel|worktree root|--show-cdup" src/connector src/application src/domain || true

echo "== Search for any function that derives repo root from input path =="
rg -n "git_root|repo_root|repository_root|worktree|rev_parse.*toplevel" src/connector src/application src/domain || true

Repository: ArtemisMucaj/codesearch

Length of output: 290


Ensure marker is written at the git repository root (not just the canonicalized user input path)

  • use_case.execute(&path, ...) canonicalizes path and indexes that directory directly; it does not resolve a VCS/working-tree root (so passing a subdirectory makes the “root” a subdirectory).
  • write_project_marker then writes to <canonicalized path>/.codesearch/project.json, so the marker can land under that subdirectory.
  • The post-checkout hook checks for .codesearch/project.json relative to the repo working dir before running codesearch index ., so if the marker isn’t at the actual repo root, re-index on checkout won’t fire.

Either enforce that callers pass the repo root, or have the indexing/marker path resolution derive the git worktree root (e.g., via git rev-parse --show-toplevel) and use that for the marker.

🤖 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/connector/api/controller/index_controller.rs` around lines 47 - 53, The
marker is being written to the canonicalized input path which may be a
subdirectory; instead resolve the repository worktree root and write the marker
there: before calling write_marker (and before use_case.execute if appropriate)
derive the git top-level directory (e.g., via running `git rev-parse
--show-toplevel` or using the repo library) and canonicalize that worktree root,
then create ProjectMarker and call write_marker(&worktree_root, &marker) so the
marker ends up at the actual repo root; alternatively, enforce callers to pass
repo root but prefer deriving the root in this module (affecting
use_case.execute, write_marker, and write_project_marker flows).

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

Declining this one (the other four findings in this review are fixed in ec58877).

codesearch indexes arbitrary directories, not necessarily git worktrees — index is regularly run against non-git folders. Resolving the marker location via git rev-parse --show-toplevel would therefore be wrong in two ways: it would fail/misbehave for non-git directories, and it would override a deliberate choice to index a subdirectory.

The marker is intentionally written at the root of what was indexed (the canonicalized input path). In the standard codesearch index . flow — and in the git hooks themselves, which run codesearch index . from the worktree root — the indexed path is the repo root, so the marker lands exactly where the post-checkout hook ([ -f ".codesearch/project.json" ]) and pre-tool-call (which walks up from cwd) look for it. Indexing a subdirectory is a valid, scoped use; the marker correctly reflects that scope rather than silently re-pointing at a VCS root the user didn't index.


Generated by Claude Code

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.

@ArtemisMucaj, understood — the explanation is clear and the design makes sense. Writing the marker at the canonicalized input path (rather than forcing VCS root resolution) correctly handles non-git directories, preserves subdirectory indexing scope, and aligns with the standard codesearch index . from the worktree root convention used by the git hooks. I'll keep this in mind for future reviews.

(¬ 、¬)


✏️ Learnings added
Learnt from: ArtemisMucaj
Repo: ArtemisMucaj/codesearch PR: 153
File: src/connector/api/controller/index_controller.rs:0-0
Timestamp: 2026-06-08T09:46:30.518Z
Learning: In the `codesearch` project (Rust), the project marker `.codesearch/project.json` is intentionally written at the canonicalized root of **what was indexed** (the input path to `codesearch index`), not at the git worktree root. This is by design because:
1. `codesearch index` can be run against arbitrary directories, including non-git folders — resolving via `git rev-parse --show-toplevel` would fail for those.
2. Indexing a subdirectory is a valid scoped use case; the marker should reflect that scope.
3. In the standard flow, `codesearch index .` is run from the worktree root (including by git hooks), so the marker naturally lands at the repo root where the `post-checkout` hook (`[ -f ".codesearch/project.json" ]`) and `hook-check` (which walks up from cwd) look for it.
File: `src/connector/api/controller/index_controller.rs`, function `write_project_marker`.

Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.

claude added 4 commits June 8, 2026 09:04
The internal `codesearch hook-check` command name was vague. Rename it to
`codesearch pre-tool-call` (and the module/constant to match) so the command
clearly reflects that it evaluates a pre-tool-call payload. Updates the Claude
PreToolUse hook command string and all references; behaviour is unchanged.
- git_hooks: set executable bit when appending to an existing hook so git
  runs the codesearch section; add anyhow::Context to all filesystem calls
- agent::load_json_object: return Result and propagate parse/read errors
  instead of silently overwriting a malformed-but-present config with {}
- index_controller: move the blocking marker write into spawn_blocking so it
  never stalls a Tokio worker during concurrent indexing
The agent integration extends the ecosystem around codesearch (editor/agent
hooks) rather than adding to its core search/analysis capabilities — much like
the TUI. Move it out of the connector layer (src/connector/api/agent) to a
sibling top-level module (src/agent) to reflect that, and repoint the four
references (lib.rs, main.rs, connector/api/mod.rs, index_controller.rs).
No behaviour change.
…ctor

- Move the per-project marker (.codesearch/project.json read/write/find) out of
  the agent module into the connector layer (src/connector/marker.rs), where
  filesystem persistence belongs; it is consumed by both the index controller
  and the pre-tool-call command.
- Group all install/uninstall/hook-writing code under a dedicated
  src/agent/install submodule, leaving src/agent with just the install
  subtree and the runtime pre_tool_call command.

Repoints references (main.rs, connector/mod.rs, index_controller, pre_tool_call).
No behaviour change.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants