@abjad-org/research-chef
v0.3.0
Published
research-chef: an interactive, BYOK-powered AI research assistant for your terminal
Maintainers
Readme
@abjad-org/research-chef
An interactive terminal AI research assistant with BYOK (Bring Your Own
Key) support, built with @clack/prompts
and picocolors.
Features
- 🔑 BYOK — bring your own API key for OpenAI, Anthropic (Claude), Google Gemini, or any OpenAI-compatible endpoint (Groq, Together AI, OpenRouter, a local Ollama server, self-hosted deployments, etc). No key ever leaves your machine except to call the provider's own API directly.
- 🛡️ Verified before you start — your API key and model are tested with a minimal request during setup, so problems surface immediately instead of after you've already typed out a research topic.
- 🔍 One-shot research report — enter a topic and get a clear, structured
summary (overview, key points, context, takeaway) backed by live web
search, with a clickable
Sources:section (title + full URL) so every claim can be verified. - 🗺️ Outline-first reports — approve, edit, or regenerate the proposed
outline (sections + sub-questions) before the full report is written;
navigate long reports with
/sectionsand/goto <number>. - 💬 Interactive follow-up chat — keep asking questions in the same
session, switch models with
/model, start fresh with/clear, or save the conversation with/save— until you type/exit. - 🎨 Polished terminal UI — spinners, colored output, and boxed panels
via
@clack/promptsandpicocolors.
Getting started
Install from npm (recommended for end users)
npx @abjad-org/research-chefor install it globally:
npm install -g @abjad-org/research-chef
research-chefRun from source (for development)
From the monorepo root:
npm install
npm run build
npm startOr in dev mode (no build step, powered by tsx):
npm run devUsage walkthrough
- Welcome screen — a short banner explains what the tool does.
- Connect your provider — pick OpenAI, Anthropic, Gemini, or a Custom (OpenAI-compatible) endpoint, then paste your API key (input is masked). Optionally override the default model. For a custom endpoint, you'll also be asked for its base URL; if it looks like a local Ollama server, the API key can be left blank.
- Verification — a quick, minimal request confirms your key and model actually work together before moving on, so problems are caught here rather than later.
- Enter a research topic — e.g. "The impact of AI on renewable energy adoption".
- Approve the outline — review the proposed sections and guiding
sub-questions, then approve, edit (your own headings separated by
;), or regenerate before the full report is written. - Research spinner — a loading spinner plays while the AI puts together its answer, following your approved outline.
- Research report — a structured, easy-to-read summary is printed in a
boxed panel, ending with a
Sources:list of full URLs. Built-in providers (OpenAI via the Responses API, Anthropic, Gemini) search the live web automatically; custom endpoints answer from the model's own knowledge (noted once, neutrally, during setup). - Chat loop — keep asking follow-up questions (auto-saved after every
reply), or use a command:
/model— switch to a different AI model mid-conversation/clear— clear the conversation and start a new topic/save— export the conversation to a Markdown file under~/.research-chef/exports//history [filter]— list auto-saved sessions, optionally filtered by topic/resume <number>— resume a past session from/history/sections— list the sections of the current report/goto <number>— jump to one section of the current report/help— show all available commands/exit— quit research-chef
Sessions are auto-saved as JSON under ~/.research-chef/sessions/ (API
keys are never written to disk). At startup, when past sessions exist,
you can resume one instead of starting fresh.
Where does my API key go?
Your key is only ever used, in memory, for the duration of the CLI process
to call the selected provider's official HTTPS API directly from your
machine (api.openai.com, api.anthropic.com, or
generativelanguage.googleapis.com). It is never written to disk, sent
to any research-chef server (there isn't one), or logged.
Project structure
src/
├── index.ts # Entry point: wires the whole flow together
├── types/ # Shared TypeScript interfaces & error types
│ └── index.ts
├── providers/ # BYOK provider adapters (one file per provider)
│ ├── registry.ts # Provider metadata (labels, default models, key format)
│ ├── factory.ts # Maps a ProviderId -> concrete adapter
│ ├── openai.provider.ts
│ ├── anthropic.provider.ts
│ └── gemini.provider.ts
├── core/ # Provider-agnostic research/chat logic
│ ├── prompts.ts # System prompt & kickoff message templates
│ ├── citations.ts # Dedupe/format/append for web-source citations
│ ├── outline.ts # Outline parsing + report section navigation
│ ├── conversation.ts # Conversation history state
│ ├── sessionStore.ts # Auto-save/list/load/search for past sessions
│ └── engine.ts # Orchestrates conversation + provider calls
└── ui/ # clack + picocolors presentation layer
├── theme.ts # Centralized colors & text wrapping helper
├── banner.ts # Intro/outro screens
├── setup.ts # Provider selection + API key prompt
├── topic.ts # Research topic prompt
├── resumeStartup.ts # Startup resume picker
├── outlineFlow.ts # Outline approve/edit/regenerate loop
├── researchFlow.ts # Spinner + initial research report
├── chatLoop.ts # Interactive follow-up chat loop
├── render.ts # Renders reports / replies / errors
└── cancel.ts # Shared Ctrl+C / Esc handling
└── ui/ # clack + picocolors presentation layer
├── theme.ts # Centralized colors & text wrapping helper
├── banner.ts # Intro/outro screens
├── setup.ts # Provider selection + API key prompt
├── topic.ts # Research topic prompt
├── researchFlow.ts # Spinner + initial research report
├── chatLoop.ts # Interactive follow-up chat loop
├── render.ts # Renders reports / replies / errors
└── cancel.ts # Shared Ctrl+C / Esc handlingAdding a new provider
- Create
src/providers/<name>.provider.tsimplementing theAiProviderinterface (asendMessage()and atestConnection()method). - Register its metadata (label, hint, default model, key format check) in
src/providers/registry.ts. - Add it to the
ADAPTERSmap insrc/providers/factory.ts.
No other file needs to change — the UI and engine work against the
AiProvider interface, not concrete providers.
Already OpenAI-compatible? If the provider speaks the same
/chat/completionsrequest/response shape as OpenAI (many do — Groq, Together AI, OpenRouter, Ollama, etc.), you likely don't need a new adapter file at all. ReusecreateOpenAiCompatibleProvider(providerId, defaultBaseUrl)fromsrc/providers/openai.provider.tsinstead, the same waysrc/providers/custom.provider.tsdoes.
Scripts
| Script | Description |
| ------------------ | --------------------------------------------- |
| npm run dev | Run the CLI directly from TypeScript source |
| npm run build | Compile TypeScript to dist/ |
| npm start | Run the compiled CLI from dist/ |
| npm run typecheck | Type-check without emitting files |
| npm run clean | Remove the dist/ folder |
