CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-anthropic-ai--claude-agent-sdk

SDK for building AI agents with Claude Code's capabilities to programmatically interact with Claude and build autonomous agents that can understand codebases, edit files, and execute workflows.

Overview
Eval results
Files

permissions.mddocs/apis/

Permission System

Fine-grained control over tool execution.

Permission Modes

type PermissionMode =
  | 'default'           // Prompt for dangerous operations
  | 'acceptEdits'       // Auto-accept file edits
  | 'bypassPermissions' // Bypass all checks
  | 'plan'              // Planning mode, no execution
  | 'dontAsk';          // Deny if not pre-approved

Usage:

{permissionMode: 'acceptEdits'}

Custom Permission Handler

type CanUseTool = (
  toolName: string,
  input: Record<string, unknown>,
  options: {
    signal: AbortSignal;
    suggestions?: PermissionUpdate[];
    blockedPath?: string;
    decisionReason?: string;
    toolUseID: string;
    agentID?: string;
  }
) => Promise<PermissionResult>;

type PermissionResult =
  | {behavior: 'allow'; updatedInput: Record<string, unknown>; updatedPermissions?: PermissionUpdate[]; toolUseID?: string}
  | {behavior: 'deny'; message: string; interrupt?: boolean; toolUseID?: string};

Example:

canUseTool: async (toolName, input, {decisionReason}) => {
  // Block dangerous commands
  if (toolName === 'Bash' && (input.command as string).includes('rm -rf')) {
    return {
      behavior: 'deny',
      message: 'Dangerous command not allowed',
      interrupt: true
    };
  }

  // Block sensitive files
  if ((toolName === 'Write' || toolName === 'Edit') &&
      (input.file_path as string).includes('.env')) {
    return {
      behavior: 'deny',
      message: 'Cannot modify .env files'
    };
  }

  // Allow with optional updates
  return {
    behavior: 'allow',
    updatedInput: input,
    updatedPermissions: suggestions // Apply suggestions
  };
}

Permission Updates

type PermissionUpdate =
  | {type: 'addRules'; rules: PermissionRuleValue[]; behavior: PermissionBehavior; destination: PermissionUpdateDestination}
  | {type: 'replaceRules'; rules: PermissionRuleValue[]; behavior: PermissionBehavior; destination: PermissionUpdateDestination}
  | {type: 'removeRules'; rules: PermissionRuleValue[]; behavior: PermissionBehavior; destination: PermissionUpdateDestination}
  | {type: 'setMode'; mode: PermissionMode; destination: PermissionUpdateDestination}
  | {type: 'addDirectories'; directories: string[]; destination: PermissionUpdateDestination}
  | {type: 'removeDirectories'; directories: string[]; destination: PermissionUpdateDestination};

interface PermissionRuleValue {
  toolName: string;
  ruleContent?: string;
}

type PermissionBehavior = 'allow' | 'deny' | 'ask';
type PermissionUpdateDestination = 'userSettings' | 'projectSettings' | 'localSettings' | 'session' | 'cliArg';

MCP Permission Tool

Route prompts through custom MCP tool:

{
  permissionPromptToolName: 'my-permission-handler',
  mcpServers: {
    'my-server': {
      command: 'node',
      args: ['./server.js']
    }
  }
}

Complete Example

const allowedCommands = new Set(['ls', 'pwd', 'cat', 'grep']);

const result = query({
  prompt: 'Task',
  options: {
    permissionMode: 'default',
    canUseTool: async (toolName, input, {blockedPath}) => {
      console.log(`Permission: ${toolName}`);
      if (blockedPath) console.log(`  Path: ${blockedPath}`);

      // Bash whitelist
      if (toolName === 'Bash') {
        const cmd = (input.command as string).trim().split(' ')[0];
        if (!allowedCommands.has(cmd)) {
          return {
            behavior: 'deny',
            message: `Command "${cmd}" not allowed. Use: ${Array.from(allowedCommands).join(', ')}`
          };
        }
      }

      // File protection
      if (toolName === 'Write' || toolName === 'Edit') {
        const path = input.file_path as string;
        if (path.includes('.env') || path.includes('secrets')) {
          return {behavior: 'deny', message: 'Cannot modify sensitive files'};
        }
        if (path.startsWith('/etc/') || path.startsWith('/sys/')) {
          return {behavior: 'deny', message: 'Cannot modify system files', interrupt: true};
        }
      }

      return {behavior: 'allow', updatedInput: input};
    }
  }
});

for await (const msg of result) {
  if (msg.type === 'result' && msg.permission_denials.length > 0) {
    console.log('Denied operations:');
    msg.permission_denials.forEach(d => {
      console.log(`  ${d.tool_name}:`, d.tool_input);
    });
  }
}

Types

interface SDKPermissionDenial {
  tool_name: string;
  tool_use_id: string;
  tool_input: Record<string, unknown>;
}

Install with Tessl CLI

npx tessl i tessl/npm-anthropic-ai--claude-agent-sdk

docs

apis

agents.md

hooks.md

mcp.md

messages.md

options.md

permissions.md

query-api.md

sandbox.md

tools.md

index.md

patterns.md

quick-reference.md

types.md

tile.json