8.8 KiB
agentu
agentu is a small local coding agent written in Go. It provides a terminal chat UI with OpenAI-compatible providers, streaming responses, session-level model/provider switching, skills, approvals, and local tools.
v0.3.1
- TUI-first chat experience with a light theme by default.
- OpenAI-compatible
/v1/chat/completionsprovider support. - OpenAI Responses API (
/v1/responses) provider support. - Multiple providers from
~/.agentu/config.yaml. - Session-only provider, model, and thinking-level switching.
- Interactive approval for model-requested file writes and shell commands.
- Atomic file writes, per-file rollback snapshots, and multi-file patches.
- Project outlines with Go, TypeScript/JavaScript, and Rust symbols.
- Global Codex-style skills loaded from
~/.agentu/skills. - Persistent session index and in-memory task tracking.
- Built-in web search and URL fetching.
--yolomode for automatic file writes and shell execution.- Temporary
/btwside questions that can run while the main task continues.
Quick Start
mkdir -p ~/.agentu
cp agentu.example.yaml ~/.agentu/config.yaml
export AGENTU_API_KEY='your-api-key'
go run .
Use dark mode when your terminal is dark:
go run . --theme dark
By default, the TUI asks for approval before every model-requested file change
or shell command. Use --yolo only when those operations should run without
confirmation:
go run . --yolo
Config
By default, agentu reads:
~/.agentu/config.yaml
Use --config <path> to load another file.
providers:
loveuer:
api_type: chat
base_url: https://ai.loveuer.com
api_key: ${AGENTU_API_KEY}
models:
- id: deepseek-v4-flash
thinking: none
context: 256000
Web tools are enabled by default with a built-in no-key backend. agentu exposes
web_search for current or external web information and web_fetch for reading
a known URL.
Provider names are the keys under providers. At startup, agentu selects the
first provider by name. Use /model provider <name> to switch providers for the
current session.
api_type selects which API protocol the provider speaks:
chat OpenAI-compatible /v1/chat/completions (default)
responses OpenAI Responses API /v1/responses
The Responses API client converts the conversation history to Responses input
items (user/assistant messages, function_call, and
function_call_output), sends the system prompt as the top-level
instructions field, streams response.output_text.delta events, and supports
function calling through response.output_item.added,
response.function_call_arguments.delta, and response.output_item.done.
models is required. /model model <name> is restricted to that list. Each
entry is an object with:
id: model name sent to the provider.thinking: optional default thinking level for that model.context: optional context-window token count used for auto-compaction.
If model is omitted, agentu uses the first models entry. The agent block
is optional: working_dir, tool_timeout, system_prompt, and
max_context_tokens all have defaults. max_context_tokens overrides the
selected model's context when set.
Supported thinking values are:
none, middle, high, xhigh, max
When configured or changed with /model thinking ..., the value is sent as a
top-level request field. The default field depends on api_type: chat uses
thinking, while responses uses the official reasoning field, sent as
{"effort": ...} with agentu's middle level mapped to the official medium
value (none, high, xhigh, max pass through). Override with
thinking_param if a provider expects a different field name.
CLI Flags
go run . [flags]
--config <path>loads a YAML config file. Default:~/.agentu/config.yaml.--theme light|darkselects the TUI theme. Default:light.--plainuses the simple line-based REPL instead of the TUI.--yoloautomatically approves model-requested file writes and shell execution.--resume <id>resumes a saved session from~/.agentu/sessions.
TUI Controls
entersends the message.ctrl+jinserts a newline.uprecalls the previous input;ctrl+p/ctrl+nnavigate input history.- The input starts at one line and grows up to six lines.
page up/page downscrolls the transcript.esccancels a running response.- While a task is running,
/btw <question>asks a concurrent side question. - Entering only
.means “continue with the current task.” - At a tool approval prompt,
yapproves andnorescdenies the operation. - Type
/to show available commands. - In
--yolomode, type! <command>to run a shell command from the configured working directory.
Slash commands:
/btw <question>answers from a snapshot of the current context without adding the question or answer to conversation history. It never exposes tools and can run alongside the main task./clearresets conversation history./compactsummarizes older conversation history and keeps the newest ~20% of context, with a small recent-message floor./statusshows changed files withgit status --short./diff [--stat] [path...]shows the unstaged git diff./test [command...]runs a project test command; defaults togo test ./...for Go modules ornpm testfor Node projects./skillslists global skills./skills install <path-or-url>installs a skill and activates it in the current conversation./rollback [id]restores a file snapshot; without an ID it restores the newest snapshot./modelshows current provider, model, thinking, and switch usage./model provider <name>switches provider for the current session./model model <name>or/model <name>switches model for the current session. In the TUI, type/modelor/model modelto choose from configured model IDs in the candidate palette./model thinking <none|middle|high|xhigh|max>changes thinking for the current session./sessionslists saved sessions./resume [id]resumes by ID or opens an interactive picker./rename <name>renames the current session./newsaves the current session and starts a fresh one./exitor/quitexits.
Local Tools
These tools are always available:
file_readfile_listfile_searchwith optionalcontext_linesandmax_resultscode_symbolsfor Go packages, imports, types, functions, and methodsproject_outlinefor a gitignore-aware tree with Go, TypeScript/JavaScript, and Rust symbolstodofor conversation-local task trackinggit_statusshows changed filesgit_diffshows unstaged or staged diff outputgit_logshows recent commit history
Web tools are also available:
web_searchweb_fetch
In the TUI, these tools require approval by default and run automatically with
--yolo:
file_writefor creating or replacing whole filesfile_editfor surgical line-range or pattern edits to existing filesapply_patchfor atomic-style multi-file V4 patches, including dry runsshell_runfor non-interactive shell commands; output streams live into the TUI while the command runs instead of appearing only after completion
Before a file mutation, agentu stores an in-memory snapshot and includes its
rb_... ID in the tool result. Use /rollback or /rollback <id> to restore
it. Snapshots last for the lifetime of the process. The plain REPL remains
read-only unless --yolo is supplied because it has no interactive approval UI.
Use --yolo for prompts that ask agentu to run or inspect local commands, for
example:
请帮我运行 `go test ./...` 并总结结果
Global Skills
At startup, agentu loads both Codex-style directories containing SKILL.md
and legacy flat Markdown files from ~/.agentu/skills. Skill instructions are
added to the system prompt. Install a local directory, Markdown file, or direct
HTTP(S) Markdown URL from the TUI:
/skills install ./my-skill
/skills install https://example.com/SKILL.md
Directory installs preserve supporting files such as references/; symlinks
inside a source directory are rejected.
Development
Run the verification suite:
go test ./...
go vet ./...
go build .
Local config and build outputs are intentionally ignored by git.
Notes
- Provider/model/thinking changes are session-only; agentu does not write them
back to
~/.agentu/config.yaml. api_typeis per provider and cannot be changed at runtime; use/model provider <name>to switch to a provider configured with a different API type.- The config schema is intentionally strict during MVP development. Deprecated
fields such as
provideroractive_providerare rejected. - Session metadata is indexed in
~/.agentu/sessions/index.json; complete conversations remain stored as one JSON file per session.