helixent - tiny ReAct agent loop for Bun
Small TypeScript library for ReAct-style agent loops on the Bun stack. Tools, skills, and a coding-focused harness in a minimal package.
Helixent is a small, deliberately legible TypeScript library for building ReAct-style coding agents on the Bun stack. The mascot is a blue rabbit; the actual project is a clean three-layer architecture you can read end-to-end in an afternoon. If you've ever wondered what's actually inside Claude Code or Codex but didn't want to read 50,000 lines of code to find out, Helixent is the one to study.
The author's framing is honest: foundation, agent loop, coding agent. Each layer depends only on the one below. The whole thing fits in src/foundation, src/agent, and src/coding, plus a community/ directory for provider adapters.
Three layers, in order
Foundation - the primitives every ReAct loop needs:
Model- unified abstraction over LLM providers. Define a model once, swap providers without changing agent code.Message- single transcript type that flows end-to-end. Source of truth for the conversation.Tool- definitions and execution plumbing for the actions an agent can invoke.
Agent Loop - reusable, generic, ReAct-style:
- Maintains state over a conversation transcript.
- Orchestrates "think -> act -> observe" steps in a loop.
- Invokes tool calls in parallel and feeds observations back.
- Supports middleware for extending behaviour.
This layer is domain-agnostic - the same loop drives any agent.
Coding Agent - domain-specific, pre-configured with developer tools: read_file, write_file, str_replace, bash, list_files, glob_search, grep_search, apply_patch, file_info, mkdir, move_path. Plus the skills middleware. Plus a todo-list-based plan mode.
The separation matters. If you only need the agent loop (you have your own tools), Layer 2 is what you import. If you want a working coding agent right now, Layer 3 is two function calls.
Quick start
Install and run:
npm install -g helixent@latest
cd path/to/your/project
helixent
Or no install:
npx helixent@latest
Configuration lives at ~/.helixent/config.yaml. Models added via:
helixent config model add
helixent config model list
helixent config model set-default <model_name>
Build a coding agent from scratch
The README's worked example is the right size to read. Three steps in TypeScript:
import { createCodingAgent } from "helixent/coding";
import { OpenAIModelProvider } from "helixent/community/openai";
import { Model } from "helixent/foundation";
const provider = new OpenAIModelProvider({
baseURL: "https://api.openai.com/v1",
apiKey: process.env.OPENAI_API_KEY,
});
const model = new Model("gpt-4o", provider, {
max_tokens: 16 * 1024,
thinking: { type: "enabled" },
});
const agent = await createCodingAgent({ model });
const stream = await agent.stream({
role: "user",
content: [{ type: "text", text: "Create a hello world web server." }],
});
for await (const message of stream) {
for (const content of message.content) {
if (content.type === "thinking") console.info("💡", content.thinking);
else if (content.type === "text") console.info(content.text);
else if (content.type === "tool_use") console.info("🔧", content.name);
}
}
That's a real, working coding agent in 30-ish lines. The provider in this example is OpenAI-compatible, but the model abstraction is provider-agnostic - swap the provider class for Anthropic, Groq, OpenRouter, or any local OpenAI-compatible endpoint.
Middleware - the extension surface
Eight hooks at every stage of the loop:
| Hook | When it runs |
|---|---|
beforeAgentRun | once, after user message appended, before first step |
afterAgentRun | once, when agent stops (no tool calls) |
beforeAgentStep | at the start of each step, before model invocation |
afterAgentStep | at the end of each step, after tool calls complete |
beforeModel | before the model context is sent to the provider |
afterModel | after the model response is received |
beforeToolUse | immediately before a tool is invoked |
afterToolUse | immediately after a tool resolves |
Each hook receives the current context and returns either a partial update to merge in or void to leave it unchanged. Middleware runs in array order, which is the right composition rule.
This is the same shape that LangChain's middleware doc describes, scaled down to the layer that actually fits in your head. If you're learning how middleware-based agent harnesses work, read this codebase first.
Skills support
Helixent supports the standard agent skill format from agentskills.io. Skills are discovered from four locations:
~/.agents/skills~/.helixent/skills${current_project}/.agents/skills${current_project}/.helixent/skills
Duplicate skill names across folders are allowed - useful when project-local skills override global ones. Plus AGENTS.md at the project root is automatically picked up as long-term project guidance.
Why Bun
Three reasons the project gives:
- Same runtime as Claude Code - Bun powers CC; the ecosystem is converging on TypeScript-first tools running on Bun. Compiled builds are single native executables.
- Performance - HTTP, filesystem I/O, and cold starts are noticeably faster than Node, which compounds across an agent loop with dozens of tool calls per run.
- Standalone executables -
bun build --compileoutputs one self-contained binary. Shipping a CLI = handing users one file. - Batteries included - test runner, bundler, TypeScript support all in the runtime.
If you don't already use Bun, treat that as a real install cost. For TypeScript-first agent work it's the right ecosystem; for Node-default teams it's a small but real switch.
Roadmap
The README is up-front about what's not yet shipped:
- Sub-agents - spawn child agents with their own context and tools.
- Agent Team - multi-agent collaboration patterns.
- Print Mode - Claude Code-style rich terminal rendering.
- Sessioning - local file-based session store for context and history.
If any of those are load-bearing for your use case, evaluate now whether the current state is enough.
When to reach for it
- You want to build an agent harness from a clean, legible base instead of forking Claude Code.
- You're learning how ReAct loops, middleware, and tool execution actually compose.
- You want a TypeScript-first coding agent runtime that's small enough to modify confidently.
When not to
- You need a finished, batteries-included product for end users today. Use Claude Code or Codex.
- You're committed to a Node or Python stack and don't want to add Bun. The project is tightly coupled to Bun.
- You need multi-agent orchestration, persistent sessions, or rich terminal UI right now. Wait for the roadmap or build on a different harness.
Trade-offs
Layer 3 (the Coding Agent) is the part that ships ready to use. Layers 1 and 2 are deliberately neutral, which means they're useful exactly because they're lean - but they're also a kit, not a product. If you write your own tools, you'll write a meaningful amount of code on top.
The provider story is OpenAI-compatible by default in the shipped community/openai adapter. Other providers - Anthropic native, Gemini, etc. - get there by writing the contract; the abstraction is correct for the shape, but the work of writing each adapter is yours unless someone else has already done it.
Pre-commit hooks block commits until bun run check passes (linting + type checking + tests). The project's framing - "in an AI-dominated GitHub universe, we should be able to handle the last mile of code quality" - is the right attitude for any project that ships agent infrastructure.
The repo is unusually approachable for what it is. If you've been meaning to read a coding-agent codebase end-to-end, this is the one.
Related entries
open-harness - composable SDK for AI agents
TypeScript SDK for building agents with a code-first composition model: tools, skills, and MCP servers wire together as plain modules. Ships an agent loop you control.
passmark - Playwright AI regression testing
Open-source Playwright library for AI-driven browser regression testing with intelligent caching, auto-healing locators, and multi-model verification. Designed to keep flaky AI tests stable across model versions.
bunqueue - SQLite-backed job queue for Bun
High-performance Bun job queue with SQLite persistence, dead-letter queue, cron scheduling, and S3 backups. Marketed as BullMQ alternative for AI agent workloads.
agent-prism - React components for agent traces
React component library for visualizing distributed traces from AI agents. Drop-in widgets for timelines, span trees, and tool-call breakdowns from LangChain or custom runtimes.