Skip to main content

@tokenring-ai/cli

The @tokenring-ai/cli package provides a comprehensive command-line interface for interacting with TokenRing AI agents. This terminal-based interface enables users to manage agents, execute commands, and handle human interface requests with a rich, responsive UI using raw terminal rendering with ANSI escape codes.

Overview

The CLI package integrates seamlessly with the TokenRing agent framework, providing an interactive terminal interface for agent communication. It supports real-time streaming of agent output, interactive input editing, command completion, file path completion, and handling of agent questions and interaction requests.

Key Features

  • Raw Terminal UI: Direct terminal rendering using ANSI escape codes for maximum compatibility
  • Agent Management: Spawn, select, and interact with multiple agent types
  • Interactive Chat: Real-time streaming of agent output with syntax highlighting and markdown formatting
  • Command History: Navigate previous inputs with arrow keys and Ctrl+P/N
  • Auto-completion: Command auto-completion with Tab navigation
  • File Path Completion: Workspace file search using @ syntax with arrow key navigation
  • Human Interface Handling: Interactive handling of agent questions, follow-ups, and interaction requests
  • Responsive Layout: Adapts to different terminal sizes with incremental rendering
  • Customizable Theme: Full theming support for colors and styling
  • Background Loading Screen: Optional loading screen while agents initialize
  • Graceful Shutdown: Proper signal handling and cleanup with abort signals
  • Markdown Styling: Applied markdown formatting to terminal output
  • Bracketed Paste: Support for bracketed paste mode for efficient text input
  • Verbose Mode: Toggle visibility of reasoning and artifact output
  • Model/Tools Selection: Quick access to change agent configuration

Core Components

AgentCLI Service

The main service that manages CLI operations, including user input, agent selection, and interaction handling.

Interface:

class AgentCLI implements TokenRingService {
readonly name = "AgentCLI";
description = "Command-line interface for interacting with agents";

constructor(
readonly app: TokenRingApp,
readonly config: z.infer<typeof CLIConfigSchema>
);

async run(signal: AbortSignal): Promise<void>;
}

Constructor Parameters:

  • app: The TokenRingApp instance to manage agents
  • config: CLI configuration object matching CLIConfigSchema

Methods:

MethodDescriptionParametersReturns
runStarts the CLI interface and manages agent interactionssignal: AbortSignalPromise<void>

Behavior:

  • Displays loading screen (if no auto-start agent configured)
  • Presents agent selection screen
  • Spawns selected agent and enters interaction loop
  • Handles SIGINT for graceful shutdown
  • Restarts agent selection after agent completion (unless startAgent.shutdownWhenDone is true)
  • Supports automatic agent spawning with optional initial prompt
  • Properly cleans up terminal state on exit

Agent Loop Operations:

The AgentCLI service uses an AgentLoop instance to handle individual agent interactions:

  • Event Processing: Consumes agent events and renders them to the terminal
  • Execution State Sync: Syncs with agent execution state to show appropriate UI indicators
  • Input Collection: Gathers user input via the RawChatUI component
  • Human Request Handling: Processes human interface requests from agents
  • Signal Handling: Responds to abort signals and handles graceful shutdown

Event Types Handled:

Event TypeDescription
agent.createdDisplay agent creation message
agent.stoppedShutdown the interaction loop
output.chatStream chat output with formatting
output.reasoningStream reasoning output with formatting (when verbose)
output.info/warning/errorDisplay system messages
output.artifactDisplay artifact information (when verbose)
output.responseDisplay response status
input.receivedDisplay user input
input.interactionHandle interaction requests
cancelDisplay cancellation messages

AgentLoop Class

Handles the interactive loop for individual agents, managing input collection, event rendering, and human request handling.

Interface:

class AgentLoop {
constructor(
readonly agent: Agent,
readonly options: AgentLoopOptions
);

async run(externalSignal: AbortSignal): Promise<void>;
}

AgentLoopOptions Interface:

interface AgentLoopOptions {
availableCommands: CommandDefinition[];
config: z.infer<typeof CLIConfigSchema>;
}

Properties:

  • agent: The Agent instance to interact with
  • options: Configuration including available commands and CLI config

Methods:

MethodDescriptionParametersReturns
runStarts the agent interaction loopexternalSignal: AbortSignalPromise<void>

Event Handling: The AgentLoop processes the following agent events:

  • agent.created: Display agent creation message
  • agent.stopped: Shutdown the interaction loop
  • output.chat: Stream chat output with formatting
  • output.reasoning: Stream reasoning output with formatting
  • output.info/warning/error: Display system messages
  • output.artifact: Display artifact information
  • output.response: Display response status
  • input.received: Display user input
  • input.interaction: Handle interaction requests

State Management:

  • Tracks event cursor for incremental updates
  • Subscribes to AgentEventState for real-time updates
  • Handles abort signals for graceful cancellation
  • Manages UI lifecycle with proper cleanup

RawChatUI Class

The main chat UI component that handles terminal rendering, input editing, and interaction management. This is a raw terminal-based UI that works directly with ANSI escape codes for maximum compatibility and performance.

Interface:

class RawChatUI {
constructor(options: RawChatUIOptions);

start(): void;
stop(): void;
renderEvent(event: AgentEventEnvelope): void;
syncState(state: AgentEventState): void;
flash(text: string, tone?: FlashMessage["tone"], durationMs?: number): void;
}

RawChatUIOptions Interface:

interface RawChatUIOptions {
agent: Agent;
config: z.output<typeof CLIConfigSchema>;
commands: CommandDefinition[];
onSubmit: (message: string) => void;
onOpenAgentSelection: () => void;
onDeleteIdleAgent: () => void;
onAbortCurrentActivity: () => boolean;
}

Properties:

  • chatEditor: Multi-line input editor for chat messages
  • transcript: Array of transcript entries showing conversation history
  • followupEditors: Map of editors for follow-up interactions
  • questionSessions: Map of inline question sessions
  • completionState: Command completion state
  • fileSearchState: File search state for @ syntax

Methods:

MethodDescriptionParameters
startAttaches terminal and starts rendering-
stopDetaches terminal and stops rendering-
renderEventRenders an agent event to the transcriptevent: AgentEventEnvelope
syncStateSynchronizes UI with agent statestate: AgentEventState
flashShows a temporary flash messagetext: string, tone?: FlashMessage["tone"], durationMs?: number

Keyboard Shortcuts:

  • Ctrl+C: Cancel current activity or exit the CLI
  • Ctrl+L: Clear and replay the screen
  • Alt+A / F1: Open agent selection
  • Alt+M / F3: Open model selector
  • Alt+T / F2: Open tools selector
  • Alt+V / F4: Toggle verbose mode
  • Alt+Q / F6: Toggle optional questions
  • Tab: Command or file completion
  • Escape: Cancel current activity or close picker
  • Ctrl+O: Insert newline
  • Ctrl+P / Up: Browse command history (previous)
  • Ctrl+N / Down: Browse command history (next)
  • Up/Down: Navigate completion lists
  • PageUp/PageDown: Page through completion lists

Input Editor Features:

  • Multi-line text editing with cursor navigation
  • Word navigation (Alt+B/F)
  • Line navigation (Home/End)
  • Delete operations (Ctrl+U/K/W/D)
  • Bracketed paste support
  • History navigation with Ctrl+P/N and arrow keys

Internal Utilities

The CLI package includes internal utilities that support the main functionality. These are not exported from the main package entry point but are available for internal use:

  • commandPrompt: Provides a prompt implementation using a shared Node.js readline interface
  • PartialInputError: Error class thrown when input is interrupted but contains non-empty buffer
  • applyMarkdownStyles: Utility function that applies terminal-friendly styling to markdown text (available via @tokenring-ai/cli/utility/applyMarkdownStyles)

applyMarkdownStyles Utility

Utility function that applies terminal-friendly styling to markdown text. Converts markdown syntax into ANSI-colored terminal output.

Interface:

function applyMarkdownStyles(text: string): string

Parameters:

  • text: Markdown-formatted text to style

Returns:

  • Styled text with ANSI color codes

Supported Markdown Elements:

ElementMarkdownTerminal Styling
Code blocks language ```Gray horizontal line with language
Horizontal rules---, ***, ___Gray line (60% of terminal width)
Unordered lists*, -, +Yellow bullet point
Ordered lists1., 2.Yellow number
Headings# HeadingBold + Underlined
Blockquotes> quoteGray vertical bar + italic
Bold**text** or __text__Bold
Italic*text* or _text_Italic
Strikethrough~~text~~Strikethrough
Inline code`code`White background, black text
Links[text](url)Cyan underlined text + gray URL

Usage:

import applyMarkdownStyles from '@tokenring-ai/cli/utility/applyMarkdownStyles';

const markdown = `
# Agent Status

## Overview
- Agent is running
- 5 tools enabled

### Code Example
\`\`\`typescript
const result = await agent.execute();
\`\`\`

> Note: This is a blockquote

**Important**: Always check the logs
`;

const styled = applyMarkdownStyles(markdown);
console.log(styled);

InputEditor Class

Multi-line text editor component for chat input and follow-up responses.

Features:

  • Cursor navigation with arrow keys
  • Word navigation (Alt+B/F)
  • Line navigation (Home/End)
  • Delete operations (Backspace, Delete, Ctrl+U/K/W/D)
  • Multi-line support with Enter
  • Bracketed paste support

Usage:

import InputEditor from '@tokenring-ai/cli/raw/InputEditor';

const editor = new InputEditor();
editor.setText('Hello, World!');
editor.insert('\nNew line');
console.log(editor.getText());
console.log(editor.getCursor());

FileSearch Module

Workspace file search functionality for @ syntax completion.

Features:

  • Lazy-loading of workspace file index
  • Fuzzy matching on file paths
  • Keyboard navigation (Up/Down, PageUp/PageDown)
  • Insert selected path with Tab or Enter
  • Error handling for file system operations

Usage:

import { findActiveFileSearchToken, getFileSearchMatches } from '@tokenring-ai/cli/raw/FileSearch';

// Find file search token in input
const token = findActiveFileSearchToken(input, cursor);
if (token) {
const matches = getFileSearchMatches(workspaceFiles, token.query, 48);
// Display matches and allow selection
}

InlineQuestions Module

Handles inline question sessions for agent interaction requests.

Features:

  • Text input questions
  • Tree selection questions
  • File selection questions
  • Form-based multi-field questions
  • Auto-submit with timer support
  • Optional question picker

Usage:

import { createInlineQuestionSession } from '@tokenring-ai/cli/raw/InlineQuestions';

const session = createInlineQuestionSession(question, {
onSubmit: (result) => console.log('Response:', result),
onCancel: () => console.log('Cancelled'),
onRender: () => render(),
listFileSelectEntries: (path) => listDirectory(path),
}, question.message);

// Handle keypress
session.handleKeypress(input, key);

CommandCompletions Module

Command auto-completion functionality for the CLI.

Features:

  • Context-aware command completion
  • Tab navigation through matches
  • Insert selected command with Tab or Enter
  • Description preview for selected command

Usage:

import { getCommandCompletionContext } from '@tokenring-ai/cli/raw/CommandCompletions';

const context = getCommandCompletionContext(input, cursor, commands);
if (context) {
const matches = context.matches;
// Display matches and allow selection
}

NativeScreens Module

Contains loading screen and agent selection screen implementations.

LoadingScreen: Displays a loading screen with animated spinner and configurable banner while the application initializes.

Features:

  • Animated spinner with progress (braille spinner animation)
  • Responsive banner selection based on terminal width (wide/narrow/compact)
  • Random loading messages from a curated list
  • Automatic width detection for banner selection
  • Abort signal support for graceful cancellation

AgentSelectionScreen: The main screen for selecting, spawning, or connecting to agents.

Features:

  • Spawn Agents: Create new agent instances from available configurations in AgentManager
  • Connect to Agents: Connect to already running agents from AgentManager
  • Open Web Applications: Launch web browsers connected to SPA resources from WebHostService
  • Run Workflows: Execute predefined workflows from WorkflowService

Action Types:

ActionFormatDescription
Spawnspawn:agentTypeCreate a new agent of the specified type
Connectconnect:agentIdConnect to an existing running agent
Openopen:urlOpen a web application in the system browser
Workflowworkflow:workflowKeyExecute a workflow and spawn an agent

Preview Panel:

  • Shows agent description and enabled tools when hovering over spawn options
  • Displays agent status (idle/running) for connected agents
  • Shows workflow description for workflow options
  • Shows web application URL for SPA resources

Agent Selection Categories:

The selection screen organizes options into categories:

  1. Web Application: SPA resources from WebHostService
  2. Running Agents: Currently active agents from AgentManager
  3. Agent Types: Configurable agent types (category defined in agent config)
  4. Workflows: Available workflows from WorkflowService

Keyboard Navigation:

  • Up/Down arrows or j/k: Move selection
  • Enter: Confirm selection
  • Escape/q: Cancel and quit
  • Ctrl+C: Interrupt and quit

Services

AgentCLI

The CLI package implements the TokenRingService interface through the AgentCLI class.

Service Registration:

import TokenRingApp from '@tokenring-ai/app';
import AgentCLI from '@tokenring-ai/cli';

const app = new TokenRingApp();

app.addServices(new AgentCLI(app, {
chatBanner: 'TokenRing CLI',
loadingBannerNarrow: 'Loading...',
loadingBannerWide: 'Loading TokenRing CLI...',
loadingBannerCompact: 'Loading',
screenBanner: 'TokenRing CLI',
verbose: false,
}));

await app.start();

Service Behavior:

The AgentCLI service manages the complete CLI lifecycle:

  1. Loading Screen: Displays a loading screen while the application initializes (unless startAgent is configured)
  2. Agent Selection: Presents an interactive agent selection screen with categories for:
    • Web Applications (SPAs hosted by WebHostService)
    • Running Agents (existing agents from AgentManager)
    • Agent Types (spawnable agent configurations)
    • Workflows (executable workflows from WorkflowService)
  3. Agent Spawning: Creates new agents or connects to existing ones based on selection
  4. Interaction Loop: Manages the agent interaction loop via AgentLoop
  5. Signal Handling: Handles SIGINT for graceful shutdown
  6. Agent Lifecycle: After agent completion, returns to agent selection (unless startAgent.shutdownWhenDone is true)
  7. Cleanup: Properly restores terminal state on exit

Configuration

The CLI plugin supports configuration options that define the user interface behavior and appearance.

Configuration Schema:

const CLIConfigSchema = z.object({
chatBanner: z.string(),
loadingBannerNarrow: z.string(),
loadingBannerWide: z.string(),
loadingBannerCompact: z.string(),
screenBanner: z.string(),
uiFramework: z.enum(['ink', 'opentui']).default('opentui'),
verbose: z.boolean().default(false),
startAgent: z.object({
type: z.string(),
prompt: z.string().optional(),
shutdownWhenDone: z.boolean().default(true),
}).optional(),
});

Configuration Options:

OptionTypeRequiredDefaultDescription
chatBannerstringYes-Banner message displayed during agent chat sessions
loadingBannerNarrowstringYes-Banner for narrow terminal windows during loading
loadingBannerWidestringYes-Banner for wide terminal windows during loading
loadingBannerCompactstringYes-Banner for compact terminal layouts during loading
screenBannerstringYes-Banner message displayed on all interactive screens
uiFramework'ink' | 'opentui'No'opentui'UI rendering framework to use (currently only raw terminal is implemented)
verbosebooleanNofalseEnable verbose output including reasoning and artifacts
startAgentobjectNoundefinedOptional agent to automatically spawn on startup
startAgent.typestringIf startAgent-Agent type to spawn
startAgent.promptstringIf startAgentundefinedInitial prompt to send to the agent
startAgent.shutdownWhenDonebooleanIf startAgenttrueWhether to shutdown after agent completes

Configuration Example:

const config = {
cli: {
chatBanner: 'TokenRing CLI',
loadingBannerNarrow: 'Loading...',
loadingBannerWide: 'Loading TokenRing CLI...',
loadingBannerCompact: 'Loading',
screenBanner: 'TokenRing CLI',
uiFramework: 'opentui',
verbose: true,
startAgent: {
type: 'coder',
prompt: 'Write a function to calculate Fibonacci',
shutdownWhenDone: true,
},
},
};

Keyboard Shortcuts

The CLI provides comprehensive keyboard shortcuts for efficient interaction:

General Navigation

ShortcutAction
Ctrl+CCancel current activity or shut down idle agent
Ctrl+LClear and replay the screen (full replay)
Alt+A / F1Open agent selection screen
EscapeCancel current activity or close picker

Model and Tools

ShortcutAction
Alt+M / F3Trigger "model select" command (opens model selector)
Alt+T / F2Trigger "tools select" command (opens tools selector)
Alt+V / F4Toggle verbose mode (show/hide reasoning and artifacts)

Questions and Interactions

ShortcutAction
Alt+Q / F6Toggle optional questions picker

Input Editing

ShortcutAction
TabCommand completion or insert selected file search match
Ctrl+O / Meta+Enter / Shift+EnterInsert newline
Ctrl+P / UpBrowse command history (previous) or move up in completions
Ctrl+N / DownBrowse command history (next) or move down in completions
PageUp / PageDownPage through completions
Ctrl+AMove to start of line
Ctrl+EMove to end of line
Ctrl+UDelete to start of line
Ctrl+KDelete to end of line
Ctrl+WDelete word backward
Ctrl+DDelete forward
Alt+BMove word left
Alt+FMove word right
HomeMove to start of line
EndMove to end of line
BackspaceDelete character before cursor
DeleteDelete character after cursor

Completion Navigation

When command completion or file search is active:

ShortcutAction
Up/DownNavigate through matches
PageUp/PageDownPage through matches (5 at a time)
Tab / EnterInsert selected match
EscapeDismiss completion/search

Input Handling

The CLI package handles interactive input through the RawChatUI class, which supports various agent interaction types.

Chat Input

The main chat input supports:

  • Multi-line text editing: Use Ctrl+O, Meta+Enter, or Shift+Enter to insert newlines
  • Command completion: Type / to trigger command auto-completion
  • File path completion: Type @ to trigger workspace file search
  • History navigation: Use Ctrl+P/N or arrow keys when at the first/last line

File Search (@ syntax)

Type @ followed by a search query to find files in the workspace:

# Example usage in chat input:
Write code for @utils/helper.ts

Features:

  • Real-time indexing of workspace files via FileSystemService.glob()
  • Scoring-based match ranking (exact matches, path depth, character sequences)
  • Navigation with Up/Down arrow keys or Ctrl+P/N
  • Page navigation with PageUp/PageDown
  • Insert selected path with Tab or Enter
  • Dismiss with Escape

Command Completion (/ syntax)

Type / at the start of a line to trigger command auto-completion:

# Example usage:
/agen # Shows: /agent <description>

Features:

  • Auto-completion for all registered commands from AgentCommandService
  • Navigation with Up/Down arrow keys or Ctrl+P/N
  • Page navigation with PageUp/PageDown
  • Insert selected command with Tab or Enter
  • Dismiss with Escape

Question Types

The CLI supports the following question types from agents via ParsedInteractionRequest:

TypeDescriptionInteraction
Text InputMulti-line text input with cursor navigationEnter to submit, Alt+Enter for newline, Esc to cancel
Tree SelectHierarchical tree selection for structured choicesArrows to navigate, Space to toggle, Enter to submit, Right/Left to expand/collapse
File SelectFile system browser for file/directory selectionArrows to navigate, Space to expand/select directories, Enter to submit, Right/Left to expand/collapse
FormMulti-section forms combining multiple field typesNavigate through fields with Enter, Esc to cancel current section
FollowupSimple follow-up prompts for additional inputEnter to submit, Alt+Enter/Shift+Enter for newline

All question handling is done inline in the terminal with responsive layout adaptation. Optional questions can be accessed via Alt+Q / F6.

Theme Configuration

The CLI uses a color theme defined in theme.ts that controls the appearance of all UI elements.

Theme Properties:

const theme = {
// Agent selection
agentSelectionBanner: '#ffffff',
agentSelectionBannerBackground: '#2c2c2c',

// Question screen
questionScreenBanner: '#ffffff',
questionScreenBannerBackground: '#cf6e32',

// General panel background style
panelBackground: '#1e1e1e',
screenBackground: '#1e1e1e',

// Ask screen
askMessage: '#00BCD4FF',

// Confirmation screen
confirmYes: '#66BB6AFF',
confirmNo: '#EF5350FF',
confirmInactive: '#9E9E9EFF',
confirmTimeout: '#FFEB3BFF',

// Chat styles
chatOutputText: '#66BB6AFF',
chatReasoningText: '#FFEB3BFF',
chatPreviousInput: '#8c6ac6',
chatSystemInfoMessage: '#64B5F6FF',
chatSystemWarningMessage: '#FFEB3BFF',
chatSystemErrorMessage: '#EF5350FF',
chatDivider: '#9E9E9EFF',
chatSpinner: '#FFEB3BFF',
chatInputReceived: '#6699CCFF',
chatInputHandledSuccess: '#99CC99FF',
chatQuestionRequest: '#00BCD4FF',
chatQuestionResponse: '#00BCD4FF',
chatReset: '#AB47BCFF',
chatAbort: '#EF5350FF',

// Box styles
boxTitle: '#FFF176FF',

// Tree Selection screen
treeMessage: '#00BCD4FF',
treePartiallySelectedItem: '#FFF176FF',
treeFullySelectedItem: '#66BB6AFF',
treeNotSelectedItem: '#9E9E9EFF',
treeHighlightedItem: '#FFEB3BFF',
treeTimeout: '#FFEB3BFF',

// Loading screen
loadingScreenBackground: '#27292c',
loadingScreenBannerBackground: '#2c2e32',
loadingScreenText: '#f0f9ff',
} as const;

Theme Usage:

The theme is automatically applied to all UI components:

  • Terminal output: Uses chalk.hex() with theme values
  • UI elements: Theme colors are applied consistently across all screens

Integration

Integration with Agent System

The CLI integrates with the agent system through:

  1. Agent Selection: Presents available agents from AgentManager service
  2. Event Subscription: Subscribes to AgentEventState for real-time updates
  3. Input Handling: Sends user input via agent.handleInput()
  4. Question Responses: Sends responses to agent questions via agent.sendInteractionResponse()
  5. Command Registration: Registers chat commands via AgentCommandService

Integration with WebHostService

The CLI integrates with WebHostService to display and launch web applications:

// WebHostService provides SPA resources that appear in the agent selection screen
// Selecting a web application option opens it in the system browser

Integration with WorkflowService

The CLI integrates with WorkflowService to execute workflows:

// Workflows appear in the agent selection screen under "Workflows" category
// Selecting a workflow spawns an agent running that workflow

Plugin Registration

import cliPlugin from '@tokenring-ai/cli';

app.install(cliPlugin, {
cli: {
chatBanner: 'TokenRing CLI',
loadingBannerNarrow: 'Loading...',
loadingBannerWide: 'Loading TokenRing CLI...',
loadingBannerCompact: 'Loading',
screenBanner: 'TokenRing CLI',
verbose: false,
},
});

Service Registration

import AgentCLI from '@tokenring-ai/cli';

app.addServices(new AgentCLI(app, {
chatBanner: 'TokenRing CLI',
loadingBannerNarrow: 'Loading...',
loadingBannerWide: 'Loading TokenRing CLI...',
loadingBannerCompact: 'Loading',
screenBanner: 'TokenRing CLI',
verbose: false,
}));

Command Registration

The plugin automatically registers commands with AgentCommandService:

// In plugin.ts
app.waitForService(AgentCommandService, agentCommandService =>
agentCommandService.addAgentCommands(agentCommands)
);

State Management

The CLI package manages the following state components through the agent system:

  • AgentEventCursor: Tracks current position in the event stream
  • AgentEventState: Manages agent event history and rendering state
  • AgentExecutionState: Tracks agent execution status and active operations
  • CommandHistoryState: Manages input history for command completion

State Integration:

// Access event state
const eventState = agent.getState(AgentEventState);

// Get events since last cursor position
const events = eventState.yieldEventsByCursor(cursor);

// Update cursor after processing
cursor = eventState.getEventCursorFromCurrentPosition();

Usage Examples

Basic CLI Usage with Plugin

import TokenRingApp from '@tokenring-ai/app';
import cliPlugin from '@tokenring-ai/cli';

const app = new TokenRingApp();

const config = {
cli: {
chatBanner: 'TokenRing CLI',
loadingBannerNarrow: 'Loading...',
loadingBannerWide: 'Loading TokenRing CLI...',
loadingBannerCompact: 'Loading',
screenBanner: 'TokenRing CLI',
verbose: false,
},
};

app.install(cliPlugin, config);
await app.start();

Manual CLI Usage (without plugin)

import TokenRingApp from '@tokenring-ai/app';
import AgentCLI from '@tokenring-ai/cli';

const app = new TokenRingApp();

app.addServices(new AgentCLI(app, {
chatBanner: 'TokenRing CLI',
loadingBannerNarrow: 'Loading...',
loadingBannerWide: 'Loading TokenRing CLI...',
loadingBannerCompact: 'Loading',
screenBanner: 'TokenRing CLI',
verbose: false,
}));

await app.start();

Starting a Specific Agent

const config = {
cli: {
chatBanner: 'TokenRing CLI',
verbose: false,
startAgent: {
type: 'coder',
prompt: 'Help me debug this issue...',
shutdownWhenDone: false, // Keep agent running after completion
},
},
};

Enable Verbose Mode

const config = {
cli: {
chatBanner: 'TokenRing CLI',
verbose: true, // Show reasoning and artifacts
loadingBannerNarrow: 'Loading...',
loadingBannerWide: 'Loading TokenRing CLI...',
loadingBannerCompact: 'Loading',
screenBanner: 'TokenRing CLI',
},
};

Custom Theme Usage

import { theme } from '@tokenring-ai/cli/theme';
import chalk from 'chalk';

// Access theme colors for custom components
const successColor = theme.chatOutputText;
const warningColor = theme.chatSystemWarningMessage;
const errorColor = theme.chatSystemErrorMessage;

const errorText = chalk.hex(errorColor)('Error occurred');

Using Abort Signals

const abortController = new AbortController();

try {
const input = await commandPrompt({
rl,
message: 'Enter input:',
signal: abortController.signal,
});

console.log('Input:', input);
} catch (err) {
if (err instanceof DOMException && err.name === 'AbortError') {
console.log('Input was aborted');
}
}

Best Practices

Signal Handling

Always pass abort signals to long-running operations:

async function handleUserInput(signal: AbortSignal) {
try {
const input = await commandPrompt({
rl,
message: '>',
signal,
});
// Process input
} catch (err) {
if (err instanceof DOMException && err.name === 'AbortError') {
// Handle abort gracefully
}
}
}

Responsive Layout

The UI automatically adapts to terminal size. Handle minimum size requirements:

// Check terminal size before rendering
const { columns, rows } = process.stdout;
if (columns < 40 || rows < 10) {
console.log('Terminal too small. Resize to at least 40x10.');
return;
}

Error Handling

Handle errors gracefully in the agent loop:

try {
await agentLoop.run(signal);
} catch (error) {
process.stderr.write(formatLogMessages(['Error while running agent loop', error as Error]));
await setTimeout(1000);
}

Theme Consistency

Use theme colors consistently across components:

import { theme } from '@tokenring-ai/cli/theme';
import chalk from 'chalk';

const errorText = chalk.hex(theme.chatSystemErrorMessage)('Error occurred');

Markdown Styling

The CLI applies markdown styling to terminal output using applyMarkdownStyles:

import applyMarkdownStyles from '@tokenring-ai/cli/utility/applyMarkdownStyles';

const styledText = applyMarkdownStyles('# Heading\n- Item 1\n- Item 2');
console.log(styledText);

File Search Syntax

Use the @ syntax for file path completion in the chat input:

# Type @ followed by a search query to find files
Write code for @utils/helper.ts

The file search will:

  • Index all files in the workspace
  • Show matches as you type
  • Allow navigation with arrow keys
  • Insert the selected path with Tab or Enter

Terminal Requirements

The CLI requires a TTY terminal with minimum dimensions:

  • Minimum width: 40 columns
  • Minimum height: 10 rows

If the terminal is too small, the CLI will display a warning message and request resizing.

Terminal Features Required:

  • TTY mode support
  • Raw mode for keyboard input
  • Bracketed paste mode
  • ANSI escape code support
  • SIGWINCH signal handling for resize detection

Resize Handling:

  • The UI automatically detects terminal resize events
  • Full screen replay is triggered on resize
  • Content is reflowed to fit the new dimensions
  • A throttle mechanism prevents excessive re-rendering during rapid resize

Testing and Development

Running Tests

# Run tests
bun test

# Run tests in watch mode
bun run test:watch

# Run with coverage
bun run test:coverage

Building

# Type check
bun run build

Package Structure

The package uses TypeScript with ES modules:

{
"type": "module",
"exports": {
".": "./index.ts",
"./*": "./*.ts"
},
"types": "./dist-types/index.d.ts"
}

Directory Structure:

pkg/cli/
├── raw/ # Raw terminal UI components (internal)
│ ├── CommandCompletions.ts # Command completion logic and context extraction
│ ├── FileSearch.ts # File search scoring, matching, and @-token handling
│ ├── InlineQuestions.ts # Inline question session handling (text, tree, file, form)
│ ├── InputEditor.ts # Multi-line text editor with cursor navigation
│ ├── NativeScreens.ts # Loading screen and agent selection screen implementations
│ ├── RawChatUI.ts # Main chat UI implementation with incremental rendering
│ └── *.test.ts # Test files for raw components
├── utility/ # Utility functions
│ └── applyMarkdownStyles.ts # Markdown styling utility for terminal output
├── AgentCLI.ts # Main CLI service implementing TokenRingService
├── AgentLoop.ts # Agent interaction loop handler with event subscription
├── AgentSelection.ts # Agent selection result types and parsing utilities
├── commandPrompt.ts # Internal command prompt implementation (not exported)
├── index.ts # Package exports (AgentCLI, CLIConfigSchema)
├── plugin.ts # Plugin definition for app.install() integration
├── schema.ts # Configuration schema definition (CLIConfigSchema)
├── theme.ts # Color theme definitions for all UI elements
├── vitest.config.ts # Vitest test configuration
└── package.json # Package metadata

Dependencies

Runtime Dependencies

  • @tokenring-ai/app (0.2.0)
  • @tokenring-ai/ai-client (0.2.0)
  • @tokenring-ai/chat (0.2.0)
  • @tokenring-ai/agent (0.2.0)
  • @tokenring-ai/utility (0.2.0)
  • @tokenring-ai/web-host (0.2.0)
  • @tokenring-ai/workflow (0.2.0)
  • @tokenring-ai/filesystem (0.2.0)
  • zod (^4.3.6)
  • chalk (^5.6.2)
  • open (^11.0.0)

Development Dependencies

  • vitest (^4.1.1)
  • typescript (^6.0.2)
  • @tokenring-ai/agent: Agent framework for AI interactions
  • @tokenring-ai/app: Application framework and plugin system
  • @tokenring-ai/chat: Chat service and tool definitions
  • @tokenring-ai/utility: Utility functions for formatting and string manipulation
  • @tokenring-ai/web-host: Web server for serving resources and APIs
  • @tokenring-ai/workflow: Workflow definition and execution service
  • @tokenring-ai/filesystem: File system operations and directory tree navigation

License

MIT License - see LICENSE file for details.