create-headless-agent
Scaffolds a headless agent in TypeScript using @openrouter/agent and Bun — for CLI tools, API servers, queue workers, and pipelines. No terminal UI. Use when building a headless agent, programmatic agent, CLI tool that uses AI, batch agent, pipeline agent, API agent, agent without a UI, or agent service.
What this skill does
# Create Headless Agent
Scaffolds a headless agent in TypeScript targeting OpenRouter. The generated project uses `@openrouter/agent` for the inner loop (model calls, tool execution, stop conditions) and provides a clean programmatic shell: configuration, session management, tool definitions, and one or more entry points (CLI, HTTP server, MCP server, or library import). No terminal UI, no readline, no ANSI — just input in, result out.
## Prerequisites
- Bun 1.1+
- `OPENROUTER_API_KEY` from [openrouter.ai/settings/keys](https://openrouter.ai/settings/keys)
- For full SDK reference, see the `openrouter-typescript-sdk` skill
---
## Decision Tree
| User wants to... | Action |
|---|---|
| Build a new headless agent | Present checklist below, follow Generation Workflow |
| Add tools to an existing agent | Read [references/tools.md](references/tools.md), present tool checklist only |
| Add a module | Read [references/modules.md](references/modules.md), generate the module |
| Add an entry point | Read [references/entry-points.md](references/entry-points.md), generate it |
---
## Interactive Feature Checklist
Present this as a multi-select checklist. Items marked **ON** are pre-selected defaults.
### Entry Points (pick one or more)
| Entry Point | Default | Description |
|-------------|---------|-------------|
| CLI | ON | args/stdin to agent to stdout, `--json` for NDJSON |
| Library module | ON | `import { runAgent } from './agent'` |
| HTTP server | OFF | `Bun.serve()` with SSE streaming |
| MCP server | OFF | Expose as MCP tool via stdio |
### OpenRouter Server Tools (server-side, zero implementation)
| Tool | Type string | Default |
|------|------------|---------|
| Web Search | `openrouter:web_search` | ON |
| Web Fetch | `openrouter:web_fetch` | ON |
| Datetime | `openrouter:datetime` | ON |
| Image Generation | `openrouter:image_generation` | OFF |
Server tools go in the `tools` array alongside user-defined tools. No client code needed — OpenRouter executes them. Docs: [openrouter.ai/docs/guides/features/server-tools](https://openrouter.ai/docs/guides/features/server-tools/overview).
### User-Defined Tools (client-side, generated into src/tools/)
| Tool | Default | Description |
|------|---------|-------------|
| File Read | ON | Read files with offset/limit |
| File Write | ON | Write/create files, auto-create directories |
| File Edit | ON | Search-and-replace with diff validation |
| Glob/Find | ON | File discovery by glob pattern |
| Grep/Search | ON | Content search by regex |
| Directory List | ON | List directory contents |
| Shell/Bash | ON | Execute commands with timeout and output capture |
| Custom Tool Template | ON | Empty skeleton for domain-specific tools |
| JS/TS REPL | OFF | Persistent Bun REPL |
| Sub-agent Spawn | OFF | Delegate tasks to child agents |
| View Image | OFF | Read local images as base64 |
### Agent Modules (architectural components)
| Module | Default | Description |
|--------|---------|-------------|
| Session Persistence | ON | JSONL conversation log, `--no-session` to disable |
| Retry with Backoff | ON | Built into agent.ts |
| Context Compaction | OFF | Summarize when context is long |
| Tool Result Offload | OFF | Persist oversized tool outputs to disk, keep preview in context |
| System Prompt Composition | OFF | Dynamic instructions from context files |
| Tool Approval Flow | OFF | Programmatic approve/reject |
| Structured Event Logging | OFF | JSON events to stderr |
| Output Schema Validation | OFF | Zod schema constraining response |
| Webhook Notifications | OFF | POST on completion |
### CLI Output Mode (single-select, if CLI entry point is ON)
| Mode | Default | Description |
|------|---------|-------------|
| Text | ON | Final response text to stdout |
| JSON | OFF | NDJSON event stream |
| Quiet | OFF | Exit code only |
---
## Generation Workflow
Before generating, **ask the user what to name their agent**. This name is used as:
- the `"name"` field in `package.json`
- the `"bin"` command (so `bun link` makes it a globally-invokable CLI)
- the project directory name (if creating a new directory)
Suggested question: *"What would you like to call your agent? (short kebab-case, e.g. `research-bot` or `docs-helper`)"*. Validate the answer is a valid npm package name (lowercase, kebab-case, no spaces). Default to `my-agent` if the user has no preference. Use the chosen name everywhere the workflow below shows `<agent-name>`.
After getting the name and checklist selections, follow this workflow:
```
- [ ] Generate package.json with name=<agent-name> and bin={"<agent-name>": "src/cli.ts"}
- [ ] Generate tsconfig.json (Bun-native)
- [ ] Generate src/config.ts
- [ ] Generate src/tools/index.ts wiring selected tools
- [ ] Generate selected tool files in src/tools/ (specs in references/tools.md)
- [ ] Generate src/agent.ts (core runner)
- [ ] If Session Persistence ON: generate src/session.ts (spec in references/modules.md)
- [ ] Generate selected modules (specs in references/modules.md)
- [ ] Generate src/cli.ts entry point with shebang `#!/usr/bin/env bun` (spec in references/entry-points.md)
- [ ] If HTTP server selected: generate src/server.ts (spec in references/entry-points.md)
- [ ] If MCP server selected: generate src/mcp-server.ts (spec in references/entry-points.md)
- [ ] Generate .env.example
- [ ] Generate test/agent.test.ts
- [ ] Run `bun install` to fetch dependencies
- [ ] Verify: run `bunx tsc --noEmit`
- [ ] Run `bun link` inside the project to register <agent-name> globally
- [ ] Verify the command is on PATH: `command -v <agent-name>` should print a path. If it fails, tell the user to add Bun's bin dir to their shell rc:
`export PATH="$HOME/.bun/bin:$PATH"` (for bash/zsh). `bun link` silently succeeds even when `~/.bun/bin` isn't on PATH, so without this check the user will be told the agent is globally available but `command not found` will greet them.
- [ ] Tell the user they can now invoke their agent from anywhere with `<agent-name> "<prompt>"`
- [ ] Optional: run `npx skills-ref validate .` to check SKILL.md frontmatter (if installed)
```
After generation, the user can run their agent from any directory:
```bash
<agent-name> "What's in this repo?"
echo "Summarize README.md" | <agent-name>
<agent-name> --json "List all TODOs" | jq .
```
To later rename the agent, update the `name` and `bin` keys in `package.json`, then run `bun unlink && bun link`.
---
## Tool Pattern
All user-defined tools follow this pattern using `@openrouter/agent/tool`. Here is one complete example — all other tools in [references/tools.md](references/tools.md) follow the same shape:
```typescript
import { tool } from '@openrouter/agent/tool';
import { z } from 'zod';
const DEFAULT_LINE_LIMIT = 2000;
const MAX_LINE_CHARS = 2000;
export const fileReadTool = tool({
name: 'file_read',
description:
'Read the contents of a file. Output is capped at 2000 lines by default (use offset/limit to paginate) and any line longer than 2000 characters is truncated. When the response is truncated, the hint field tells you how to continue.',
inputSchema: z.object({
path: z.string().describe('Absolute path to the file'),
offset: z.number().optional().describe('Start reading from this line (1-indexed)'),
limit: z.number().optional().describe(`Maximum lines to return (default ${DEFAULT_LINE_LIMIT})`),
}),
execute: async ({ path, offset, limit }) => {
try {
const content = await Bun.file(path).text();
const lines = content.split('\n');
const start = offset ? offset - 1 : 0;
const end = Math.min(start + (limit ?? DEFAULT_LINE_LIMIT), lines.length);
let longLines = 0;
const slice = lines.slice(start, end).map((line) => {
if (line.length <= MAX_LINE_CHARS) return line;
longLines++;
return line.slice(0, MAX_LINE_CHARS) + `… [line truncated, ${line.length - MAX_LINE_CHARS} chars dropped]`;
});
constRelated in Design
contribute
IncludedLocal-only OSS contribution command center. Auto-refreshes the user's in-flight PR and issue state on invoke so conversations start with full context — no need to brief Claude on what's in flight. Helps the user find issues to contribute to on GitHub, builds per-repo dossiers of what each upstream expects (CLA, DCO, branch convention, AI policy, draft-first, review bots, issue templates), runs deterministic gates before any external action so AI-assisted contributions don't reach maintainers as slop. State is markdown-only: candidate files at ~/.contribute-system/candidates/, repo dossiers at ~/.contribute-system/research/, append-only event log at ~/.contribute-system/log.jsonl. No database, no cloud calls. Use when the user asks about their PRs / issues / contributions, wants to find new work to take on, claim an issue, build/refresh a repo's dossier, or draft a Design Issue or PR. Trigger with "/contribute", "what's my PR status", "find a contribution", "claim issue X", "draft a Design Issue for Y", "refresh dossier for Z".
architectural-analysis
IncludedUser-triggered deep architectural analysis of a codebase or scoped subtree across eight modes — information architecture, data flow, integration points, UI surfaces, interaction patterns, data model, control flow, and failure modes. This skill should be used when the user asks to "diagram this codebase," "map the architecture," "show the data flow," "give me an ERD," "trace control flow," "find the integration points," "verify the layout pattern," "audit the UX architecture," or any similar request whose primary deliverable is mermaid diagrams plus cited reports under docs/architecture/. Dispatches haiku/sonnet sub-agents in parallel for per-mode exploration, then verifies every citation mechanically before any node lands in a diagram. Not for one-off prose explanations of code (use code-explanation) or for high-level system design from scratch (use system-design).
mcp
IncludedModel Context Protocol (MCP) server development and tool management. Languages: Python, TypeScript. Capabilities: build MCP servers, integrate external APIs, discover/execute MCP tools, manage multi-server configs, design agent-centric tools. Actions: create, build, integrate, discover, execute, configure MCP servers/tools. Keywords: MCP, Model Context Protocol, MCP server, MCP tool, stdio transport, SSE transport, tool discovery, resource provider, prompt template, external API integration, Gemini CLI MCP, Claude MCP, agent tools, tool execution, server config. Use when: building MCP servers, integrating external APIs as MCP tools, discovering available MCP tools, executing MCP capabilities, configuring multi-server setups, designing tools for AI agents.
react-native-skia
IncludedDesign, build, debug, and optimise high-polish animated graphics in React Native or Expo using @shopify/react-native-skia, Reanimated, and Gesture Handler. Use when the user wants canvas-driven UI, shaders, paths, rich text, image filters, sprite fields, Skottie, video frames, snapshots, web CanvasKit setup, or performance tuning for custom motion-heavy elements such as loaders, hero art, cards, charts, progress indicators, particle systems, or gesture-driven surfaces. Also use when the user asks for fluid, glow, glass, blob, parallax, 60fps/120fps, or GPU-friendly animated effects in React Native, even if they do not explicitly say "Skia". Do not use for ordinary form/layout work with standard views.
plaid
IncludedProduct Led AI Development — guides founders from idea to launched product. Six capabilities: Idea (discover a product idea), Validate (pressure-test the idea against fatal flaws, problem reality, competition, and 2-week MVP feasibility), Plan (vision intake + document generation), Design (translate image references into a design.md spec), Launch (go-to-market strategy), and Build (roadmap execution). Use when someone says "PLAID", "plaid idea", "help me find an idea", "product idea", "idea from my business", "idea from my expertise", "plaid validate", "validate my idea", "pressure-test", "is this idea good", "find fatal flaws", "validate the problem", "plan a product", "define my vision", "generate a PRD", "product strategy", "plaid design", "design from image", "translate image to design", "create design.md", "extract design tokens", "plaid launch", "go-to-market", "launch plan", "GTM strategy", "launch playbook", "plaid build", "build the app", "start building", or "execute the roadmap".
nextjs-framer-motion-animations
IncludedAdds production-safe Motion for React or Framer Motion animations to Next.js apps, including reveal, hover and tap micro-interactions, whileInView, stagger, AnimatePresence, layout and layoutId transitions, reorder, scroll-linked UI, and lightweight route-content transitions. Use when the user asks to add, refactor, or debug Motion or Framer Motion in App Router or Pages Router codebases, especially around server/client boundaries, reduced motion, LazyMotion, bundle size, hydration, or route transitions. Avoid for GSAP-style timelines, WebGL or 3D scenes, heavy scroll storytelling, or CSS-only effects unless Motion is explicitly requested.