From 5f195252c403f7c48cb8b2894f2c57beba292ce4 Mon Sep 17 00:00:00 2001 From: Stephen Hellicar Date: Wed, 8 Apr 2026 00:01:15 +1000 Subject: [PATCH 1/4] Move CacheTtl from types to enums, export from package index --- packages/claude-sdk/src/index.ts | 28 ++----------------- packages/claude-sdk/src/private/AgentRun.ts | 3 +- .../claude-sdk/src/private/RequestBuilder.ts | 4 +-- packages/claude-sdk/src/private/pricing.ts | 2 +- packages/claude-sdk/src/public/enums.ts | 5 ++++ packages/claude-sdk/src/public/types.ts | 8 +----- .../claude-sdk/test/RequestBuilder.spec.ts | 4 +-- 7 files changed, 16 insertions(+), 38 deletions(-) diff --git a/packages/claude-sdk/src/index.ts b/packages/claude-sdk/src/index.ts index 15adc04..63301c5 100644 --- a/packages/claude-sdk/src/index.ts +++ b/packages/claude-sdk/src/index.ts @@ -3,13 +3,12 @@ import type { AuthCredentials } from './private/Auth/types'; import { calculateCost } from './private/pricing'; import { createAnthropicAgent } from './public/createAnthropicAgent'; import { defineTool } from './public/defineTool'; -import { AnthropicBeta } from './public/enums'; +import { AnthropicBeta, CacheTtl } from './public/enums'; import { IAnthropicAgent } from './public/interfaces'; import type { AnthropicAgentOptions, AnthropicBetaFlags, AnyToolDefinition, - CacheTtl, ConsumerMessage, ILogger, RunAgentQuery, @@ -28,26 +27,5 @@ import type { } from './public/types'; export type { BetaMessageParam } from '@anthropic-ai/sdk/resources/beta.js'; -export type { - AnthropicAgentOptions, - AnthropicBetaFlags, - AnyToolDefinition, - AuthCredentials, - CacheTtl, - ConsumerMessage, - ILogger, - RunAgentQuery, - RunAgentResult, - SdkDone, - SdkError, - SdkMessage, - SdkMessageEnd, - SdkMessageStart, - SdkMessageText, - SdkMessageUsage, - SdkQuerySummary, - SdkToolApprovalRequest, - ToolDefinition, - ToolOperation, -}; -export { AnthropicAuth, AnthropicBeta, calculateCost, createAnthropicAgent, defineTool, IAnthropicAgent }; +export type { AnthropicAgentOptions, AnthropicBetaFlags, AnyToolDefinition, AuthCredentials, ConsumerMessage, ILogger, RunAgentQuery, RunAgentResult, SdkDone, SdkError, SdkMessage, SdkMessageEnd, SdkMessageStart, SdkMessageText, SdkMessageUsage, SdkQuerySummary, SdkToolApprovalRequest, ToolDefinition, ToolOperation }; +export { AnthropicAuth, CacheTtl, AnthropicBeta, calculateCost, createAnthropicAgent, defineTool, IAnthropicAgent }; diff --git a/packages/claude-sdk/src/private/AgentRun.ts b/packages/claude-sdk/src/private/AgentRun.ts index f85f772..f7d01e3 100644 --- a/packages/claude-sdk/src/private/AgentRun.ts +++ b/packages/claude-sdk/src/private/AgentRun.ts @@ -10,6 +10,7 @@ import { MessageStream } from './MessageStream'; import { calculateCost, getContextWindow } from './pricing'; import { buildRequestParams } from './RequestBuilder'; import type { ContentBlock, MessageStreamResult, ToolUseResult } from './types'; +import { CacheTtl } from '../public/enums'; export class AgentRun { readonly #client: Anthropic; @@ -79,7 +80,7 @@ export class AgentRun { return; } - const cacheTtl = this.#options.cacheTtl ?? '5m'; + const cacheTtl = this.#options.cacheTtl ?? CacheTtl.OneHour; const costUsd = calculateCost(result.usage, this.#options.model, cacheTtl); const contextWindow = getContextWindow(this.#options.model); this.#channel.send({ type: 'message_usage', ...result.usage, costUsd, contextWindow } satisfies SdkMessage); diff --git a/packages/claude-sdk/src/private/RequestBuilder.ts b/packages/claude-sdk/src/private/RequestBuilder.ts index 119c4f0..b957bfb 100644 --- a/packages/claude-sdk/src/private/RequestBuilder.ts +++ b/packages/claude-sdk/src/private/RequestBuilder.ts @@ -1,8 +1,8 @@ import type { Anthropic } from '@anthropic-ai/sdk'; import type { BetaMessageStreamParams } from '@anthropic-ai/sdk/resources/beta/messages.js'; import type { BetaCacheControlEphemeral, BetaClearThinking20251015Edit, BetaClearToolUses20250919Edit, BetaCompact20260112Edit, BetaContentBlockParam, BetaContextManagementConfig, BetaTextBlockParam, BetaToolUnion } from '@anthropic-ai/sdk/resources/beta.mjs'; -import { AnthropicBeta } from '../public/enums'; -import { CacheTtl, type RunAgentQuery } from '../public/types'; +import { AnthropicBeta, CacheTtl } from '../public/enums'; +import type { RunAgentQuery } from '../public/types'; import { AGENT_SDK_PREFIX } from './consts'; export type RequestParams = { diff --git a/packages/claude-sdk/src/private/pricing.ts b/packages/claude-sdk/src/private/pricing.ts index 970ce78..a5675d4 100644 --- a/packages/claude-sdk/src/private/pricing.ts +++ b/packages/claude-sdk/src/private/pricing.ts @@ -1,4 +1,4 @@ -export type CacheTtl = '5m' | '1h'; +import type { CacheTtl } from "../public/enums"; type ModelRates = { input: number; diff --git a/packages/claude-sdk/src/public/enums.ts b/packages/claude-sdk/src/public/enums.ts index c29ea9a..4f9c0b8 100644 --- a/packages/claude-sdk/src/public/enums.ts +++ b/packages/claude-sdk/src/public/enums.ts @@ -1,3 +1,8 @@ +export enum CacheTtl { + FiveMinutes = '5m', + OneHour = '1h', +} + export enum AnthropicBeta { /** * @see https://platform.claude.com/docs/en/build-with-claude/compaction diff --git a/packages/claude-sdk/src/public/types.ts b/packages/claude-sdk/src/public/types.ts index 0926490..cc2f982 100644 --- a/packages/claude-sdk/src/public/types.ts +++ b/packages/claude-sdk/src/public/types.ts @@ -1,7 +1,7 @@ import type { MessagePort } from 'node:worker_threads'; import type { Model } from '@anthropic-ai/sdk/resources/messages'; import type { z } from 'zod'; -import type { AnthropicBeta } from './enums'; +import type { AnthropicBeta, CacheTtl } from './enums'; export type ToolOperation = 'read' | 'write' | 'delete'; @@ -25,11 +25,6 @@ export type AnyToolDefinition = { export type AnthropicBetaFlags = Partial>; -export enum CacheTtl { - FiveMinutes = '5m', - OneHour = '1h', -} - export type RunAgentQuery = { model: Model; thinking?: boolean; @@ -47,7 +42,6 @@ export type RunAgentQuery = { }; /** Messages sent from the SDK to the consumer via the MessagePort. */ - export type SdkMessageStart = { type: 'message_start' }; export type SdkMessageText = { type: 'message_text'; text: string }; export type SdkMessageThinking = { type: 'message_thinking'; text: string }; diff --git a/packages/claude-sdk/test/RequestBuilder.spec.ts b/packages/claude-sdk/test/RequestBuilder.spec.ts index 0e5e3b2..bc5dcac 100644 --- a/packages/claude-sdk/test/RequestBuilder.spec.ts +++ b/packages/claude-sdk/test/RequestBuilder.spec.ts @@ -3,8 +3,8 @@ import { describe, expect, it } from 'vitest'; import type { BetaMessageParam } from '../src/index.js'; import { AGENT_SDK_PREFIX } from '../src/private/consts.js'; import { buildRequestParams } from '../src/private/RequestBuilder.js'; -import { AnthropicBeta } from '../src/public/enums.js'; -import { type AnyToolDefinition, CacheTtl, type RunAgentQuery } from '../src/public/types.js'; +import { AnthropicBeta, CacheTtl } from '../src/public/enums.js'; +import { type AnyToolDefinition, type RunAgentQuery } from '../src/public/types.js'; // --------------------------------------------------------------------------- // Helpers From 2fe007733b163db4ee57efc8983a4536f07bec7b Mon Sep 17 00:00:00 2001 From: Stephen Hellicar Date: Wed, 8 Apr 2026 00:01:24 +1000 Subject: [PATCH 2/4] Switch to CacheTtl enum and raise maxTokens to 32000 --- apps/claude-sdk-cli/src/runAgent.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/apps/claude-sdk-cli/src/runAgent.ts b/apps/claude-sdk-cli/src/runAgent.ts index 5b95384..1bc877b 100644 --- a/apps/claude-sdk-cli/src/runAgent.ts +++ b/apps/claude-sdk-cli/src/runAgent.ts @@ -1,4 +1,4 @@ -import { AnthropicBeta, type AnyToolDefinition, type IAnthropicAgent, type SdkMessage } from '@shellicar/claude-sdk'; +import { AnthropicBeta, type AnyToolDefinition, type IAnthropicAgent, type SdkMessage, CacheTtl } from '@shellicar/claude-sdk'; import { CreateFile } from '@shellicar/claude-sdk-tools/CreateFile'; import { DeleteDirectory } from '@shellicar/claude-sdk-tools/DeleteDirectory'; import { DeleteFile } from '@shellicar/claude-sdk-tools/DeleteFile'; @@ -29,7 +29,7 @@ export async function runAgent(agent: IAnthropicAgent, prompt: string, layout: A const cwd = process.cwd(); const model = 'claude-sonnet-4-6'; - const cacheTtl = '5m' as const; + const cacheTtl = CacheTtl.OneHour; const transformToolResult = (toolName: string, output: unknown): unknown => { const result = refTransform(toolName, output); @@ -44,10 +44,10 @@ export async function runAgent(agent: IAnthropicAgent, prompt: string, layout: A const { port, done } = agent.runAgent({ model, - maxTokens: 8000, + maxTokens: 32000, messages: [prompt], systemPrompts, - cacheTtl: '1h', + cacheTtl, transformToolResult, pauseAfterCompact: true, compactInputTokens: 150_000, From 468a336d0db860a07c2026438dc73405d8c36b18 Mon Sep 17 00:00:00 2001 From: Stephen Hellicar Date: Wed, 8 Apr 2026 00:01:53 +1000 Subject: [PATCH 3/4] Add sdk-tools backlog (config, tool instructions, Find exclusions) --- .claude/plans/sdk-tools.md | 55 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) create mode 100644 .claude/plans/sdk-tools.md diff --git a/.claude/plans/sdk-tools.md b/.claude/plans/sdk-tools.md new file mode 100644 index 0000000..1be9375 --- /dev/null +++ b/.claude/plans/sdk-tools.md @@ -0,0 +1,55 @@ +# claude-sdk-tools — Planned Work + +## Config + +The tools currently take no configuration. Everything is either hardcoded or passed +ad-hoc by the consumer. This is the foundation the other items depend on. + +**Config loading** +- Load from `./.claude/tools-config.json` (local) and `~/.claude/tools-config.json` (home). + Local takes priority; fields merge-overwrite (null in local means "use home value"). +- Hot reload during idle phase, same pattern as the CLI config watcher. +- Zod schema for validation, coerce/default on invalid values rather than throwing. +- Publish a JSON schema for the config file so editors can validate it. + +**Config resolution** +- Resolve config once at startup into a concrete `ResolvedConfig` object. +- Stop threading optional fields through every function call. Resolved config is passed + to tool factories; they read from it, not from individual options. +- The existing CLI has this pattern — `claude-sdk-cli/src/cli-config/` is a reference. + +--- + +## Better tool instructions + +The tool descriptions drive how Claude uses the tools. They are currently minimal. Better +instructions would reduce mistakes and turn count. + +Things worth covering: +- `PreviewEdit`: lead with the `lineEdits`/`textEdits` split; clarify that line numbers + always reference the file before the call; show a combined example. +- `Exec`: structured args, no shell quoting, pipeline support, when to use `stdin`. +- Batching: call multiple read tools before deciding what to write; avoid a round-trip + per small decision. +- Whether to deliver instructions as part of tool `description` fields or as a + `` block injected into the system prompt. The reminder approach + keeps descriptions short and puts guidance where Claude refers to it during a turn. + +--- + +## Find tool exclusions + +The current `exclude` parameter is a list of directory names matched by basename. +Two improvements: + +**Standard regex patterns** +- Rename `pattern` to use standard regex (it already does, just document it). +- Change `exclude` from a list of directory names to a list of regex patterns matched + against the full relative path. +- Default exclusions should cover `dist/`, `node_modules/`, and all dot directories + (`^\..*/` — catches `.git`, `.claude`, `.turbo`, etc.). + +**Examples in the tool description** +- `pattern: \.(ts|js|svelte|vue)$` — source files +- `pattern: \.(md|html)$` — docs +- `exclude: [dist, node_modules, ^\..*/]` — standard ignores From 98fff2f640f13759cb8e962397fb476655d2bb66 Mon Sep 17 00:00:00 2001 From: Stephen Hellicar Date: Wed, 8 Apr 2026 00:02:13 +1000 Subject: [PATCH 4/4] Fix biome import ordering and style in cache-ttl-enum changes --- apps/claude-sdk-cli/src/runAgent.ts | 2 +- packages/claude-sdk/src/index.ts | 2 +- packages/claude-sdk/src/private/AgentRun.ts | 2 +- packages/claude-sdk/src/private/pricing.ts | 2 +- packages/claude-sdk/test/RequestBuilder.spec.ts | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/apps/claude-sdk-cli/src/runAgent.ts b/apps/claude-sdk-cli/src/runAgent.ts index 1bc877b..4c7a9ed 100644 --- a/apps/claude-sdk-cli/src/runAgent.ts +++ b/apps/claude-sdk-cli/src/runAgent.ts @@ -1,4 +1,4 @@ -import { AnthropicBeta, type AnyToolDefinition, type IAnthropicAgent, type SdkMessage, CacheTtl } from '@shellicar/claude-sdk'; +import { AnthropicBeta, type AnyToolDefinition, CacheTtl, type IAnthropicAgent, type SdkMessage } from '@shellicar/claude-sdk'; import { CreateFile } from '@shellicar/claude-sdk-tools/CreateFile'; import { DeleteDirectory } from '@shellicar/claude-sdk-tools/DeleteDirectory'; import { DeleteFile } from '@shellicar/claude-sdk-tools/DeleteFile'; diff --git a/packages/claude-sdk/src/index.ts b/packages/claude-sdk/src/index.ts index 63301c5..33b4866 100644 --- a/packages/claude-sdk/src/index.ts +++ b/packages/claude-sdk/src/index.ts @@ -28,4 +28,4 @@ import type { export type { BetaMessageParam } from '@anthropic-ai/sdk/resources/beta.js'; export type { AnthropicAgentOptions, AnthropicBetaFlags, AnyToolDefinition, AuthCredentials, ConsumerMessage, ILogger, RunAgentQuery, RunAgentResult, SdkDone, SdkError, SdkMessage, SdkMessageEnd, SdkMessageStart, SdkMessageText, SdkMessageUsage, SdkQuerySummary, SdkToolApprovalRequest, ToolDefinition, ToolOperation }; -export { AnthropicAuth, CacheTtl, AnthropicBeta, calculateCost, createAnthropicAgent, defineTool, IAnthropicAgent }; +export { AnthropicAuth, AnthropicBeta, CacheTtl, calculateCost, createAnthropicAgent, defineTool, IAnthropicAgent }; diff --git a/packages/claude-sdk/src/private/AgentRun.ts b/packages/claude-sdk/src/private/AgentRun.ts index f7d01e3..970e95c 100644 --- a/packages/claude-sdk/src/private/AgentRun.ts +++ b/packages/claude-sdk/src/private/AgentRun.ts @@ -2,6 +2,7 @@ import { randomUUID } from 'node:crypto'; import type { MessagePort } from 'node:worker_threads'; import type { Anthropic } from '@anthropic-ai/sdk'; import type { BetaCompactionBlockParam, BetaTextBlockParam, BetaThinkingBlockParam, BetaToolUseBlockParam } from '@anthropic-ai/sdk/resources/beta.mjs'; +import { CacheTtl } from '../public/enums'; import type { AnyToolDefinition, ILogger, RunAgentQuery, SdkMessage } from '../public/types'; import { AgentChannel } from './AgentChannel'; import { ApprovalState } from './ApprovalState'; @@ -10,7 +11,6 @@ import { MessageStream } from './MessageStream'; import { calculateCost, getContextWindow } from './pricing'; import { buildRequestParams } from './RequestBuilder'; import type { ContentBlock, MessageStreamResult, ToolUseResult } from './types'; -import { CacheTtl } from '../public/enums'; export class AgentRun { readonly #client: Anthropic; diff --git a/packages/claude-sdk/src/private/pricing.ts b/packages/claude-sdk/src/private/pricing.ts index a5675d4..52f9085 100644 --- a/packages/claude-sdk/src/private/pricing.ts +++ b/packages/claude-sdk/src/private/pricing.ts @@ -1,4 +1,4 @@ -import type { CacheTtl } from "../public/enums"; +import type { CacheTtl } from '../public/enums'; type ModelRates = { input: number; diff --git a/packages/claude-sdk/test/RequestBuilder.spec.ts b/packages/claude-sdk/test/RequestBuilder.spec.ts index bc5dcac..a43efe9 100644 --- a/packages/claude-sdk/test/RequestBuilder.spec.ts +++ b/packages/claude-sdk/test/RequestBuilder.spec.ts @@ -4,7 +4,7 @@ import type { BetaMessageParam } from '../src/index.js'; import { AGENT_SDK_PREFIX } from '../src/private/consts.js'; import { buildRequestParams } from '../src/private/RequestBuilder.js'; import { AnthropicBeta, CacheTtl } from '../src/public/enums.js'; -import { type AnyToolDefinition, type RunAgentQuery } from '../src/public/types.js'; +import type { AnyToolDefinition, RunAgentQuery } from '../src/public/types.js'; // --------------------------------------------------------------------------- // Helpers