Source repo: https://github.com/gabrielchasukjin/cloi
Integration type: Provider/tool adapter (builtin tool through src/tools registry)
Distribution surface: Cloi's existing builtin tool registry (ToolRegistry.register in src/tools/index.js) — tools self-gate availability via an optional check() probe, which is the project's native opt-in mechanism.
Status: ✅ PR opened — awaiting maintainer review
Links
Why cloi
- Local-first tool-calling coding agent for the terminal (Ollama, Node 22.5+, MIT, ~400 stars, active maintainer — PRs merged within days).
- Its "Known gaps" section explicitly lists "No sub-agents, no MCP, no web access" — web search is a recognized missing capability, not an imposed one.
- Tools are plain JS modules registered through explicit calls (
src/tools/index.js); no filesystem auto-discovery, no plugin packaging needed.
- The registry supports an optional
check() availability probe, so a tool whose env var is missing simply never appears in the schema list. Perfect opt-in: zero behavior change without YDC_API_KEY.
Candidate evaluation (shortlist of 3)
| Candidate |
Stars |
Verdict |
| gabrielchasukjin/cloi |
408 |
✅ Selected. Clean tool registry, explicit "no web access" gap, strong docs/tests (node --test), active maintainer, MIT, no competing search provider. |
| qwen-code-dev-bot/oh-my-cli |
811 |
Rejected: extremely dense src tree (150+ modules, mostly bot-authored PRs); external-provider integration would fight the project's local-only design and review pace. |
| SkyworkAI/DeepResearchAgent |
3535 |
Rejected: already has web-search plumbing; above target band; inactivity since May 2026. |
Implemented integration
web_search builtin tool through Cloi's existing tool registry:
src/tools/web.js: tool gated on YDC_API_KEY via check() → absent from schema list without the key (default behavior unchanged); GET https://api.you.com/api/search with X-API-Key + Authorization: Bearer headers; numbered result list (title/URL/snippet, snippets clipped at 280 chars); 15s timeout; isError results for 401/403 (with key-fix hint), other HTTP errors, network failures, non-JSON bodies. Node built-in fetch only — zero new dependencies.
permission: 'ask' (first call only; query leaves the host, matching the project's local-first ethos).
YDC_API_KEY added to KNOWN_SECRET_NAMES in src/util/secrets.js → stripped from child envs, redacted from output.
- Conditional system-prompt rule in
src/agent/prompt.js (only when tool present, matching the python rule pattern).
- README "Optional web search" section + Known-gaps line updated;
docs/configuration.md env-var table entry.
Setup / env vars
`export YDC_API_KEY=*** (https://you.com/platform/api-keys). Nothing else; no config change, no default behavior change.
Usage example
Ask cloi "what's the latest stable version of Express?" → model calls web_search(query="express latest stable version") → approves once → numbered cited results returned to the model.
Fallback / error handling
- No key → tool never offered (check-gated); if invoked anyway, returns
web_search is not configured. Export YDC_API_KEY to enable it.
- 401/403 → error names the key fix; 5xx/network/timeout → plain error result; all failures are tool results, never thrown exceptions (
dispatch invariant preserved).
- Empty results → normal (non-error) "No results" outcome.
Tests run
node --test test/web.test.js test/secrets.test.js test/registry.test.js test/prompt.test.js → 38 pass / 0 fail.
- 13 new tests in
test/web.test.js (stubbed fetch, no network).
- Live wiring smoke check: registered-but-absent without key; present with key; correct schema.
- Full
npm test has pre-existing flaky SQLite failures on clean main in this environment (confirmed via git stash before/after) — unrelated to this change.
- Live API call not exercised (no
YDC_API_KEY in this environment); exact manual command documented in the PR body.
Source repo: https://github.com/gabrielchasukjin/cloi
Integration type: Provider/tool adapter (builtin tool through
src/toolsregistry)Distribution surface: Cloi's existing builtin tool registry (
ToolRegistry.registerinsrc/tools/index.js) — tools self-gate availability via an optionalcheck()probe, which is the project's native opt-in mechanism.Status: ✅ PR opened — awaiting maintainer review
Links
Why cloi
src/tools/index.js); no filesystem auto-discovery, no plugin packaging needed.check()availability probe, so a tool whose env var is missing simply never appears in the schema list. Perfect opt-in: zero behavior change withoutYDC_API_KEY.Candidate evaluation (shortlist of 3)
node --test), active maintainer, MIT, no competing search provider.Implemented integration
web_searchbuiltin tool through Cloi's existing tool registry:src/tools/web.js: tool gated onYDC_API_KEYviacheck()→ absent from schema list without the key (default behavior unchanged); GEThttps://api.you.com/api/searchwithX-API-Key+Authorization: Bearerheaders; numbered result list (title/URL/snippet, snippets clipped at 280 chars); 15s timeout;isErrorresults for 401/403 (with key-fix hint), other HTTP errors, network failures, non-JSON bodies. Node built-infetchonly — zero new dependencies.permission: 'ask'(first call only; query leaves the host, matching the project's local-first ethos).YDC_API_KEYadded toKNOWN_SECRET_NAMESinsrc/util/secrets.js→ stripped from child envs, redacted from output.src/agent/prompt.js(only when tool present, matching thepythonrule pattern).docs/configuration.mdenv-var table entry.Setup / env vars
`export YDC_API_KEY=*** (https://you.com/platform/api-keys). Nothing else; no config change, no default behavior change.
Usage example
Ask
cloi"what's the latest stable version of Express?" → model callsweb_search(query="express latest stable version")→ approves once → numbered cited results returned to the model.Fallback / error handling
web_search is not configured. Export YDC_API_KEY to enable it.dispatchinvariant preserved).Tests run
node --test test/web.test.js test/secrets.test.js test/registry.test.js test/prompt.test.js→ 38 pass / 0 fail.test/web.test.js(stubbed fetch, no network).npm testhas pre-existing flaky SQLite failures on cleanmainin this environment (confirmed via git stash before/after) — unrelated to this change.YDC_API_KEYin this environment); exact manual command documented in the PR body.