Skip to content

feat(harness): grep, find and ls built-in tools - #64

Merged
sanchitrk merged 2 commits into
canaryfrom
feat/search-tools
Oct 10, 2026
Merged

sanchitrk merged 2 commits into
canaryfrom
feat/search-tools

Conversation

@sanchitrk

Copy link
Copy Markdown
Contributor

Summary

Adds Pi's search and listing tools as built-in plugins.

  • grep runs ripgrep inside the mounted sandbox:
    • host and remote: the sandbox's own rg
    • virtual (memory, sqldb): just-bash's built-in rg
    • Only the first limit matches leave the sandbox. Context lines are read through scanLines.
  • find runs fd in the sandbox. Virtual mounts have no fd, and the tool says so to the model instead of emulating it.
  • ls lists one directory through the sandbox filesystem.
  • Output, limits and truncation messages follow Pi.
  • Deliberate differences from Pi:
    • rg --sort path and sorted fd results, so results come back in the same order every run.
    • find reports Path not found up front, as Pi's non-fd path does.

Missing binaries

tool/binary.ts checks for rg/fd the first time a tool needs them. It remembers per sandbox only that a binary was found.

  • Local: a missing binary is installed into <home>/bin.
  • Remote: it goes into the sandbox's own $HOME/.codework/bin. The release is downloaded on the host and uploaded, so the sandbox needs no network access.
  • Install failure: the model is told the binary isn't available. There is no fallback search code.

Some providers (Daytona) merge stderr into stdout. The grep pipeline therefore sends ripgrep's exit status as a final JSON line and holds its stderr until the pipe has closed. find recognises fd's [fd error]: lines.

Opt-in, as in Pi

Pi's default tools are read, bash, edit, write. A plugin can now declare optIn: true: it keeps its built-in position but runs only after settings turn it on:

{ "plugins": [{ "plugin": "codework.tool.grep", "enabled": true }] }

grep, find and ls are opt-in. Configuration still never adds a plugin by itself. Once turned on, an opt-in plugin stays on when its module is listed again, for example by project settings.

Plugin context

Plugin setup now gets ctx.paths (home, bin, cache, data, log), the harness's own directories on the host. global.ts gains bin.

Testing

All end to end, each ending in a snapshot under __artifacts__/:

  • Host and memory sandboxes (tools.search.test.ts): one shared fixture with Pi's own cases:

    • a flag-like --pre= pattern that must not run anything
    • match limit combined with context
    • path globs (Pi #3302)
    • nested .gitignore scoping (Pi #3303)
    • broken globs, dotfiles, and a 60KB match line

    grep and ls give the same results on both. The one real difference is recorded: real ripgrep lets --glob override .gitignore.

  • Live Daytona and Vercel sandboxes (shared spec in the existing e2e suites): results identical to the host. Daytona used its own rg and the tool installed fd; on Vercel the tool installed both.

  • Live models through the harness (tools.search.live.test.ts) and the real CLI (cli.search.live.test.ts): OpenAI and Anthropic answer a question that needs find, grep and ls. Through the CLI the tools are absent without settings and present with them.

  • Opt-in: an end-to-end check that the tools are off by default and turned on by settings, plus catalog cases for the opt-in rule.

vp run typecheck passes. Tests: harness 572, plugin 117, codework (including the live CLI test).

🤖 Generated with Claude Code

sanchitrk and others added 2 commits October 10, 2026 18:38
grep runs ripgrep and find runs fd inside the mounted sandbox: the host's or
the remote's own binary, or just-bash's built-in rg on a virtual mount, which
has no fd and says so. A missing binary is installed on first use, into
<home>/bin for the host and into the sandbox's own $HOME/.codework/bin for a
remote, downloaded on the host so the sandbox needs no network. ls lists
through the sandbox filesystem. Output, limits and truncation follow Pi.

The tools ship off, as Pi ships them. A plugin can declare `optIn: true`: it
keeps its built-in position but runs only once settings turn it on with
`{ "plugin": "codework.tool.grep", "enabled": true }`.

Plugin setup now gets `ctx.paths` (home, bin, cache, data, log).

Covered end to end on the host, a memory sandbox, live Daytona and Vercel
sandboxes, and live OpenAI and Anthropic models through the harness and the
CLI.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@sanchitrk
sanchitrk merged commit acb9442 into canary Oct 10, 2026
@sanchitrk
sanchitrk deleted the feat/search-tools branch October 10, 2026 13:23
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.

1 participant