Documentation Index
Fetch the complete documentation index at: https://mintlify.com/mblode/rubber-duck/llms.txt
Use this file to discover all available pages before exploring further.
This page documents the core TypeScript types exported by @rubberduck/cli.
Daemon Protocol Types
DaemonRequest
Discriminated union of all daemon request types.
type DaemonRequest = {
[M in DaemonMethod]: {
id: string;
method: M;
params: DaemonRequestMap[M];
};
}[DaemonMethod];
Each request has:
id — Unique request ID for correlation
method — One of the supported daemon methods
params — Type-safe parameters for that method
DaemonMethod
type DaemonMethod =
| "attach" // Attach to a workspace
| "follow" // Subscribe to session events
| "unfollow" // Unsubscribe from events
| "say" // Send a message
| "sessions" // List sessions
| "abort" // Stop the running agent
| "doctor" // Health checks
| "get_state" // Get session state
| "ping" // Liveness check
| "extension_ui_response" // Respond to UI request
| "voice_connect" // Connect voice session
| "voice_tool_call" // Execute voice tool
| "voice_state"; // Update voice state
DaemonRequestMap
Maps each method to its parameter type.
interface DaemonRequestMap {
ping: PingParams; // {}
attach: AttachParams; // { path?: string }
follow: FollowParams; // { sessionId?: string }
unfollow: UnfollowParams; // {}
say: SayParams; // { message: string; sessionId?: string }
sessions: SessionsParams; // { all?: boolean; workspaceId?: string }
abort: AbortParams; // { sessionId?: string }
doctor: DoctorParams; // {}
get_state: GetStateParams; // { sessionId?: string }
extension_ui_response: ExtensionUiResponseParams;
voice_connect: VoiceConnectParams;
voice_tool_call: VoiceToolCallParams;
voice_state: VoiceStateParams;
}
Key Parameter Types:
{ path?: string } // Workspace path (defaults to cwd)
{ message: string; sessionId?: string }
{ all?: boolean; workspaceId?: string }
ExtensionUiResponseParams
{
id: string; // Request ID from extension_ui_request
sessionId?: string;
value?: unknown; // User's input/selection
confirmed?: boolean; // For confirm prompts
cancelled?: boolean; // User cancelled
}
DaemonResponse
interface DaemonResponse {
id: string; // Matches request ID
ok: boolean; // Success flag
data?: Record<string, unknown>; // Response payload
error?: string; // Error message if ok=false
}
Example:
// Success
{ id: "req_123", ok: true, data: { sessionId: "abc" } }
// Error
{ id: "req_456", ok: false, error: "Session not found" }
DaemonEvent
Asynchronous events pushed from the daemon.
interface DaemonEvent {
event: string; // Event name (e.g., "pi_event")
sessionId: string; // Session that emitted the event
data: PiEvent | Record<string, unknown>; // Event payload
}
DaemonMessage
Union of responses and events (what the daemon sends over the socket).
type DaemonMessage = DaemonResponse | DaemonEvent;
Type Guards:
function isDaemonResponse(msg: DaemonMessage): msg is DaemonResponse;
function isDaemonEvent(msg: DaemonMessage): msg is DaemonEvent;
Pi Event Types
PiEvent
Discriminated union of all Pi agent events.
type PiEvent =
| AgentStartEvent
| AgentEndEvent
| TurnStartEvent
| TurnEndEvent
| MessageStartEvent
| MessageUpdateEvent
| MessageEndEvent
| ToolExecutionStartEvent
| ToolExecutionUpdateEvent
| ToolExecutionEndEvent
| AutoCompactionStartEvent
| AutoCompactionEndEvent
| AutoRetryStartEvent
| AutoRetryEndEvent
| ExtensionErrorEvent
| PromptErrorEvent
| ExtensionUiRequestEvent;
Agent Lifecycle Events
interface AgentStartEvent {
type: "agent_start";
}
interface AgentEndEvent {
type: "agent_end";
messages: unknown[]; // Final message list
}
Turn Events
interface TurnStartEvent {
type: "turn_start";
}
interface TurnEndEvent {
type: "turn_end";
message: AgentMessage;
toolResults: ToolResult[];
}
Message Events
interface MessageStartEvent {
type: "message_start";
message: AgentMessage;
}
interface MessageUpdateEvent {
type: "message_update";
message: AgentMessage;
assistantMessageEvent: AssistantMessageDelta;
}
interface MessageEndEvent {
type: "message_end";
message: AgentMessage;
}
interface ToolExecutionStartEvent {
type: "tool_execution_start";
toolName: string;
toolCallId: string;
args: Record<string, unknown>;
}
interface ToolExecutionUpdateEvent {
type: "tool_execution_update";
toolName: string;
toolCallId: string;
args: Record<string, unknown>;
partialResult: ToolContent; // Streaming output
}
interface ToolExecutionEndEvent {
type: "tool_execution_end";
toolName: string;
toolCallId: string;
result: ToolContent;
isError: boolean;
exitCode?: number; // For bash tools
}
Compaction Events
interface AutoCompactionStartEvent {
type: "auto_compaction_start";
reason: "threshold" | "overflow";
}
interface AutoCompactionEndEvent {
type: "auto_compaction_end";
aborted: boolean;
willRetry: boolean;
result: { summary: string; tokensBefore: number } | null;
errorMessage?: string;
}
Retry Events
interface AutoRetryStartEvent {
type: "auto_retry_start";
attempt: number;
maxAttempts: number;
delayMs: number;
errorMessage: string;
}
interface AutoRetryEndEvent {
type: "auto_retry_end";
attempt: number;
success: boolean;
finalError?: string;
}
Error Events
interface ExtensionErrorEvent {
type: "extension_error";
extensionPath: string;
event: string; // Event that threw
error: string; // Error message
}
interface PromptErrorEvent {
type: "prompt_error";
error: string;
}
UI Request Event
interface ExtensionUiRequestEvent {
type: "extension_ui_request";
id: string;
method:
| "select" // Choose from options
| "confirm" // Yes/no
| "input" // Text input
| "editor" // Multi-line input
| "notify" // Show notification
| "setStatus" // Set status message
| "setWidget" // Custom widget
| "setTitle" // Set window title
| "set_editor_text";
message?: string;
title?: string;
placeholder?: string;
prefill?: string;
options?: Array<string | { label: string; value: string }>;
notifyType?: "info" | "warning" | "error";
timeout?: number; // Auto-dismiss after ms
}
Type Guard:
function isExtensionUiRequestEvent(
event: PiEvent | Record<string, unknown>
): event is ExtensionUiRequestEvent;
Supporting Types
AgentMessage
interface AgentMessage {
id?: string;
role:
| "user"
| "assistant"
| "toolResult"
| "bashExecution"
| "custom"
| "branchSummary"
| "compactionSummary";
content?: string | ContentBlock[];
timestamp?: string;
}
ContentBlock
interface ContentBlock {
type: "text" | "tool_use" | "tool_result" | "thinking";
id?: string;
text?: string;
name?: string; // Tool name
input?: Record<string, unknown>; // Tool arguments
}
AssistantMessageDelta
Streaming update types:
type AssistantMessageDeltaType =
| "start"
| "text_start" | "text_delta" | "text_end"
| "thinking_start" | "thinking_delta" | "thinking_end"
| "toolcall_start" | "toolcall_delta" | "toolcall_end"
| "done"
| "error";
interface AssistantMessageDelta {
type: AssistantMessageDeltaType;
delta?: string; // Text/thinking delta
contentIndex?: number; // Block index
toolCall?: PiToolCall; // Tool being called
partial?: unknown; // Partial JSON
reason?: string; // Error reason
}
ToolContent
interface ToolContent {
content: Array<{ type: string; text?: string }>;
details?: {
truncation?: string; // "exceeded 2000 lines"
fullOutputPath?: string; // Path to full output file
};
}
interface ToolResult {
toolCallId: string;
toolName: string;
content: Array<{ type: string; text?: string }>;
isError: boolean;
}
Session & Workspace Types
Session
interface Session {
id: string;
name: string;
workspaceId: string;
piSessionFile: string; // Path to Pi session JSON
createdAt: string; // ISO timestamp
lastActiveAt: string;
isVoiceActive: boolean;
}
Workspace
interface Workspace {
id: string;
path: string; // Absolute path
createdAt: string;
lastActiveSessionId: string | null;
}
interface DaemonMetadata {
version: number;
workspaces: Workspace[];
sessions: Session[];
activeVoiceSessionId: string | null;
}
Pi State Types
PiState
Current state of a Pi session.
interface PiState {
sessionId: string;
sessionName: string;
sessionFile: string;
model: string; // e.g., "gpt-4o-mini"
thinkingLevel: string; // "off" | "minimal" | "low" | ...
messageCount: number;
pendingMessageCount: number;
isStreaming: boolean;
isCompacting: boolean;
autoCompactionEnabled: boolean;
}
PiSessionStats
Usage statistics for a session.
interface PiSessionStats {
sessionId: string;
sessionFile: string;
totalMessages: number;
userMessages: number;
assistantMessages: number;
toolCalls: number;
toolResults: number;
tokens: {
input: number;
output: number;
cacheRead: number;
cacheWrite: number;
total: number;
};
cost: number; // USD
}
Renderer Types
RendererOptions
interface RendererOptions {
json: boolean; // NDJSON mode
color: boolean; // ANSI colors
showThinking: boolean; // Show <thinking> blocks
verbose: boolean; // Debug output
}
EventRenderer
interface EventRenderer {
render(event: RendererPiEvent): void | Promise<void>;
cleanup(): void;
}
RendererPiEvent
type RendererPiEvent = PiEvent | AppHistoryEvent;
interface AppHistoryEvent {
type: "app_history_event";
appEventType: string; // "user_audio", "assistant_text", etc.
sessionID?: string;
timestamp?: string;
text?: string;
metadata?: Record<string, string>;
}
Utility Types
DoctorCheck
interface DoctorCheck {
name: string; // Check name
status: "ok" | "warn" | "fail";
message: string; // Human-readable result
}
Usage Examples
Type-Safe Request
import type { DaemonRequestMap, DaemonResponse } from '@rubberduck/cli';
type SayParams = DaemonRequestMap['say'];
// { message: string; sessionId?: string }
const params: SayParams = {
message: 'Hello',
sessionId: 'abc123'
};
const response: DaemonResponse = await client.request('say', params);
Event Type Narrowing
import type { PiEvent } from '@rubberduck/cli';
function handleEvent(event: PiEvent) {
switch (event.type) {
case 'message_update':
// TypeScript knows event.assistantMessageEvent exists
if (event.assistantMessageEvent.type === 'text_delta') {
console.log(event.assistantMessageEvent.delta);
}
break;
case 'tool_execution_start':
// TypeScript knows event.toolName and event.args exist
console.log(`Calling ${event.toolName} with`, event.args);
break;
}
}
UI Request Handling
import { isExtensionUiRequestEvent } from '@rubberduck/cli';
import type { ExtensionUiResponseParams } from '@rubberduck/cli';
client.onEvent(async (daemonEvent) => {
if (isExtensionUiRequestEvent(daemonEvent.data)) {
const uiEvent = daemonEvent.data;
let value: unknown;
if (uiEvent.method === 'confirm') {
value = await askYesNo(uiEvent.message);
}
const response: ExtensionUiResponseParams = {
id: uiEvent.id,
sessionId: daemonEvent.sessionId,
value,
confirmed: value === true
};
await client.request('extension_ui_response', response);
}
});
Constants
Path constants exported by the CLI for locating runtime files.
APP_SUPPORT
const APP_SUPPORT: string
Application support directory path.
Default: ~/Library/Application Support/RubberDuck
Override: Set RUBBER_DUCK_APP_SUPPORT environment variable.
SOCKET_PATH
const SOCKET_PATH: string
Unix domain socket path for daemon IPC.
Default: ~/Library/Application Support/RubberDuck/daemon.sock
Fallback: $TMPDIR/duck-<hash>.sock if default path exceeds Unix socket length limit.
const METADATA_PATH: string
Path to daemon metadata store (workspaces and sessions).
Value: ~/Library/Application Support/RubberDuck/metadata.json
CONFIG_PATH
const CONFIG_PATH: string
Path to daemon configuration file.
Value: ~/Library/Application Support/RubberDuck/config.json
LOG_PATH
Path to daemon lifecycle log.
Value: ~/Library/Application Support/RubberDuck/duck-daemon.log
SESSIONS_DIR
const SESSIONS_DIR: string
Directory containing Pi session files.
Value: ~/Library/Application Support/RubberDuck/pi-sessions/
Usage Example
import {
APP_SUPPORT,
SOCKET_PATH,
METADATA_PATH,
SESSIONS_DIR
} from 'duck';
console.log('App support:', APP_SUPPORT);
console.log('Daemon socket:', SOCKET_PATH);
console.log('Sessions:', SESSIONS_DIR);
Utility Functions
Helper functions exported by the CLI for workspace and path management.
workspaceId
function workspaceId(absolutePath: string): string
Generate a stable workspace ID from an absolute path.
Parameters:
absolutePath — Absolute filesystem path
Returns: SHA-256 hash (first 16 hex chars) of the normalized path.
Example:
import { workspaceId } from 'duck';
const id = workspaceId('/Users/alice/projects/my-app');
// => "7f3a8b2c9d1e4f56"
findGitRoot
function findGitRoot(startPath: string): string | null
Find the nearest .git directory by walking up from startPath.
Parameters:
startPath — Starting directory path
Returns: Absolute path to Git repository root, or null if not found.
Example:
import { findGitRoot } from 'duck';
const gitRoot = findGitRoot('/Users/alice/projects/my-app/src');
// => "/Users/alice/projects/my-app"
resolveWorkspacePath
async function resolveWorkspacePath(
pathArg: string | undefined
): Promise<string>
Resolve a workspace path argument to an absolute path.
Parameters:
pathArg — Path string (relative, absolute, or undefined for cwd)
Returns: Absolute path, preferring Git root if found.
Behavior:
- If
pathArg is undefined, use process.cwd()
- Resolve relative paths against cwd
- Check for
.git directory and return repo root if found
- Otherwise return the resolved absolute path
Example:
import { resolveWorkspacePath } from 'duck';
// From /Users/alice/projects/my-app/src
const workspace = await resolveWorkspacePath('.');
// => "/Users/alice/projects/my-app" (Git root)
const absolute = await resolveWorkspacePath('/tmp/sandbox');
// => "/tmp/sandbox"
generateId
function generateId(): string
Generate a unique ID for requests or sessions.
Returns: Random 22-character base64url string.
Example:
import { generateId } from 'duck';
const requestId = generateId();
// => "k3x7n2m9p4q8r1s5t6u0"
function formatTimestamp(date: Date): string
Format a timestamp for display.
Parameters:
Returns: ISO 8601 timestamp string (local timezone).
Example:
import { formatTimestamp } from 'duck';
const now = formatTimestamp(new Date());
// => "2026-03-03T10:15:30.123-08:00"