@affer/affer
v0.9.0
Published
Zero-dependency terminal coding agent: professional TUI, 13 LLM providers, sessions, checkpoints, LLM compaction, V4A apply_patch, todo planning. Prebuilt native binaries, no runtime required.
Maintainers
Readme
Affer
Zero-dependency terminal coding agent — professional TUI, 13 LLM providers, sessions, checkpoints, LLM context compaction, Codex-style apply_patch, todo planning, and an SDK. Built from scratch after studying 30+ open-source agent harnesses (OpenCode, Codex CLI, Gemini CLI, Claude Code patterns, Aider, Crush, Goose, Pi, grok-cli…).
███ ████ ████ ████ ████
█ █ █ █ █ █ █
█████ ███ ███ ███ ████
█ █ █ █ █ █ █
█ █ █ █ ████ █ █
ask · xai/grok-4.6
/ commands · shift+tab posture · ctrl+c stop
affer v0.9.0 · afferInstall
npm install -g @affer/afferThat's it — npm pulls the pre-compiled native binary for your platform
(linux/macOS/Windows, x64 & arm64). No Bun, no Node toolchains, nothing else
to install. The command is affer.
First run opens a setup wizard: pick a provider, paste your API key once —
it's verified live, saved to ~/.affer2/config.json (chmod 600), and affer
handles everything after that. Switch anytime with /connect inside the app.
Affer is a single Bun/TypeScript program. To run from source or build your own binary:
git clone <repo> && cd affer
bun index.ts --help # run from source
bun build --compile index.ts --outfile affer # self-contained binaryConfigure
Affer defaults to the zai provider. Set one API key:
export ZAI_API_KEY=...…or use any of the 13 supported providers:
| Provider | Env key |
|---|---|
| zai (default) | ZAI_API_KEY |
| anthropic | ANTHROPIC_API_KEY |
| openai | OPENAI_API_KEY |
| google | GOOGLE_API_KEY |
| groq | GROQ_API_KEY |
| mistral | MISTRAL_API_KEY |
| deepseek | DEEPSEEK_API_KEY |
| xai | XAI_API_KEY |
| together | TOGETHER_API_KEY |
| openrouter | OPENROUTER_API_KEY |
| opencode zen | OPENCODE_API_KEY (60+ models incl. free tiers) |
| ollama / lmstudio | (local, no key) |
Also supported: AFFER_PROVIDER, AFFER_MODEL, AFFER_API_KEY (fallback for any provider).
For zai gateways: ZAI_BASE_URL (default https://api.z.ai/api/paas/v4), plus optional ZAI_CHAT_ID / ZAI_TOKEN / ZAI_USER_ID.
Usage
affer # interactive TUI (default on a terminal)
affer --plain # legacy readline REPL
affer -p "fix the tests" # one-shot task
affer -p "..." --yolo # one-shot, no approval prompts
affer -c # continue the latest session
affer -r <session-id> # resume a specific sessionInside the TUI
| Key | Action |
|---|---|
| tab | complete /commands and arguments |
| shift+tab | cycle posture plan → ask → auto → full |
| ctrl+c | interrupt the agent (busy) / clear input / exit (idle ×2) |
| ctrl+j / alt+enter | newline — multi-line prompts |
| ctrl+g | open the prompt in $EDITOR |
| ctrl+a / ctrl+e | start / end of line |
| ctrl+w / ctrl+u / ctrl+k | delete word / line / to end of line |
| ctrl+l | clear the screen |
| ↑ / ↓ | input history (inside a multi-line buffer: move lines) |
| esc | clear input / drop queued messages |
| y / n / a | answer permission prompts |
| alt+b / alt+f / ctrl+← / ctrl+→ | word-wise cursor motion |
Queue while busy: keep typing while the agent works — press enter to queue
your message; it sends automatically when the current task finishes. Type / —
filtered command palette; /model, /provider, /posture, /theme open
argument pickers with ↑↓ + enter (exact /help + enter runs immediately).
Slash commands
/help /connect /model /provider /posture /plan /yolo /goal /theme
/memory /todos /diff /undo /restore /checkpoints /compact /clear
/init /sessions /cost /version /exit
Features
- Interactive TUI — compact boxed header, bordered prompt, command palette (type
/— filtered list with descriptions, ↑↓ + tab/enter), tool cards (●/└plus a dim summary line), live reasoning tail and a braille spinner with elapsed time. Light-terminal safe: no background fills, only foreground accents. Zero dependencies. - 6 themes —
/theme affer | light | ember | gruvbox | dracula | mono(saved globally,lightauto-selected on light terminals). Pure-ASCII mode withAFFER_ASCII=1. - Zero-config onboarding — first launch walks you through provider + API key, verifies the key live, saves it, done.
/connectre-runs it anytime.NO_COLOR=1andFORCE_COLORare respected. - 13 providers — OpenAI-compatible SSE adapters (streaming + tool-call fragment reassembly by index, abort-aware retries with
Retry-After,reasoning/reasoning_contentfor DeepSeek/OpenRouter), Anthropic native with prompt caching, tool-result merging andstop_reasonmapping,zaivia its OpenAI-compatible endpoint, live/v1/modelswith a static fallback, o-series/GPT-5max_completion_tokens. - 4 postures —
plan(read-only —todo_writeis still allowed, it is the plan),ask(approve writes/commands),auto,full(hard blocklist still applies). Protected paths (.git,.affer2) can never be written. - Sessions & resume — every session persisted atomically as JSON with auto-titles;
-cresumes the latest session for the current directory and warns when continuing elsewhere. - Checkpoints — file snapshots per turn under
~/.affer2/sessions/checkpoints/<id>;/undoconsumes its checkpoint,/checkpointslists restorable turns,/restore <turn>replays a point in time.apply_patchtargets are backed up too. - LLM context compaction — auto + manual (
/compact): the older conversation is summarized into a structured handoff note (Objective / Key Knowledge / Work State / Next Step / Relevant Files); inflating summaries are rejected; stub fallback when the summarizer fails. Split is group-safe sotool_callsare never orphaned. - Todo planning — Codex-style
todo_write(full-list rewrite, onein_progress), rendered as a plan card in the TUI, inspectable via/todos. - Git auto-commit — opt-in with
AFFER_GIT=1: stages only the touched files and commits (affer: <task>). Checkpoints cover undo in all cases. - Subagents — read-only explore tasks with depth limits; children receive only read-only tools and share the parent's abort signal.
- Toolset — shell (process-group kill,
head+tailfor long output, Windowstaskkillfallback), read/write/edit files (aider-grade match ladder: exact → uniform-indent → whitespace-normalized →...elision → closest-lines hint, plus a fix for thevoid endinfinite loop), Codex V4Aapply_patch(multi-file, context-anchored, 5-pass fuzzy seek, unified-diff fallback, blank-line handling), glob (**crosses directories,{a,b}alternations), grep (ignore_case, binary skip), todo, subagent — with a hard-coded dangerous-command blocklist that no posture can bypass. Paths are resolved through a singlepaths.tshelper so Windows absolute paths work and the classic prefix bug (/proj2passing for/proj) is gone. - Unattended-safe — approvals deny instead of hanging when stdin isn't a TTY; truncated tool calls are poisoned instead of executed;
run_commandand provider retries honourAbortSignal.
SDK
Use Affer programmatically — zero deps, same harness the CLI uses:
import { createAgent, listProviders } from "./sdk.ts";
const agent = createAgent({
provider: "openai",
model: "gpt-4o",
events: {
onText: (t) => process.stdout.write(t),
onToolStart: (name) => console.log(`→ ${name}`),
},
});
await agent.run("fix the failing tests in ./src");Re-exports for embedding:
import { Agent, SessionStore, listSessions, CheckpointStore } from "./sdk.ts";
import { repoMap, scanSymbols, buildSystemPrompt } from "./sdk.ts";
import { TOOL_DEFS, executeTool, executeToolAsync, SPAWN_AGENT_DEF } from "./sdk.ts";
import { checkPolicy, HARD_BLOCKLIST, diffForEdit, classifyCommand } from "./sdk.ts";
import { compactMessages, estTokens, verifyKey, VERSION } from "./sdk.ts";
import { Tui, THEMES, setTheme, parseKeys, headerLines } from "./sdk.ts";
import { G, SPINNER, ASCII } from "./sdk.ts";
import type { Config, ToolDef, Message, AgentEvents } from "./sdk.ts";createAgent(opts)— resolves config (env < file < flags), creates session + checkpoints, returnsAgentagent.compact()— LLM context compaction with stub fallbacklistProviders()/listModels(provider)/verifyKey(provider, key)— provider registry + live key checklistSessions(dir?)— recent sessions, newest firstrepoMap(cwd)/buildRepoMap(cwd)/scanSymbols(file, src)— ctags-like repo overview for promptsAgent,SessionStore,CheckpointStore,TOOL_DEFS,checkPolicy— low-level harness primitivesTui/THEMES/setTheme— the whole TUI is embeddable
License
MIT
