Documentation of the classes, interfaces, and functions exported by each module.
Loads all configuration from environment variables. Exits with process.exit(1) if a required variable is missing or the format is invalid.
interface AppConfig {
matrix: MatrixConfig;
projects: ProjectsConfig;
claude: ClaudeConfig;
groq: GroqConfig;
bot: BotConfig;
}interface MatrixConfig {
homeserverUrl: string; // Homeserver URL
accessToken: string; // Bot access token
allowedUserId: string; // Authorized user ID (@user:server)
enableE2ee: boolean; // Enable end-to-end encryption
cryptoStoragePath: string; // Directory for E2EE keys (SQLite)
}interface ProjectsConfig {
projects: Record<string, string>; // name -> absolute path
defaultProject: string; // default project
}interface ClaudeConfig {
binaryPath: string; // Path to the claude binary
timeout: number; // Timeout in ms
maxTurns: number; // Maximum agentic turns
}interface GroqConfig {
apiKey: string; // Groq API key
model: string; // Whisper model
endpoint: string; // Endpoint URL
language: string; // Language or "auto"
}interface BotConfig {
maxMessageLength: number; // Max chars per message
tmpDir: string; // Temporary directory
sessionsFile: string; // Sessions file path
logLevel: string; // debug|info|warn|error
}interface BridgeConfig {
mode: "bot" | "bridge" | "ide"; // Operation mode
claudeArgs: string[]; // Extra args for Claude (e.g.: ["--model", "sonnet"])
socketDir: string; // Directory for Unix sockets IPC (bridge)
hookTimeout: number; // Hook timeout in ms (bridge)
}Persists Claude Code sessions per Matrix room.
Constructor:
new SessionStore(filePath: string)Loads the JSON file if it exists. If it's corrupt, starts with an empty map.
Methods:
| Method | Description |
|---|---|
get(roomId: string): SessionData | null |
Gets the session for a room |
set(roomId: string, data: Partial<SessionData>): void |
Updates (merges) the session for a room |
clear(roomId: string): void |
Deletes the session for a room |
interface SessionData {
sessionId: string | null; // Claude session ID for --resume
project: string; // Active project name
}Executes prompts in Claude Code as a subprocess.
Constructor:
new ClaudeRunner(
config: ClaudeConfig,
projectsConfig: ProjectsConfig,
sessions: SessionStore,
queue: SerialQueue,
)Methods:
| Method | Description |
|---|---|
run(roomId: string, prompt: string): Promise<string> |
Executes a prompt and returns the response |
The run method:
- Looks up the room's session to get the project and session_id
- Builds the arguments:
-p,--output-format json,--max-turns,--resume - Spawns the process with explicit env and closed stdin
- Parses the JSON output
- Saves the session_id for future messages
- Returns the response text
Transcribes audio to text via the Groq API.
Constructor:
new GroqTranscriber(config: GroqConfig)Methods and properties:
| Member | Description |
|---|---|
transcribe(filePath: string): Promise<string> |
Transcribes an audio file |
available: boolean (getter) |
true if an API key is configured |
The transcribe method:
- Reads the file from disk
- Determines the MIME type by extension
- Builds a FormData with file, model, response_format, temperature, language
- POSTs to the Groq endpoint with Authorization bearer
- Parses the response and returns the text
FIFO queue that executes one task at a time.
Methods and properties:
| Member | Description |
|---|---|
enqueue<T>(task: () => Promise<T>): Promise<T> |
Enqueues a task. Resolves when complete |
setChildProcess(cp: ChildProcess): void |
Associates a child process with the current task |
cancelCurrent(): boolean |
Sends SIGTERM to the current process |
length: number (getter) |
Number of pending tasks |
busy: boolean (getter) |
true if a task is running |
Creates and validates a Matrix client. Configures auto-join and silences SDK logs.
interface MatrixClientWrapper {
client: MatrixClient; // Raw matrix-bot-sdk instance
userId: string; // Bot user ID
start(): Promise<void>; // Starts sync loop + prints device info for verification
stop(): void; // Stops the sync loop
sendText(roomId: string, text: string): Promise<string>; // Renders markdown to HTML
sendNotice(roomId: string, text: string): Promise<string>; // Unformatted notice
setTyping(roomId: string, typing: boolean): Promise<void>;
downloadMedia(mxcUrl: string, destPath: string): Promise<void>; // Unencrypted media
downloadEncryptedMedia(file: EncryptedFileInfo, destPath: string): Promise<void>; // E2EE media
}Metadata for an encrypted file in an E2EE message. Corresponds to the content.file field of the Matrix event.
interface EncryptedFileInfo {
url: string; // mxc:// URL of the encrypted file
key: { kty: "oct"; key_ops: string[]; alg: "A256CTR"; k: string; ext: true };
iv: string; // Initialization vector
hashes: Record<string, string>; // SHA-256 hash of the encrypted content
v: string; // Encryption scheme version
}Encrypted media downloads use the authenticated endpoint /_matrix/client/v1/media/download/ (since matrix.org deprecated the legacy endpoint /_matrix/media/v3/download/) and decrypt with Attachment.decrypt() from the Rust crypto SDK.
Orchestrator for bridge mode (tmux + hooks).
Constructor:
new BridgeRunner(config: AppConfig, matrix: MatrixClientWrapper, sessionStore: SessionStore)Methods:
| Method | Description |
|---|---|
handleMessage(roomId: string, prompt: string): Promise<string | null> |
Injects prompt into tmux and waits for response |
newSession(roomId: string): Promise<void> |
Destroys tmux session and clears state |
cancel(roomId: string): boolean |
Cancels the current task |
getStatus(roomId: string, lines?: number): { alive: boolean; output?: string } |
Status of the tmux session |
stop(): void |
Cleans up all sessions and the IPC server |
Orchestrator for IDE mode (MCP WebSocket + one-shot subprocess).
Constructor:
new IdeRunner(config: AppConfig, matrix: MatrixClientWrapper, sessionStore: SessionStore)Methods:
| Method | Description |
|---|---|
handleMessage(roomId: string, prompt: string): Promise<string | null> |
Launches claude -p --ide and returns response |
newSession(roomId: string): Promise<void> |
Stops the room's MCP server and clears session |
cancel(roomId: string): boolean |
Cancels the current subprocess |
getStatus(roomId: string): { alive: boolean; connected: boolean } |
MCP server status |
handleDiffResponse(roomId: string, text: string): boolean |
Processes a diff response (y/n). Returns true if handled |
stop(): void |
Cleans up all MCP servers and cancels tasks |
WebSocket server that implements the MCP (Model Context Protocol) version 2024-11-05.
Constructor:
new McpServer(workspaceFolders: string[], sessionName: string)Methods:
| Method | Description |
|---|---|
start(): void |
Starts the WebSocket server and creates lockfile |
stop(): void |
Stops the server and removes lockfile |
connected: boolean (getter) |
True if Claude Code is connected |
sendToolResponse(requestId, content): void |
Sends tool response to Claude |
sendToolError(requestId, message): void |
Sends tool error to Claude |
storeDeferredResponse(uniqueKey, requestId): void |
Stores a deferred response |
completeDeferredResponse(uniqueKey, content): void |
Completes a deferred response |
sendNotification(method, params?): void |
Sends JSON-RPC notification |
Emitted events:
| Event | Parameters | Description |
|---|---|---|
connected |
— | Claude Code connected to the WebSocket |
disconnected |
— | Claude Code disconnected |
tool_call |
(requestId, toolName, args) |
Claude invokes a tool |
Returns a logger object with debug, info, warn, error methods. Logs are written to stderr with the format:
2024-01-15T10:30:00.000Z [INFO] [component] message
Sets the minimum log level. The levels are: debug < info < warn < error.
Splits a long text into chunks that don't exceed maxLength. Attempts to split at line breaks, then at spaces, and as a last resort does a hard cut.