A starter template for building terminal CLI agents: an Ink chat UI wired to @mozaik-ai/core, a TypeScript runtime for collaborative, event-driven agents. Humans, agents, and observers join one runtime; semantic events fan out to situation handlers so you can compose reactive behaviors without a central scheduler.
Fork or copy this repo, rename the package, add tools and participants, and ship your own agent-backed CLI.
This repository is meant to be copied into a new project so you keep a clean git history.
npx degit jigjoy-ai/cli-agent-starter my-cli-agent
cd my-cli-agent
git init
git add .
git commit -m "Initial commit"
npm installReplace jigjoy-ai/cli-agent-starter with your fork or the published template URL if it moves. Replace my-cli-agent with your project folder name.
Then customize:
- Set
name(and optionallybin) inpackage.json. - Adjust branding and copy in
source/cli.tsx,source/app.tsx, and this README.
If you enable Template repository in the repo settings on GitHub, Use this template creates a new repository whose first commit is the template snapshot—also a straightforward way to start without inheriting long unrelated history.
Built against @mozaik-ai/core ^4.0.0 (see package.json).
| Concept | Where it lives |
|---|---|
defineRuntime — shared runtime, events, and runLoop |
source/runtime.ts |
createAgent — instruction, tools, situation handlers |
source/terminal/agent.ts |
createHuman observer — model.answer / function_call.started → UI |
source/ui-updater.ts |
runLoop — context update, inference, and tool execution |
source/terminal/agent.ts: message.sent handler |
Declarative Tool definitions |
source/terminal/tools.ts |
The Ink UI does not call OpenAI directly. It calls session.send(message), which publishes a message.sent event; the UI updater listens for assistant text and tool notifications and updates the UI through callbacks.
flowchart LR
subgraph ui [Ink UI]
App[app.tsx]
end
subgraph mozaik [Mozaik runtime]
Runtime((defineRuntime))
Agent[Terminal Agent]
Obs[UI updater]
User[Human user]
end
Tools[terminal tools / run_command]
OAI[OpenAI via runLoop]
App -->|session.send| User
User -->|sendMessage| Runtime
Agent -->|join| Runtime
Obs -->|join| Runtime
User -->|join| Runtime
Runtime -->|message.sent| Agent
Agent -->|runLoop| OAI
Agent --> Tools
Runtime -->|function_call.started / model.answer| Obs
Obs -->|callbacks| App
Flow in plain language
createAgentSessioncallsinitializeRuntime, then **join**s a human user, the terminal agent, and a UI observer. User messages go throughsendMessage(message, user.getId()).- The terminal agent is a
createAgentparticipant. Onmessage.sentfrom someone else it callsrunLoopwith the agent’s memory context and tools. Tool execution and the follow-up inference live inside the loop. - The UI updater is a
createHumanobserver. It handlesmodel.answerto surface assistant text to Ink, andfunction_call.startedto show which tool was invoked.
- Node.js ≥ 18 (see
package.jsonengines) @mozaik-ai/core^4.0.0 — upgrade or pin inpackage.jsonif you track a different minor- OpenAI API key —
runLooppicks a provider from the model name; this starter usesgpt-5.4
-
Install dependencies:
npm install
-
Configure credentials. Create a
.envin the project directory (or a parent directory — the CLI searches upward fromcwdand from the install location):OPENAI_API_KEY=sk-...
-
Build TypeScript:
npm run build
Run the compiled CLI:
node dist/cli.jsOr link globally after a build (command matches the "name" field in package.json):
npm link
cli-agentIn the TUI: type a message and press Enter. Use /exit, /quit, Escape, or Ctrl+C to quit (Escape exits via Ink’s useInput).
When the model calls run_command, output is also printed to stdout from the tool implementation (see source/terminal/tools.ts), which is useful for debugging alongside the chat transcript.
| Path | Role |
|---|---|
source/cli.tsx |
Entry: dotenv, meow help, render(<App />) |
source/app.tsx |
Ink UI, local chat state, createAgentSession hooks |
source/runtime.ts |
defineRuntime, RuntimeState, join / sendMessage / runLoop |
source/session.ts |
Wiring: initialize runtime, join user, agent, observer |
source/ui-updater.ts |
Observer situation handlers → UI callbacks |
source/terminal/agent.ts |
createAgent + message.sent → runLoop |
source/terminal/tools.ts |
Tool[] for run_command |
source/terminal/terminal.ts |
spawn-based command runner |
source/terminal/command-result.ts |
Structured command result type |
| Script | Command |
|---|---|
| Build | npm run build |
| Watch mode | npm run dev |
| Lint / format check / tests | npm test |
- Package:
@mozaik-ai/coreon npm — this repo pins^4.0.0; install or upgrade withnpm install @mozaik-ai/core@^4.0.0. - Examples: mozaik-examples —
terminal-agent, situation handlers,runLoop, interception, and more. - The upstream README documents
defineRuntime,createAgent/createHuman, situation handlers, andrunLoop. This starter focuses on one human + one agent + one observer as a minimal base.
To extend your CLI: add another createAgent or createHuman, join it to the same runtime, and register situation handlers for the events you care about (message.sent, model.answer, function_call.started, …).
MIT — see package.json.
