TypeScript SDK
Using Ripperdoc with TypeScript/JavaScript
The Ripperdoc TypeScript SDK provides a type-safe interface for integrating Ripperdoc's AI coding capabilities into TypeScript and JavaScript applications.
Installation
npm install ripperdoc-agent-sdk
# or
yarn add ripperdoc-agent-sdk
# or
pnpm add ripperdoc-agent-sdkQuick Start
One-Shot Query
For simple, single-turn queries:
import { query } from 'ripperdoc-agent-sdk';
async function main() {
for await (const message of query('What files are in this project?')) {
if (message.type === 'assistant') {
for (const block of message.content) {
if (block.type === 'text') {
console.log(block.text);
}
}
}
}
}
main();Persistent Client
For multi-turn conversations with full control:
import { RipperdocClient, RipperdocOptions } from 'ripperdoc-agent-sdk';
async function main() {
const options: RipperdocOptions = {
model: 'main',
permissionMode: 'acceptEdits',
verbose: true
};
const client = new RipperdocClient(options);
try {
await client.connect();
// Start a conversation
await client.query('What files are in this project?');
for await (const message of client.receiveMessages()) {
if (message.type === 'assistant') {
for (const block of message.content) {
if (block.type === 'text') {
console.log(block.text);
}
}
}
}
// Continue the conversation
await client.query('Read the main.ts file');
for await (const message of client.receiveMessages()) {
if (message.type === 'assistant') {
for (const block of message.content) {
if (block.type === 'text') {
console.log(block.text);
}
}
}
}
} finally {
await client.close();
}
}
main();RipperdocOptions
The RipperdocOptions interface configures SDK behavior:
interface RipperdocOptions {
// Model configuration
model?: string; // Model profile name
maxThinkingTokens?: number; // Extended thinking tokens (0 = disabled)
// Permission mode
permissionMode?: PermissionMode; // "default" | "acceptEdits" | "bypassPermissions" | "plan"
// Tool configuration
allowedTools?: string[]; // Whitelist specific tools
disallowedTools?: string[]; // Blacklist specific tools
// Behavior settings
verbose?: boolean; // Enable verbose output
maxTurns?: number; // Max conversation turns (undefined = unlimited)
// Context
cwd?: string; // Working directory path
context?: Record<string, string>; // Custom context variables
systemPrompt?: string; // Override system prompt
additionalInstructions?: string | string[]; // Additional instructions
// Extensions
mcpServers?: McpServerConfig[]; // MCP server configurations
agents?: AgentConfig[]; // Programmatic agent definitions
hooks?: HookConfig[]; // Event hook callbacks
// Transport
ripperdocPath?: string; // Path to Ripperdoc CLI
}Permission Modes
The SDK supports four permission modes:
| Mode | Description |
|---|---|
default | Prompts for dangerous operations (bash, file edits, etc.) |
acceptEdits | Auto-accept file edits, prompt for other dangerous operations |
bypassPermissions | Allow all operations without prompting |
plan | Planning mode - no execution, analysis only |
// Safe mode with prompts
const options: RipperdocOptions = {
permissionMode: 'default'
};
// Auto-accept file edits
const options: RipperdocOptions = {
permissionMode: 'acceptEdits'
};
// Planning mode - no execution
const options: RipperdocOptions = {
permissionMode: 'plan'
};
// Fully automated (use with caution)
const options: RipperdocOptions = {
permissionMode: 'bypassPermissions'
};Tool Filtering
Control which tools are available:
// Only allow read operations
const options: RipperdocOptions = {
allowedTools: ['Read', 'Glob', 'Grep', 'LS']
};
// Allow all except bash
const options: RipperdocOptions = {
disallowedTools: ['Bash']
};Message Types
The SDK yields different message types with structured content:
import type {
AssistantMessage,
TextBlock,
ThinkingBlock,
ToolUseBlock,
ResultMessage
} from 'ripperdoc-agent-sdk';
async function processMessages(client: RipperdocClient) {
for await (const message of client.receiveMessages()) {
switch (message.type) {
case 'assistant':
for (const block of message.content) {
switch (block.type) {
case 'text':
console.log(`Text: ${block.text}`);
break;
case 'thinking':
console.log(`Thinking: ${block.thinking}`);
break;
case 'tool_use':
console.log(`Tool: ${block.name}`);
break;
}
}
break;
case 'result':
console.log(`Usage: ${message.result.usage}`);
break;
}
}
}Content Blocks
Messages contain content blocks of different types:
- TextBlock: Plain text response
- ThinkingBlock: Extended thinking output (for models with thinking enabled)
- ToolUseBlock: Tool being called with parameters
- ToolResultBlock: Result from a tool execution
- ImageBlock: Image content
MCP Servers
Integrate external MCP servers for additional tools:
import { RipperdocOptions, McpServerConfig } from 'ripperdoc-agent-sdk';
const options: RipperdocOptions = {
mcpServers: [
{
name: 'filesystem',
command: 'npx',
args: ['-y', '@modelcontextprotocol/server-filesystem', '/allowed/path']
},
{
name: 'postgres',
command: 'npx',
args: ['-y', '@modelcontextprotocol/server-postgres'],
env: {
POSTGRES_CONNECTION_STRING: 'postgresql://...'
}
}
]
};Programmatic Agents
Define custom subagents programmatically:
import { RipperdocOptions, AgentConfig } from 'ripperdoc-agent-sdk';
const options: RipperdocOptions = {
agents: [
{
name: 'code-reviewer',
agentType: 'code-reviewer',
whenToUse: 'Review code for security issues',
tools: ['Read', 'Grep', 'Glob'],
systemPrompt: 'You are a security expert. Focus on vulnerabilities.',
model: 'sonnet'
},
{
name: 'test-writer',
agentType: 'test-writer',
whenToUse: 'Write comprehensive tests',
tools: ['Read', 'Write', 'Glob', 'Grep'],
systemPrompt: 'You are a testing specialist.',
model: 'haiku'
}
]
};Hooks
Intercept and modify events during execution:
import { RipperdocOptions, HookConfig, HookEvent } from 'ripperdoc-agent-sdk';
// Define your hook callbacks
const logToolUse = (context: HookContext) => {
console.log(`Tool used: ${context.toolName}`);
};
const sanitizeInput = (context: HookContext) => {
// Modify tool input before execution
return { updatedInput: sanitize(context.input) };
};
const options: RipperdocOptions = {
hooks: [
{
event: 'PreToolUse',
callback: 'logToolUse',
pattern: { toolName: '*' }
},
{
event: 'PreToolUse',
callback: 'sanitizeInput',
pattern: { toolName: 'Bash*' }
}
]
};Hook Events
Available hook events:
PreToolUse- Before a tool is calledPostToolUse- After a tool completesPostToolUseFailure- After a tool fails or times outPreRead- Before reading a filePostRead- After reading a filePreEdit- Before editing a filePostEdit- After editing a filePreWrite- Before writing a filePostWrite- After writing a filePreBash- Before executing bash commandPostBash- After executing bash commandOnError- When an error occursOnTurnStart- When a turn startsOnTurnEnd- When a turn endsOnQueryStart- When a query startsOnQueryEnd- When a query endsSubagentStart- Before a subagent startsSubagentStop- When a subagent stopsSetup- Repository setup/maintenance (first startup per project)
RipperdocClient
The main class for session-based interactions.
Constructor
import { RipperdocClient, RipperdocOptions } from 'ripperdoc-agent-sdk';
const options: RipperdocOptions = {
model: 'main',
permissionMode: 'default'
};
const client = new RipperdocClient(options);Methods
connect
Connect to the Ripperdoc CLI:
async connect(): Promise<void>Example:
await client.connect();close
Close the connection:
async close(): Promise<void>Example:
await client.close();query
Start a query with the given prompt:
async query(prompt: string): Promise<void>Throws:
ClientNotConnectedError- If client is not connectedQueryInProgressError- If a query is already in progress
Example:
await client.query('What files are in this project?');receiveMessages
Receive messages as an async generator:
async *receiveMessages(): AsyncGenerator<Message, void, unknown>Yields:
Message: Messages from the conversation
Example:
for await (const message of client.receiveMessages()) {
console.log(message);
}setPermissionMode
Change permission mode during conversation:
async setPermissionMode(mode: PermissionMode): Promise<void>Example:
await client.setPermissionMode('acceptEdits');setModel
Change the AI model during conversation:
async setModel(model: string): Promise<void>Example:
await client.setModel('sonnet');getServerInfo
Get server information:
async getServerInfo(): Promise<ServerInfo>Returns:
- Server information including version, features, available tools and models
Example:
const info = await client.getServerInfo();
console.log(`Version: ${info.version}`);
console.log(`Tools: ${info.availableTools.join(', ')}`);Properties
isConnected
Check if client is connected:
get isConnected(): booleanisQuerying
Check if a query is in progress:
get isQuerying(): booleansessionIdValue
Get the current session ID:
get sessionIdValue(): stringError Handling
The SDK provides specific error types for different failure scenarios:
import {
RipperdocClient,
CLINotFoundError,
QueryFailedError,
InitializationError
} from 'ripperdoc-agent-sdk';
async function main() {
const client = new RipperdocClient();
try {
await client.connect();
await client.query('Do something');
for await (const message of client.receiveMessages()) {
console.log(message);
}
} catch (error) {
if (error instanceof CLINotFoundError) {
console.error('Ripperdoc CLI not found!');
} else if (error instanceof QueryFailedError) {
console.error('Query failed:', error.message);
} else if (error instanceof InitializationError) {
console.error('Initialization failed:', error.message);
} else {
console.error('Unknown error:', error);
}
} finally {
await client.close();
}
}Error Types
CLINotFoundError- Ripperdoc CLI executable not foundInitializationError- Failed to initialize sessionQueryFailedError- Query execution failedClientNotConnectedError- Operation attempted while not connectedClientAlreadyConnectedError- Connection attempted while already connectedQueryInProgressError- Query attempted while another query is runningNoActiveQueryError- Message receive attempted without active query
Use Cases
Code Analysis
import { query, RipperdocOptions } from 'ripperdoc-agent-sdk';
async function analyzeCode(code: string) {
const options: RipperdocOptions = {
systemPrompt: 'You are a security expert.',
allowedTools: ['Read'],
permissionMode: 'default'
};
for await (const message of query(
`Analyze this code for security issues:\n\n\`\`\`typescript\n${code}\n\`\`\``,
options
)) {
if (message.type === 'assistant') {
for (const block of message.content) {
if (block.type === 'text') {
return block.text;
}
}
}
}
}Automated Refactoring
import { RipperdocClient, RipperdocOptions } from 'ripperdoc-agent-sdk';
async function refactorCodebase() {
const options: RipperdocOptions = {
permissionMode: 'acceptEdits',
allowedTools: ['Read', 'Glob', 'Grep', 'Edit'],
maxTurns: 20
};
const client = new RipperdocClient(options);
try {
await client.connect();
await client.query('Find all deprecated API calls');
for await (const msg of client.receiveMessages()) {
// Process results
}
await client.query('Update them to use the new API');
for await (const msg of client.receiveMessages()) {
// Process results
}
} finally {
await client.close();
}
}Documentation Generation
import { query, RipperdocOptions, AgentConfig } from 'ripperdoc-agent-sdk';
async function generateDocs() {
const options: RipperdocOptions = {
allowedTools: ['Read', 'Glob', 'Grep'],
agents: [
{
name: 'doc-writer',
agentType: 'doc-writer',
whenToUse: 'Generate API documentation',
systemPrompt: 'You are a technical writer. Generate clear, concise documentation.'
}
]
};
for await (const message of query(
'Generate API documentation for all public functions in src/api/',
options
)) {
if (message.type === 'assistant') {
for (const block of message.content) {
if (block.type === 'text') {
console.log(block.text);
}
}
}
}
}Type Definitions
Message Types
interface UserMessage {
type: 'user';
content: ContentBlock[];
role: 'user';
}
interface AssistantMessage {
type: 'assistant';
content: ContentBlock[];
role: 'assistant';
}
interface SystemMessage {
type: 'system';
content: string;
role: 'system';
}
interface ResultMessage {
type: 'result';
result: ResultData;
}
interface ResultData {
status: 'success' | 'error';
usage?: UsageInfo;
error?: string;
}
interface UsageInfo {
inputTokens: number;
outputTokens: number;
cacheCreationTokens?: number;
cacheReadTokens?: number;
costUsd?: number;
durationMs?: number;
}
type Message = UserMessage | AssistantMessage | SystemMessage | ResultMessage;Content Block Types
interface TextBlock {
type: 'text';
text: string;
}
interface ThinkingBlock {
type: 'thinking';
thinking: string;
}
interface ToolUseBlock {
type: 'tool_use';
id: string;
name: string;
input: Record<string, unknown>;
}
interface ToolResultBlock {
type: 'tool_result';
toolUseId: string;
content: string | ContentBlock[];
isError?: boolean;
}
interface ImageBlock {
type: 'image';
source: {
type: 'url';
url: string;
};
}
type ContentBlock = TextBlock | ThinkingBlock | ToolUseBlock | ToolResultBlock | ImageBlock;Configuration Types
type PermissionMode = 'default' | 'acceptEdits' | 'bypassPermissions' | 'plan';
interface McpServerConfig {
name: string;
command: string;
args?: string[];
env?: Record<string, string>;
}
interface AgentConfig {
name: string;
agentType: string;
whenToUse?: string;
tools?: string[];
systemPrompt?: string;
model?: string;
}
interface HookConfig {
event: HookEvent;
callback: string;
pattern?: {
toolName?: string;
toolInput?: Record<string, unknown>;
};
}
type HookEvent =
| 'PreToolUse'
| 'PostToolUse'
| 'PostToolUseFailure'
| 'PreRead'
| 'PostRead'
| 'PreEdit'
| 'PostEdit'
| 'PreWrite'
| 'PostWrite'
| 'PreBash'
| 'PostBash'
| 'OnError'
| 'OnTurnStart'
| 'OnTurnEnd'
| 'OnQueryStart'
| 'OnQueryEnd'
| 'SubagentStart'
| 'SubagentStop'
| 'Setup';SDK Features
- Type Safety: Comprehensive TypeScript definitions
- Streaming: Real-time response streaming with async generators
- Error Handling: Detailed error hierarchy for specific failure scenarios
- Permission Management: Configurable safety modes
- Session Management: Persistent connections with cleanup
- Tool Access: Full access to Ripperdoc tools
- MCP Integration: Connect external MCP servers
- Programmatic Agents: Dynamic agent definitions
- Hooks: Event interception and modification
Next Steps
- Python SDK - Python SDK documentation
- MCP Integration - Model Context Protocol
- Hooks - Event hooks and customization