chore: add project docs, glossary, research and opencode/fastcrw skills

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
haylanandClaude Bot committed 2026-10-03 17:30:03 +02:00
commit b316daed43
9 files changed
+409

No files matched your search

@@ -0,0 +1,53 @@
---
name: fastcrw-search-api
description: Contract of the fastCRW `POST /v1/search` REST endpoint (auth, request, response shapes, errors, env vars). Use when writing or testing the plugin's search call or its response/error mapping.
---
# fastCRW `/v1/search`
Researched from docs.fastcrw.com and github.com/us/crw source; not tested against a live instance. Full detail: `docs/research/fastcrw-search-api.md`.
## Call
`POST {baseURL}/v1/search`, `Content-Type: application/json`, body `{ "query": string, "limit": number }`.
- `query` required, max 2000 chars. `limit` default 5, clamped server-side to 1..20.
- Optional extras worth exposing: `lang`, `tbs` (`qdr:h|d|w|m|y`). Do not send `sources` (switches the response to a grouped shape).
## Auth
`Authorization: Bearer <key>`. Send it only when a key is configured; self-hosted needs none unless the operator set `CRW_AUTH__API_KEYS`. 401 messages: "Missing Authorization header", "Invalid API key".
## Env vars (match upstream names)
`CRW_API_URL` (base URL; hosted default `https://api.fastcrw.com`, self-hosted `http://localhost:3000`), `CRW_API_KEY` (token).
## Response: parse both shapes
```json
{ "success": true, "data": [ ... ] }
{ "success": true, "data": { "results": [ ... ] } }
```
Result: `url`, `title`, `description`, `snippet` (always-populated alias of `description`), `position`, optional `score`, `publishedDate`, `category`. Map to opencode as `{ url, title, content: snippet || description || "", time: {} }`.
## Errors
Body `{ "success": false, "error": string, "error_code": string }`.
| HTTP | error_code |
|---|---|
| 400 | `invalid_request` |
| 401 | auth middleware message |
| 422 | `target_unreachable` |
| 429 | `rate_limited` |
| 500 | `internal_error` |
| 502 | `http_error` |
| 503 | `search_disabled` / `search_degraded` |
| 504 | `timeout` |
Self-hosted search needs a SearXNG-style backend (`CRW_SEARCH__SEARCH_BACKEND_URL`); without one expect 503 `search_disabled`.
## Limits
Server defaults: 10 req/s, 60 s request timeout, 15 s search timeout. A plain `fetch` suffices; `crw-mcp` is unnecessary for search only.
@@ -0,0 +1,65 @@
---
name: opencode-v2-plugin
description: How to write, configure and register an opencode v2 plugin, including adding a websearch provider. Use when writing or editing plugin code, opencode.json `plugins`/`websearch` config, or plugin packaging in this repo.
---
# opencode v2 plugin
Verified against opencode.ai/v2 docs (build/plugins, plugins, config, websearch). Full evidence and open items: `docs/research/opencode-v2-plugin-api.md`. The v1 package `@opencode-ai/plugin` does NOT run in v2.
## Entry point
```ts
import { Plugin } from "@opencode/plugin"
export default Plugin.define({
id: "home.fastcrw", // required, stable; used for storage scoping and diagnostics
async setup(ctx) {
// ctx.options (plugin options), ctx.storage, ctx.location, ctx.websearch, ...
// may return a cleanup function
},
})
```
Options are read from `ctx.options` inside `setup`, not passed as an argument. They are untyped key/value: validate them yourself.
## Websearch provider
```ts
await ctx.websearch.transform((editor) => {
editor.add({
id: "fastcrw",
name: "fastCRW (self-hosted)",
execute: async ({ query }, { signal }) => [{ url, title, content, time: {} }],
})
editor.default.set("fastcrw") // make it active; set(false) disables
})
```
- `execute` returns `{ url, title, content, time }[]`. Pass `signal` to `fetch`.
- `await ctx.websearch.reload()` re-evaluates providers.
## Config (`opencode.json`)
```jsonc
{
"plugins": [{ "package": "~/.config/opencode/plugins/fastcrw", "options": { "baseURL": "http://crw.home:3000", "limit": 8 } }],
"websearch": { "provider": "fastcrw" }
}
```
- Key is plural `plugins` (v1: `plugin`). Entries are a string or `{ package, options }`.
- `package` may be an npm name (`name`, `name@1.2.0`, `@scope/name`), `./local`, an absolute path or `file://`.
- Auto-discovered: `.ts`/`.js` files and packages in `.opencode/plugins/` and `~/.config/opencode/plugins/`.
- `websearch.provider` is a provider id or `"random"`; `"websearch": false` disables search. Built-in ids: exa, firecrawl, parallel, tavily, tinyfish.
- CLI: `opencode plugin add|list|check|update|remove`.
## Packaging (npm)
`"type": "module"`, `exports["."]` pointing at the entry, dependency on `@opencode/plugin`.
## Unverified: check at runtime, do not assume
- Exact TypeScript types for the editor, `time` and `execute` args (read `@opencode/plugin` typings after install).
- Inner shape of `time`, and whether extra result fields are allowed.
- Precedence between config `websearch.provider` and `editor.default.set(id)`.