examples/cli
An interactive REPL (examples/cli, package @lite-agent/example-cli) that wires the full stack on top of @lite-agent/sdk:
- streaming agent loop via
createLiteAgent, driven by a provider from@lite-agent/provider - permission gate — asks before
bash/write_file/edit_file - OS-level sandbox via
@lite-agent/sandbox-anthropic— degrades to noop on unsupported environments ask_user— the model can ask you questions (free text or numbered options)- session management — list / resume / clear / delete sessions from the REPL
- multi-line paste,
ESCto interrupt a run
Use it as a runnable reference for how to wire your own app.
Run
From the monorepo root:
The agent operates on the directory you launch it from (process.cwd()), while .env and skills always load from examples/cli/ itself — so you can cd into any project directory and run the REPL against it.
Configuration
Config is read from examples/cli/.env (via dotenv). All variables use the LITE_AGENT_ prefix:
src/model.ts turns these into a provider (anthropic(...) or openai(...) from @lite-agent/provider); protocol auto-detection means the same .env shape works for Claude and for OpenAI-compatible endpoints.
How it's wired
Everything happens in one createLiteAgent call (src/main.ts):
The wiring pattern worth copying:
- Policy + handlers are separate.
policy({ ask: [...] })decides when to ask;onApproval/onAskUserdecide how to ask. Swap the handlers for a GUI, a Slack bot, or an auto-approver without touching the policy. - Sandbox is defense-in-depth. The permission gate controls intent; the sandbox enforces an OS-level boundary regardless.
onUnavailablekeepsbashworking where Seatbelt/bubblewrap is missing. - Server-side history. Each turn sends only the new message —
agent.run([{ role: "user", content: text }])— and the kernel reloads the transcript via the agent's currentsessionId.
In the REPL
Input that doesn't start with / is sent to the model. q or exit quits.
Slash commands
Handled locally (never sent to the model):
Approvals and questions
[approve] bash {...}? [y/N]— the permission gate intercepted a tool call. Pressyto allow, anything else to deny. The keypress is read in raw mode, so there's no Enter to hit.[ask] ...— the model invokedask_user. Type free text, or the number(s) of the listed options (comma-separated for multi-select questions), then Enter.ESC— aborts the current run mid-stream and returns to the prompt.- Pasting multiple lines switches the prompt to multi-line mode; submit with a blank line.
What you see while a run streams
The REPL renders the typed AgentEvent stream from agent.run() directly:
As a wiring reference
If you're building your own UI on the SDK, src/main.ts (~290 lines, no dependencies beyond the packages and dotenv) shows the minimal complete loop: resolve a provider from env → createLiteAgent with policy + handlers + sandbox → consume the AgentEvent stream from agent.run() → route approvals / questions back through the handlers. Start from Getting started for the step-by-step version.