All notable changes to this project will be documented in this file. This change log follows the conventions of keepachangelog.com.
:on-post-tool-use-failurehook — New lifecycle hook in the:hooksmap. Fires after a tool execution whose result was"failure";:on-post-tool-useonly fires for successful results, so register this handler to observe or react to failed tool outcomes. Note:"rejected","denied", and"timeout"results do not currently trigger this hook — only"failure"does. Handler input has:tool-name,:tool-args,:error(string), plus the base hook fields (:session-id,:timestamp,:cwd). Optional return value:{:additional-context "..."}is appended as hidden guidance to the model alongside the failed tool result. (upstream PR #1421):runtime-instructionssystem message section — New section recognized by the SDK's:system-message:customizemode. Wire-encoded as"runtime_instructions"and accepted by::specs/system-prompt-section. Upstream PR #1377 also renamedSystemPromptSection→SystemMessageSectionin TypeScript; for source compatibility the Clojure side keepsspecs/system-prompt-sectionsas the canonical name and exposesspecs/system-message-sections(and::specs/system-message-section) as aliases pointing at the same data. (upstream PR #1377):copilot/mcp_app.tool_call_completeevent — New session event emitted when a tool call from an MCP App completes (upstream schema 1.0.52-4, SEP-1865). Added to the publicevent-typesset. The:argumentsand:resultfields are preserved opaquely byprotocol/preserve-event-opaque-fields(they survivenormalize-incomingwithout kebab-case rewriting so source-defined keys round-trip verbatim).- Additional event-data fields (passive, via schema regen) — All optional;
generated
:opt-unspecs pick them up automatically::service-request-idon:error,:assistant.message,:assistant.usage,:model.call_failure,:session.compaction_completeevent data (Copilot CAPI service-request-id for correlation with CAPI logs).:context-tier("long_context" | "default" | nil) on:session.model_changedata.:transport,:plugin-name,:plugin-versionon the loaded MCP server spec inside:session.mcp_servers_loadeddata.:erroron:session.mcp_server_status_changeddata.:sourceand:trigger("user-invoked" | "agent-invoked" | "context-load") on:skill.invokeddata.:tool-descriptionand:ui-resourceon:tool.execution_completedata.
- Schema bump —
.copilot-schema-versionadvanced from1.0.52-1to1.0.55-1. Picked up the 1.0.52-4 pre-release (upstream PR #1393), the 1.0.52 stable release (upstream PR #1405), the 1.0.53-2 pre-release (upstream PR #1408), and the 1.0.53 / 1.0.54 / 1.0.55-0 / 1.0.55-1 schema bumps (upstream PRs #1410, #1411, #1412, #1432). Schema regen surfaces new wire-only canvas event types (session.canvas.opened,session.canvas.registry_changed) and their field set in the generatedevent-specsnamespace. The canvas runtime (extension manifests,requestCanvasRenderer,openCanvases, etc. — upstream PRs #1401, #1413) is not yet exposed on the public Clojure API, including the curatedevent-typesset. Canvas runtime support (including opaque-field preservation fordata.inputand nestedinputSchemapayloads on canvas events) will land in a dedicated future sync round.
- BREAKING: Minimum supported protocol version raised from 2 to 3. The
SDK will now reject CLI servers that report protocol version 2. The
back-compat shims that adapted v2
tool.call/permission.requestJSON-RPC requests into v3 broadcast-event flows have been removed fromset-request-handler!and fromprotocol/normalize-incoming. Clients must use a Copilot CLI that supports protocol v3 (CLI 1.0.46 or later). (upstream PR #1378)
- v2 protocol RPC dispatcher cases —
tool.callandpermission.requestrequest handlers (and their associated teststest-tool-call-response-shape,test-tool-handler-runs-on-blocking-thread,test-permission-denied-with-deny-handler,test-permission-approved-with-handler,test-permission-unknown-session-response-shape,test-permission-custom-handler,test-permission-no-result-v2). v3 broadcast handlershandle-v3-tool-requested!/handle-v3-permission-requested!cover the same behaviour. (upstream PR #1378)
-
:on-pre-mcp-tool-callhook — New lifecycle hook in the:hooksmap that fires before an MCP tool call is dispatched to its server (upstream PR #1366, wirehookType: "preMcpToolCall"). The handler receives an input map with kebab-cased base fields (:server-name,:tool-name,:tool-call-id,:session-id,:timestamp) plus two opaque, source-defined fields that are preserved verbatim through wire normalization::arguments(the MCP tool arguments) and:_meta(the MCP request metadata; the leading underscore is preserved — not collapsed by kebab-case conversion). The handler return value supports a tri-state:meta-to-usefield controlling the outgoing MCP request_meta:- absent (
nil/{}): preserve the existing_meta {:meta-to-use {...}}: replace_metawith the given map (inner keys are preserved opaquely — not camelCased){:meta-to-use nil}: serialize as JSONnull, removing_meta.
Note: PR #1366 also renamed hook-input
cwdtoworkingDirectoryin the Node.js public API. Existing Clojure hook handlers (:on-pre-tool-use,:on-post-tool-use, etc.) currently receive the field as:cwd. For internal consistency,:on-pre-mcp-tool-callalso exposes:cwd; the coordinated:cwd→:working-directoryrename across all hooks is tracked with the deferred PR #1357 work below.(upstream PR #1366)
- absent (
-
Schema bump —
.copilot-schema-versionadvanced from1.0.51to1.0.52-1. Additive changes only:session.compaction_complete-datagains optional:custom-instructions.tool.execution_complete-datagains optional:sandboxed.session.shutdown-datarelaxes:total-premium-requestsfrom required to optional. The hand-curated idiom spec::specs/session.shutdown-datamatches.
Most of the remaining schema diff is
x-opaque-json/ description annotations that do not affect the generated specs.
- PR #1357 (TypeScript SDK API review fixes) — Pure naming/API-shape
changes in the JS public API:
onExitPlanMode → onExitPlanModeRequest,onAutoModeSwitch → onAutoModeSwitchRequest,ResumeSessionConfig.disableResume → suppressResumeEvent,cwd → workingDirectoryacross config types,getMessages → getEvents,InputOptions → UiInputOptions,maxInputTokens → maxPromptTokens(drops wire shim), and removal ofautoStart/autoRestartfromCopilotClientOptions. The Clojure SDK already uses idiomatic kebab-case names that are independent of upstream's JS naming, and the:max-input-tokens→maxPromptTokenswire shim was explicit in Clojure from the start (mirrors upstream's pre-#1357 behavior), so dropping the JS shim has no effect on Clojure. The remaining renames (:cwd→:working-directoryon hook inputs,:disable-resume?→:suppress-resume-event?, etc.) are breaking and are deferred to a separate PR that can introduce deprecation aliases. - PRs #1370 / #1371 (1.0.52-x schema bumps) — Picked up by the schema regen in this PR.
ping:timestampfield type changed in CLI 1.0.51 — Upstream PR #1340 changed thepingRPC resulttimestampfield from epoch-millis number to an ISO 8601 date-time string (e.g."2026-05-21T08:00:00.000Z"). The SDK forwards the server value verbatim, so callers ofsdk/pingwill see a string:timestampagainst CLI ≥ 1.0.51 and a numeric epoch-millis value against older CLIs. The::specs/timestampspec accepts both shapes ((s/or :iso-string string? :epoch-ms nat-int?)) so spec instrumentation passes against either CLI version. The mock test server was updated to emit the ISO string form, and the ping docstring documents both shapes. (upstream PR #1340)
:mcp-argsis now optional on MCP stdio server configs — Following upstream PR #1347 (MCPStdioServerConfig.argsmade optional across all SDKs), the::mcp-local-server/::mcp-stdio-serverspec moves::mcp-argsfrom:req-unto:opt-un. Stdio MCP servers declared with just{:mcp-command "..." :mcp-tools [...]}(no:mcp-args) now validate and forward correctly. (upstream PR #1347):time-to-first-token-msonassistant.usageevent data — The CLI 1.0.51 wire schema renamed the assistant-usage TTFT property fromttftMstotimeToFirstTokenMs, which surfaces as the kebab-case key:time-to-first-token-msafter wire normalization. The::assistant.usage-dataspec lists both keys in:opt-unso events from older and newer CLIs both validate; the new key is the canonical name going forward. The generated wire spec (generated/event_specs.clj) only declares the new field, matching the current schema. (upstream CLI 1.0.51 schema)- Schema bump —
.copilot-schema-versionadvanced from1.0.49to1.0.51. Generated wire specs and coercions regenerated. Additive changes only beyond the rename above: bounded-integer fields previously typed asnumber?now generate asinteger?(upstream PR #1329, "Use 32-bit types for bounded schema integers").
- PR #1316 (re-export generated session-event types from
index.ts) — Node.js packaging concern only; the Clojure SDK already exposes generated event specs via thegithub.copilot-sdk.generated.event-specsnamespace. - PR #1327
ToolBinaryResult.typetightened to"image" | "resource"— Our::binary-results-for-llmspec is intentionally permissive ((coll-of map?)). Tightening would require adding a dedicated::tool-binary-resultspec with string-valued:type; deferred since the runtime helpers already emit valid values. - Upstream test stabilization (#1346, #1317, #1314), other-language / documentation / codegen-only PRs (#1336, #1291, #1331, #1338, #1339, #1304, #1289, #1313) — no Clojure SDK action required.
- SessionFs SQLite support —
sessionFs.sqliteQueryandsessionFs.sqliteExistsRPCs are now dispatched to a user-supplied provider. The provider-style handler accepts an optional nested:sqlite {:query (fn [query-type sql params]) :exists (fn [])}map, alongside the existing filesystem keys. The low-level handler shape uses flat:sqlite-query/:sqlite-existskeys (the adapter translates between them). Clients advertise support via:capabilities {:sqlite true}under:session-fs; the value is forwarded onsessionFs.setProviderand validated at session creation (declaringcapabilities.sqlitewithout providing a:sqlitehandler now throws).query-typeis automatically coerced from the wire string to a keyword (#{:exec :query :run}). SQL bind-parameter keys (e.g.$userId) are preserved verbatim through wire normalization, and result row column-name keys (e.g.:user_id,:created_at) round-trip verbatim on the outgoing wire path — they are no longer mangled by recursive kebab→camelCase conversion. SQLite errors propagate as JSON-RPC errors (not wrapped as SessionFsError). (upstream PR #1299) - Schema bump —
.copilot-schema-versionadvanced from1.0.49-1to1.0.49. Additive changes only: new named enum types (AutoModeSwitchResponse,ExitPlanModeAction,McpServerSource,McpServerStatus,SessionMode,SkillSource, renamedPermissionRequestMemoryAction/Direction),format: "duration"/"uri"annotations,"max"value in reasoning-effort description, plus the newsessionFs.sqliteQuery/sessionFs.sqliteExistsRPC methods. (upstream PRs #1305, #1307, #1327, #1333)
examples/permission_bash.clj— Updated permission decision kind from the deprecated:approvedto the current:approve-once. (carried from upstream PR #1315)
-
:session-idon hook input maps —:on-hook-invokehandlers now receive a:session-idkey on the input map. When the upstream wire payload includes asessionId(sub-agent hooks), the wire-provided value is preserved; otherwise the SDK fills in the parent session id as a convenience. (upstream PR #1290) -
:cloudsession config option (create only) —create-sessionaccepts an optional:cloudmap for creating a remote cloud session. Shape:{:repository {:owner "octocat" :name "hello-world" :branch "main"}}—:ownerand:nameare required non-blank strings;:branchis optional. Forwarded on the wire ascloud.repository.*. Matches upstream'sCloudSessionOptions/CloudSessionRepository. Not accepted onresume-session/join-session, matching upstreamResumeSessionConfig(Pick excludescloud). (upstream PR #1306) -
Optional permission and tool callbacks (manual pending RPCs) — Following upstream PR #1308,
:on-permission-requestis now optional oncreate-sessionandresume-session, and:handleris optional on tools built viatools/define-tool. When omitted, the runtime no longer auto-responds to permission requests or tool calls. Applications can resolve these requests asynchronously via the new public functions:sdk/handle-pending-tool-call!/sdk/<handle-pending-tool-call!sdk/handle-pending-permission-request!/sdk/<handle-pending-permission-request!
Useful for human-in-the-loop UIs that surface pending tool/permission requests through
sdk/get-messagesand resolve them later. Note: This is a behavioural change — previously the SDK threw if:on-permission-requestwas missing; now it's accepted and the request is treated as pending until the application resolves it. (upstream PR #1308) -
:agent-modelon custom-agent configs — Custom agent maps in:custom-agentsnow accept an optional:agent-modelstring (e.g."claude-haiku-4.5"). When set, the runtime attempts to use that model for the agent, falling back to the parent session model if unavailable. Forwarded on the wire asagentModelon each entry incustomAgentsfor bothsession.createandsession.resume. (upstream PR #1309) -
Schema bump —
.copilot-schema-versionadvanced from1.0.48to1.0.49-1. Generated wire specs and coercions regenerated; new pass-through event fields include:display-prompt,:reasoning-summary,:previous-reasoning-summary. (upstream PRs #1305, #1307)
::cloud-repositoryspec now enforces non-blank:name(was juststring?via the shared::namespec, allowing blanks despite docs).handle-pending-tool-call!and<handle-pending-tool-call!now throw when neither:resultnor:erroris supplied (previously fell through to a default "tool returned no result" payload).handle-pending-tool-call!/<handle-pending-tool-call!validate that:error, when supplied, is a string.- All four pending-RPC resolvers (
handle-pending-tool-call!,<handle-pending-tool-call!,handle-pending-permission-request!,<handle-pending-permission-request!) now require:request-idto be a non-blank string. handle-pending-permission-request!and async variant validate that:result :kindis a keyword in the documented decision set — matches the upstreamPermissionDecisionschema::approve-once,:approve-for-session,:approve-for-location,:approve-permanently,:reject,:user-not-available. Previously unsupported values (e.g.{:kind 42}) would be sent on the wire and surface as opaque server-side errors.tools/define-tool-from-specmirrorstools/define-tool: when:handleris omitted, no:tool-handlerwrapper is installed (declaration-only tool).
Upstream v1.0.0-beta.4 shipped no new Node.js SDK API surface relative to
v1.0.0-beta.3 — every SDK-visible change in the upstream diff
(ModelBilling.multiplier optional, extension permission kinds,
detachedFromSpawningParentSessionId, advisor block fields on
assistant.message, model on assistant.message, model-picker categories,
session.commands.respondToQueuedCommand) was already brought in by the
earlier CLI 1.0.48 schema sync (PR #103), whose entries appear below.
session.tasks.sendMessage and the C#/Go-only changes from beta.4 are
deliberately out of scope per the API-parity rule (see Tracked-but-not-ported).
This release bumps the upstream marker from 1.0.0-beta.3 to 1.0.0-beta.4.
- Schema bump —
.copilot-schema-versionadvanced from1.0.46to1.0.48(the latest GA on npm). Generated wire specs and coercions regenerated. :remote-sessionsession config option —create-sessionandresume-sessionaccept an optional:remote-sessionkey set to:off,:export, or:on, enabling per-session Mission Control remote mode at session-creation time without a separateremote-enablecall. Forwarded to the wire asremoteSession. Reuses the::remote-session-modespec. (upstream PR #1295, CLI 1.0.48):copilot/session.custom_notificationevent — Skills (via theNotifyblock) can emit arbitrary application-level events to the SDK. The event exposes:source,:name,:payload(any JSON value), optional:subject(map of keyword→string), and optional:version(positive integer). Added tosdk/event-typesandsdk/session-events; new idiom spec::session.custom_notification-data. The:subjectand:payloadfields contain source-defined identifiers and opaque JSON, so their keys are preserved verbatim by the protocol normalizer (no kebab-casing) — matching the existing escape hatch forexternal_tool.requestedarguments. (upstream PR #1292, CLI 1.0.48)- Extension permission kinds —
::permission-kindaccepts the new upstream values:extension-managementand:extension-permission-access, emitted by the CLI for extension lifecycle and capability-access prompts. (upstream PR #1239, CLI 1.0.44-3) :detached-from-spawning-parent-session-idonsession.startevents — when a session continues another session's context (e.g., a detached headless rem-agent run launched on the parent's interactive shutdown),session.startnow exposes the spawning parent's session id. Telemetry from such sessions is reported under the parent'ssession_id. Accepted by both the regenerated wire spec and the hand-curated::specs/session.start-data. (upstream PR #1239, CLI 1.0.44-3)- Anthropic advisor block fields on
assistant.message—::assistant.message-datanow accepts the optional:anthropic-advisor-blocks(raw Anthropic content array with advisor blocks, for verbatim replay),:anthropic-advisor-model, and:model(model that produced the response, when known). The regenerated wire spec already exposed these; the hand-curated idiom spec now mirrors them. (upstream PR #1263, CLI 1.0.45) :model-picker-category/:model-picker-price-categoryonlist-models— the regeneratedModelshape carries upstream's new model-picker categorization fields ("lightweight" | "versatile" | "powerful"and"low" | "medium" | "high" | "very_high").parse-model-infonow surfaces both as idiomatic strings (open enum) on each entry returned bycopilot/list-models. (upstream PR #1270, CLI 1.0.46)session/respond-to-queued-command!(experimental) — wraps the newsession.commands.respondToQueuedCommandRPC for acknowledging:copilot/command.queuedevents. Accepts{:request-id ... :handled? true/false :stop-processing-queue? bool?}and forwards the wire shape{:requestId ..., :result {:handled bool, :stopProcessingQueue bool?}}. Marked experimental, mirroring upstream's exposure of this only via the generated low-level RPC. (upstream PR #1263, CLI 1.0.45):is-autopilot-continuationonuser.messageevents —::user.message-datanow accepts the optional boolean flag emitted by autopilot's continuation loop.trueindicates the message was auto-injected rather than typed by the user; used to distinguish autopilot-driven turns in telemetry. Wire key:isAutopilotContinuation→ kebab-case key:is-autopilot-continuation(no?suffix — camel-snake-kebab does not append?for booleans). (upstream PR #1286, CLI 1.0.47):api-endpointonassistant.usageevents —::assistant.usage-datanow accepts the optional API endpoint string identifying which CAPI endpoint produced the model call. Known values:"/chat/completions","/v1/messages","/responses","ws:/responses". Modeled as an open string spec for forward-compatibility; the regenerated wire spec enforces the closed enum. (upstream PR #1286, CLI 1.0.47):modeonsession/remote-enable(experimental) — thesession.remote.enableRPC now accepts an optionalRemoteSessionModeparameter.remote-enablegained a 2-arity overload(remote-enable session opts)whereoptsmay contain:modeset to:off,:export, or:on.:offdisables remote,:exportexports session events to Mission Control without enabling remote steering,:onenables both. Zero-arg call is unchanged. New idiom specs:::remote-session-modeand::remote-enable-opts. (upstream PR #1288, CLI 1.0.48-1):recurringonsession.schedule_createdevents —::session.schedule_created-datanow accepts the optional boolean flag indicating whether the schedule re-arms after each tick (/every) or fires once (/after). Wire key:recurring→ kebab-case key:recurring(no?suffix — csk does not append?for booleans). (upstream PR #1288, CLI 1.0.48-1)
session.tasks.sendMessage(experimental) — the upstream Tasks API (session.tasks.*) is intentionally not surfaced in the Clojure SDK yet; the newsendMessageRPC is tracked here for a future port. (upstream PR #1239, CLI 1.0.44-3)UserToolSessionApprovalextension kinds — upstream addsextension-managementandextension-permission-accessto theUserToolSessionApprovaldiscriminated union. The Clojure idiom spec for::approvalis intentionally broad (map?), so these payloads pass through unchanged; only the wire-side discriminator changed. (upstream PR #1263, CLI 1.0.45)WorkspacesGetWorkspaceResult.session_sync_levelremoval — upstream dropped this field. The Clojure SDK never surfaced it; no change needed. (upstream PR #1239, CLI 1.0.44-3)session.commands.list/session.commands.invokeRPCs — upstream added these slash-command discovery and invocation methods to the generated RPC layer in CLI 1.0.47. The Node.js SDK's publicCopilotSessiondoes NOT expose them as high-level methods (only via the low-level generated RPC), so per the API-parity rule the Clojure SDK does not surface them either. (upstream PR #1286, CLI 1.0.47)ModelBilling.tokenPrices— upstream added per-token pricing fields (inputPrice,outputPrice,cachePrice,batchSize) toModel.billing. The Clojure idiom spec for::billingis intentionally broad (open map), so these payloads pass throughlist-modelsunchanged. No dedicated idiom spec added yet. (upstream PR #1270, CLI 1.0.46)
1.0.0-beta.3.0 - 2026-05-12
- Version scheme — Maven qualifier support. The release workflow,
script/release.sh, andbuild.clj(sync-version,bump-version) now accept upstream versions carrying Maven pre-release qualifiers (e.g.,1.0.0-beta.3in addition to0.1.23) and the corresponding 4th-segment forms (e.g.,1.0.0-beta.3.0,1.0.0-beta.3.0-SNAPSHOT). The full grammar isX.Y.Z[-(alpha|beta|rc).M].N[-SNAPSHOT]. Maven and tools.deps already sort these correctly; only our own validation regex was too strict.
:enable-session-telemetry?session config — boolean. When omitted (default) ortrue, the CLI's internal session telemetry is enabled for GitHub-authenticated sessions. Set tofalseto disable. With a custom:provider(BYOK), session telemetry is always disabled regardless of this setting. Independent of the OpenTelemetry config in:telemetry. Accepted in bothcreate-sessionandresume-session. Wire key:enableSessionTelemetry. (upstream PR #1224):on-exit-plan-modesession handler — restores the Exit Plan Mode request RPC. When the SDK is configured with this handler, the CLI sends anexitPlanMode.requestRPC asking the client to approve leaving plan mode. The handler receives(request, {:session-id ...})whererequesthas:summary, optional:plan-content,:actions(vec of string), and:recommended-action. Returns an idiomatic map with:approved?(required boolean), optional:selected-action,:feedback. When omitted, the SDK auto-replies with the wire-shaped equivalent of{:approved? true}(i.e.,{"approved": true}on the wire) and sets therequestExitPlanModecapability flag tofalse. Accepted in bothcreate-sessionandresume-session. (upstream PR #1228):on-auto-mode-switchsession handler — restores the Auto Mode Switch request RPC. When the SDK is configured with this handler, the CLI sends anautoModeSwitch.requestRPC asking the client whether to switch the agent to auto mode after a rate-limit event. The handler receives(request, {:session-id ...})whererequestmay include:error-codeand:retry-after-seconds. Returns:yes,:yes-always, or:no(keyword or matching string), or a map{:response ...}with the same. When omitted, the SDK auto-replies with the wire-shaped equivalent of:no(i.e.,{"response": "no"}on the wire) and sets therequestAutoModeSwitchcapability flag tofalse. Accepted in bothcreate-sessionandresume-session. (upstream PR #1228)AbortReasonwire enum —abortevents now carry a:reasonfield that is a closed enum of"user_initiated","remote_command","user_abort". Validated by the regenerated wire spec. (upstream schema 1.0.44-2)subagent.started.modelfield —subagent.startedevents now expose an optional:modelfield identifying the model the sub-agent will run against. Both the regenerated wire spec and the hand-curated idiom spec (::specs/subagent.started-data) accept it. (upstream schema 1.0.44-2)session.remote.enable/session.remote.disable(schema-only) — the regeneratedschemas/api.schema.jsonintroduces two new experimental RPC methods for enabling/disabling remote session access, along with aRemoteEnableResultdefinition. Not yet surfaced in the Clojure public API — the schemas are tracked here so future ports can lift them without another schema bump. (upstream schema 1.0.44-2)
- Schema bump —
.copilot-schema-versionadvanced from1.0.42to1.0.44-2; generated wire specs and coercions regenerated. - MCP binary tool result mime-type fallback — when an MCP tool returns a
blob resource whose
:mime-typeis missing, the empty string, or any non-string value, the SDK now falls back to"application/octet-stream"(previously onlyniltriggered the fallback). Matches upstream Node.js behavior. (upstream PR #1222)
:remote?client option — whentrue, the SDK appends--remoteto the spawned CLI args so the headless CLI exposes its session over a GitHub-hosted remote endpoint. Ignored when:cli-urlis set (i.e., when connecting to an externally-managed CLI). (upstream PR #1192)session/remote-enable,session/remote-disable(experimental) — enable/disable remote steerability for an active session via the newsession.remote.enable/session.remote.disableJSON-RPC methods.remote-enablereturns{:url ... :remote-steerable boolean}. (upstream PR #1192)- ProviderConfig overrides —
:providerconfig now accepts:model-id,:wire-model,:max-input-tokens, and:max-output-tokensalongside the existing:base-url/:api-keyfields.:max-input-tokensis renamed to wiremaxPromptTokensto match upstream'stoWireProviderConfig. (upstream PR #966) session.schedule_created/session.schedule_cancelledevents — the CLI now emits these events when the/everyslash-command registers a scheduled prompt or it is cancelled from the schedule manager dialog; both are added toevent-typesandsession-events. (upstream schema 1.0.42)mcpToolNamefield on tool requests — already-existing:mcp-tool-nameonAssistantMessageToolRequestis now spec-validated by the regenerated wire layer. (upstream schema 1.0.42)
- Schema bump —
.copilot-schema-versionadvanced from1.0.41-0to1.0.42; generated wire specs and coercions regenerated. CustomAgentsUpdatedAgent.toolsis now nilable (tools: string[] | null) on the wire; the regenerated wire spec acceptsnil. (upstream schema 1.0.41-1)
:copilot-homeclient option — base directory for Copilot data files; forwarded to the spawned CLI as theCOPILOT_HOMEenvironment variable. (upstream PR #1191):instruction-directoriessession config — additional directories to search for custom instruction files. Accepted increate-session,resume-session, andjoin-sessionconfigs and forwarded asinstructionDirectorieson the wire. (upstream PR #1190):tcp-connection-tokenclient option — connection token for the headless CLI server when running in TCP mode. When the SDK spawns its own CLI in TCP mode and the caller did not supply a token, a UUID is auto-generated so the loopback listener is safe by default. The token is sent to the CLI via theCOPILOT_CONNECTION_TOKENenvironment variable. Rejected when combined with:use-stdio? true(stdio is pre-authenticated by transport). (upstream PR #1176)connecthandshake — the SDK now performs the protocol-version handshake via the newconnectJSON-RPC method (carrying the optional connection token). Falls back topingagainst legacy servers that respond with JSON-RPCMethodNotFound(-32601), or with a non-MethodNotFound code but the message"Unhandled method connect"(matching upstream Node parity,client.ts:1132-1135). (upstream PR #1176):continue-pending-work?resume/join session config — when truthy, the CLI re-emits any in-flightpermission.requestedand external tool requests on resume so the consumer can respond, instead of treating them as interrupted. Forwarded ascontinuePendingWorkonsession.resume.
- Schema bump —
.copilot-schema-versionadvanced from0.0.403to1.0.41-0; generated wire specs (src/github/copilot_sdk/generated/) and field-level coercions regenerated. The upstream session-events schema now references each event variant via$ref; the codegen emitter (script/) was updated to dereference these refs when collecting leaf properties and emitting per-event data specs. (upstream PR #1184)
- Per-session GitHub authentication —
:github-tokenis now accepted increate-session,<create-session,resume-session,<resume-session, andjoin-sessionconfigs and is forwarded asgitHubTokenon session create/resume RPCs. This enables one client to manage sessions authenticated as different GitHub users. (upstream PR #1124) - Stable v0.3.0 permission decision kinds —
::permission-kindnow includes:hook, and::permission-result-kindaccepts upstream decision kinds:approve-once,:approve-for-session,:approve-for-location,:reject, and:user-not-availablein addition to:no-result. Legacy Clojure denial aliases remain accepted and are normalized before the SDK sends decisions to the CLI. (upstream PR #1124)
approve-allparity —copilot/approve-allnow returns{:kind :approve-once}, matching the upstream Node.js SDKapproveAllhelper. Existing legacy:approvedpermission results are still accepted from custom handlers and normalized to:approve-once. (upstream PR #1124)
- Schema-driven codegen pipeline — new
bb codegentask generatessrc/github/copilot_sdk/generated/event_specs.cljfrom the upstream@github/copilot/schemas/session-events.schema.json. Produces ~190 spec forms (one leaf spec per unique property, one*-dataspec per event variant, one envelope spec per variant, and an aggregate::eventspec). - Schema fetch task — new
bb schemas:fetchdownloads the upstream npm package at the version pinned in.copilot-schema-versionand extracts schema JSON files intoschemas/(committed for reproducibility). - CI codegen-check workflow —
.github/workflows/codegen-check.ymlregenerates on every PR touching schemas, generator, generated files, or the pinned version, and fails on drift between committed and regenerated output. - Developer documentation — new
doc/codegen.mdexplains the pipeline, workflows for local development, and the JSON Schema →clojure.spectranslation rules. - Phase 3.5: three-tier wire/coerce/idiom architecture — new
script/codegen/coercions.edn(hand-curated event-scoped coercion table) and generatedsrc/github/copilot_sdk/generated/coerce.clj(event-wire->idiomandevent-idiom->wire). The runtime event dispatcher inclient.cljnow applies idiomatic coercion (e.g. ISO-8601 strings →java.time.Instant) before delivering events to user handlers. Coercion is fail-open: parse failures log a warning and deliver the uncoerced-but-normalized event so a malformed payload cannot kill the notification go-loop. Thehand-written-specs-agree-with-generateddrift audit now runs against coerced data with an emptyknown-driftsset, and three new invariants are enforced by tests (every coercion is exercised, converters are idempotent, round-trip is semantically lossless). - Historical event coercion —
session/get-messagesnow applies the same wire→idiom coercion pipeline as the live notification path, so:start-timeonsession.startevents fetched from history is also delivered as ajava.time.Instant. New integration testtest-get-messages-applies-coercionenforces this.
- Phase 6: instrument deduplication —
src/github/copilot_sdk/instrument.cljno longer maintains three parallel symbol lists (ones/fdefper public API fn, one symbol list passed toinstrument-all!, one tounstrument-all!). A new privateregister-fdef!macro both delegates tos/fdefand records the fully-qualified symbol in a singleregistered-fdefsregistry; bothinstrument-all!andunstrument-all!now derive their target list from that registry. The macro fail-fast rejects unqualified symbols at macroexpansion time, so a stale or alias-qualified entry is caught immediately rather than silently leaving an instrumentation gap. Net effect: ~162 lines removed frominstrument.clj, no behavior change, and adding a new public API fn now requires a single edit instead of three.
session.startevent delivery —:selected-modelwas being read with the wrong (camelCase) key:selectedModelin the runtime dispatcher; fixed to:selected-modelto match the kebab-case keys produced byutil/wire->clj.
- Mock server validates injected event types —
mock/send-session-event!now rejects unknown event types instead of silently emitting an unrecognised notification. Validation uses the SDK's canonical publicevent-typesregistry as the source of truth, so any event the SDK recognises can still be injected. A dedicatedmock/send-v3-broadcast-event!helper restricts injection to the five protocol v3 broadcast events (kept in sync withclient/handle-v3-broadcast-event!); the four v3 integration tests have migrated to it. Surfaces typos like"session.startt"immediately rather than as a confusing missing-event test failure.
0.3.0.0-SNAPSHOT - 2026-04-23
defaultAgent.excludedToolssession option — new:default-agent {:excluded-tools [...]}config for create, resume, and join session paths. This hides selected tools from the built-in/default agent while preserving tool availability for custom agents. (upstream commitb1b0df5c)- Session FS provider adapter — new
create-session-fs-adapterhelper adapts provider-style filesystem functions into structuredsessionFs.*RPC results. Session factories now also auto-adapt provider-style maps while preserving the existing low-level one-arg handler contract. (upstream commita3e273c9) - Generated event data specs — added explicit specs for assistant reasoning/message/usage fields, MCP server status/load events, skills loaded events, and extension loaded events from the upstream generated schema.
- Integration tests for
defaultAgentwire params, session FS adapter behavior, session FS factory auto-adaptation, extension status values, and event data specs.
- Extension status enum parity —
session.extensions_loadednow accepts upstream statuses"running","starting","disabled", and"failed"and rejects obsolete"enabled". - Message content specs — assistant/user message and reasoning event content remains string-only while elicitation result content accepts maps, matching upstream generated schemas.
0.2.2.0 - 2026-04-20
includeSubAgentStreamingEventssession option — new boolean:include-sub-agent-streaming-events?on::session-config,::resume-session-config, and::join-session-config. Whentrue(default), sub-agent streaming events are forwarded to the parent session's event stream. (upstream PR #1108)- Per-request HTTP headers on
send!— new:request-headersoption (map of string→string) on::send-options. Forwarded as wirerequestHeadersand merged with provider-level headers by the CLI. (upstream PR #1094) - Provider-level HTTP headers — new
:headersfield (map of string→string) on::providerconfig. Sent with each model request to BYOK endpoints. (upstream PR #1094) ::can-offer-session-approvalspec — boolean field present onpermission.requestedevents of kindwriteFile, indicating the CLI can offer a "trust this session" choice. (CLI 1.0.28, upstream PR #1089)::reasoning-tokensspec — non-negative integer field onassistant.usageandsession.usage_infoevents tracking tokens used for reasoning content. (CLI 1.0.32, upstream PR #1105)::agent-idspec — optional string field on::base-event, identifying which (sub-)agent emitted the event. (upstream PR #1108)- Integration tests for all new wire fields and specs (6 new
deftests covering sync/async wire forwarding and the 3 new spec additions).
convert-mcp-call-tool-result— new public function intoolsnamespace that converts MCPCallToolResultformat into the SDK'sToolResultObject. Handles text, image, and resource content types. (upstream PR #1049)default-join-session-permission-handler— new permission handler forresume-sessionthat returns{:kind :no-result}, signaling the CLI to handle permissions itself. SendsrequestPermission: falseon the wire. (upstream PR #1056)- MCP config spec aliases —
::mcp-stdio-serverand::mcp-http-serveras aliases for::mcp-local-serverand::mcp-remote-serverrespectively, matching upstream rename from Local→Stdio, Remote→HTTP. Old names kept for backward compatibility. (upstream PR #1051) - Per-agent skills field —
::agent-skills(vector of strings) on::custom-agentspec, allowing skill injection per custom agent. (upstream PR #995) - Memory permission event specs —
::memory-action,::memory-direction,::memory-reasonspecs for enriched memory permission request events. (CLI 1.0.22, upstream PR #1055) - New RPC wrappers in
sessionnamespace (all experimental):session-name-get,session-name-set!— get/set session display name (CLI 1.0.26, upstream PR #1076)workspace-get-workspace— get current workspace metadata (CLI 1.0.26, upstream PR #1076)mcp-discover— discover MCP servers in a working directory (CLI 1.0.22, upstream PR #1055)usage-get-metrics— get session usage metrics (CLI 1.0.22, upstream PR #1055)
- Integration tests for all new features (18 tests covering convert-mcp-call-tool-result, spec renames, agent skills, requestPermission behavior, new RPCs, and memory specs)
requestPermissionon resume —resume-sessionnow sendsrequestPermission: falsewhen usingdefault-join-session-permission-handler, andtruewhen using any other handler (e.g.,approve-all). Previously always senttrue. (upstream PR #1056)
enableConfigDiscoverysession option — new boolean:enable-config-discoveryon session and resume configs. Auto-discovers.mcp.json,.vscode/mcp.json, skills, etc. Instruction files are always loaded regardless. (upstream PR #1044)modelCapabilitiesoverride — new:model-capabilitiesoption on session config, resume config, andswitch-model!/set-model!. Pass a partial capabilities map (e.g.{:model-supports {:supports-vision true}}) to override model capabilities for the session. (upstream PR #1029)history-truncate!— new experimental function to trigger manual truncation of session context (upstream PR #1039)sessions-fork!— new experimental function to fork the current session (upstream PR #1039)- Integration tests for all new features (wire param verification, RPC routing)
compaction-compact!RPC renamed — underlying JSON-RPC method changed fromsession.compaction.compacttosession.history.compact(upstream PR #1039). The Clojure function name is unchanged for backward compatibility.
0.2.1.1 - 2026-04-04
- Session RPC wrappers — new experimental functions for session-level RPCs previously only accessible via
proto/send-request!:mode-get,mode-set!— get/set agent mode (interactive/plan/autopilot)plan-read,plan-update!,plan-delete!— read/update/delete session plan fileworkspace-list-files,workspace-read-file,workspace-create-file!— session workspace file operationsagent-list,agent-get-current,agent-select!,agent-deselect!,agent-reload!— custom agent managementfleet-start!— start parallel sub-sessions
- MCP config wrappers — new experimental server-level functions in
client:mcp-config-list,mcp-config-add!,mcp-config-update!,mcp-config-remove!— MCP server configuration management
- Hooks integration tests — 6 tests covering all hook types (preToolUse, postToolUse, sessionStart, unknownType, handler exceptions, no-hooks)
- User input handler tests — 2 tests for
userInput.requestserver→client RPC - System message transform tests — 3 tests for
systemMessage.transformcallback invocation, error fallback, and passthrough - Tool result normalization tests — 3 tests for string, nil, and structured ToolResultObject results via v3 broadcast
- Session RPC wrapper tests — 18 integration tests for all new RPC wrapper functions
- Mock server enhancements —
send-rpc-request!for testing server→client RPCs, response routing in server loop, 30+ new method stubs - Full
s/fdefinstrumentation for all 19 new public functions
session.errorevent data spec enriched — optional:status-code(int),:provider-call-id(string), and:url(string) fields added to::session.error-dataspec. These fields carry HTTP status codes, GitHub request tracing IDs, and actionable URLs from upstream error events (upstream PR #999, runtime 1.0.17).
0.2.1.0 - 2026-04-04
resolvedByHookguard onpermission.requested— when the runtime resolves a permission request via apermissionRequesthook, the broadcast event includesresolvedByHook: true. The SDK now skips the client's:on-permission-requesthandler and does not send thehandlePendingPermissionRequestRPC, preventing duplicate responses. Event subscribers still observe the event (upstream PR #999, runtime 1.0.17).- New permission result kinds —
:denied-by-content-exclusion-policyand:denied-by-permission-request-hookadded to::permission-result-kindspec (upstream PR #999). - MCP fields on
tool.execution_startevents — optional:mcp-server-nameand:mcp-tool-namefields added to::tool.execution_start-dataspec indicating the MCP server and original tool name for MCP-originated tool calls (upstream runtime 1.0.17). ::resolved-by-hookspec — boolean spec for theresolvedByHookfield onpermission.requestedevent data.- Commands example — new
examples/commands.cljdemonstrating slash command registration and handling. - Integration tests for
resolvedByHookguard (both true and false cases), new permission result kind specs, and MCP tool event fields.
- Public preview branding — README updated from "technical preview" to "public preview" with link to the announcement.
- BREAKING: Elicitation handler signature changed from 2-arg
(fn [request ctx])to single-arg(fn [context]). TheElicitationContextmap now includes:session-idalongside request fields (:message,:requested-schema,:mode,:elicitation-source,:url). Matches upstream cross-SDK consistency change (upstream PR #960).::elicitation-requestspec renamed to::elicitation-context.
remote-steerable?field onsession.startandsession.resumeevents — event data now includes optional:remote-steerable?boolean field indicating whether the session supports remote steering via Mission Control. Replaces previous:steerable?(upstream PRs #927, #908).get-session-metadata— new function on client for efficient O(1) session lookup by ID. Returns session metadata map if found, ornilif not found. Sendssession.getMetadataJSON-RPC call. Sharedwire->session-metadatahelper extracted fromlist-sessionsto eliminate duplication (upstream PR #899).- Elicitation provider support — new
:on-elicitation-requesthandler onSessionConfigandResumeSessionConfig. When provided, sendsrequestElicitation: truein the session create/resume RPC. The runtime routeselicitation.requestedbroadcast events to the handler, and results are sent back viasession.ui.handlePendingElicitationRPC. Handler errors automatically send a cancel response. New::elicitation-requestand::on-elicitation-requestspecs (upstream PR #908). capabilities.changedevent handling — session capabilities are dynamically updated whencapabilities.changedbroadcast events are received, e.g. when another client joins with elicitation support (upstream PR #908).- New event types —
sampling.requested,sampling.completed,session.remote_steerable_changed,capabilities.changedadded to event type enum and event sets (upstream PRs #908, #916). - Subagent event data fields —
subagent.started,subagent.completed,subagent.failedevents now include optional:model,:total-tool-calls,:total-tokens,:duration-msfields. New::subagent.started-data,::subagent.completed-data,::subagent.failed-dataspecs (upstream PR #916). skill.invokedevent:descriptionfield — optional:descriptionfrom SKILL.md frontmatter (upstream PR #916).session.custom_agents_updatedpayload spec — full::session.custom_agents_updated-dataspec with:agents(array of agent metadata),:warnings,:errors. New::custom-agent-infospec (upstream PR #916).- SessionFs virtual filesystem — new
:session-fsclient option with:initial-cwd,:session-state-path,:conventions. Client callssessionFs.setProviderRPC on connect. New:create-session-fs-handleron session config provides a per-session FS handler factory. The SDK dispatches incomingsessionFs.*RPC requests (10 operations:readFile,writeFile,appendFile,exists,stat,mkdir,readdir,readdirWithTypes,rm,rename) to the session's handler. Enables custom session storage backends (upstream PR #917). aborted?onsession.task_complete— optional boolean indicating the preceding agentic loop was cancelled via abort signal. New::aborted?spec (upstream PR #917).timeouttool result type —::result-typenow accepts:timeout/"timeout"for tool calls that timed out (upstream PR #970).- Integration tests for elicitation provider routing, handler error→cancel fallback, capabilities.changed updates, and requestElicitation wire flag.
- BREAKING:
::steerable?renamed to::remote-steerable?onsession.startandsession.resumeevent data, matching upstream wire field rename fromsteerabletoremoteSteerable(upstream PR #908). session.idleis now ephemeral — the runtime no longer persistssession.idleevents in session history.get-messageswill no longer returnsession.idleevents. Live event listeners (used bysend-and-wait!andsend!) are unaffected and still receive it (upstream PR #927).
0.2.1.1-SNAPSHOT - 2026-03-26
- Commands support — register slash commands per-session via
:commandsoption in session config. Each command definition has:name, optional:description, and a:command-handlerfunction. Commands are sent on the wire (name + description) and executed viacommand.executebroadcast events withsession.commands.handlePendingCommandRPC callback (upstream PR #906). - UI Elicitation convenience API — new public functions
confirm!,select!,input!wrap the existingui-elicitation!with typed schemas.capabilitiesaccessor returns host capabilities from session create/resume response.elicitation-supported?predicate checks if the host supports elicitation dialogs. All convenience methods throw with a clear error when elicitation is unsupported (upstream PR #906). COPILOT_CLI_PATHenv var fallback — client constructor now checksCOPILOT_CLI_PATHenvironment variable before defaulting to"copilot"when no explicit:cli-pathor:cli-urlis provided (upstream PR #906).- New event type
session.custom_agents_updatedadded to event type enum. :hostfield onsession.handoffevents — event data now includes optional:hostfield with the GitHub host URL. New::session.handoff-dataspec documents the shape (upstream PR #900).- New specs:
::command-definition,::commands,::session-capabilities,::elicitation-params,::elicitation-result,::input-options. - Function specs and instrumentation for
capabilities,elicitation-supported?,confirm!,select!,input!. - Integration tests for command wire format, command.execute routing, unknown command errors, handler errors, capabilities storage, and elicitation guards.
ui-elicitation!no longer marked^:experimental— now asserts elicitation support before calling. Updated fdef to use::elicitation-paramsspec.- Mock server
handle-requestnow supportssession.commands.handlePendingCommandRPC and allows request hooks to merge additional data into responses.
0.2.0.0 - 2026-03-23
- System message customize mode — new
:customizemode for:system-messageenables section-level overrides of the Copilot system prompt. Ten configurable sections::identity,:tone,:tool-efficiency,:environment-context,:code-change-rules,:guidelines,:safety,:tool-instructions,:custom-instructions,:last-instructions. Each section supports static actions (:replace,:remove,:append,:prepend) and transform callbacks (1-arity functions receiving current content, returning modified text). Newsystem-prompt-sectionsconstant exported from main namespace (upstream PR #816). - New experimental RPC methods — thin wrapper functions in
sessionnamespace for emerging CLI APIs (upstream PR #900):- Skills:
skills-list,skills-enable!,skills-disable!,skills-reload! - MCP servers:
mcp-list,mcp-enable!,mcp-disable!,mcp-reload! - Extensions:
extensions-list,extensions-enable!,extensions-disable!,extensions-reload! - Plugins:
plugins-list - Compaction:
compaction-compact! - Shell:
shell-exec!,shell-kill! - UI:
ui-elicitation!
- Skills:
- 15 new event types added to the event type enum:
command.completed,command.execute,command.queued,commands.changed,exit_plan_mode.requested,exit_plan_mode.completed,external_tool.completed,mcp.oauth_required,mcp.oauth_completed,session.tools_updated,session.background_tasks_changed,session.skills_loaded,session.mcp_servers_loaded,session.mcp_server_status_changed,session.extensions_loaded. - Experimental API annotations (
^:experimentalmetadata) on all new RPC method wrappers. - Function specs (
s/fdef) and instrumentation for all new RPC methods.
- Version bump to
0.2.0.0-SNAPSHOTtracking upstream copilot-sdk v0.2.0. - Updated
interaction-eventsset to include new event types (commands, MCP OAuth, exit plan mode).
0.1.33.0-SNAPSHOT - 2026-03-19
:no-resultpermission outcome — extensions can attach to sessions without actively answering permission requests by returning{:kind :no-result}from their:on-permission-requesthandler. On v3 protocol, thehandlePendingPermissionRequestRPC is skipped; on v2, an error is propagated to the CLI (upstream PR #802).:blobattachment type for outbound messages — send inline base64-encoded data (e.g. images) via{:type :blob :data "..." :mime-type "image/png"}in:attachments. Previously blob attachments were only supported in inbound events (upstream PR #731).
:skip-permission?option on tool definitions — whentrue, the tool executes without triggering a permission prompt. Sent asskipPermission: truein the wire protocol (upstream PR #808).- OpenTelemetry support: new
:telemetryclient option (map with:otlp-endpoint,:file-path,:exporter-type,:source-name,:capture-content?) configures OTel environment variables on the spawned CLI process. New:on-get-trace-contextclient option (0-arity fn returning{:traceparent ... :tracestate ...}) enables W3C Trace Context propagation intosession.create,session.resume, andsession.sendRPCs (upstream PR #785). - Tool invocations now receive
:traceparentand:tracestatefields in the invocation context map when the CLI provides them (upstream PR #785). - Optional
:reasoning-effortparameter inswitch-model!andset-model!— pass{:reasoning-effort "high"}as a third argument to set reasoning effort when switching models (upstream PR #712). - New event data fields from upstream codegen update (upstream PR #796):
session.startevent::reasoning-effort,:already-in-use?,:host-type,:head-commit,:base-commitoptional fieldssession.resumeevent: new::session.resume-dataspec with:event-count,:selected-model,:reasoning-effort,:already-in-use?,:host-type,:head-commit,:base-commitsession.model_changeevent: new::session.model_change-dataspec with:new-model,:previous-model,:reasoning-effort,:previous-reasoning-effortuser.messageevent: new:blobattachment type with:data(base64),:mime-type, optional:display-name
join-sessionnow makes:on-permission-requestoptional. When omitted, a default handler returns{:kind :no-result}, leaving any pending permission request unanswered. This matches the upstreamJoinSessionConfigwhereonPermissionRequestis optional (upstream PR #802).:auto-restart?client option is deprecated and has no effect. The auto-restart/reconnect behavior has been removed across all official SDKs. The option is retained for backward compatibility but will be removed in a future release (upstream PR #803).
- "Permission Handling" section in README.md — covers deny-by-default model,
approve-all, custom handlers, and links to API reference (upstream PR #879).
0.1.32.0 - 2026-03-12
- Session pre-registration: sessions are now created and registered in client state before the RPC call, preventing early events (e.g.
session.start) from being dropped. Session IDs are generated client-side viajava.util.UUID/randomUUIDwhen not explicitly provided. On RPC failure, sessions are automatically cleaned up (upstream PR #664). :on-eventoptional handler increate-sessionandresume-sessionconfigs — a 1-arity function receiving event maps, registered before the RPC call so no events are missed. Equivalent to callingsubscribe-eventsimmediately after creation, but executes earlier in the lifecycle (upstream PR #664).join-sessionfunction — convenience for extensions running as child processes of the Copilot CLI. ReadsSESSION_IDfrom environment, creates a child-process client, and resumes the session with:disable-resume? true. Returns{:client ... :session ...}(upstream PR #737).:copilot/system.notificationevent type — structured notification events with:kinddiscriminator (agent_completed,shell_completed,shell_detached_completed) (upstream PR #737).
CopilotSessionrecord no longer includesworkspace-pathas a field. Use(workspace-path session)accessor which reads from mutable session state. This enables the pre-registration flow where workspace-path is set after the RPC response.
0.1.32.0 - 2026-03-10
:agentoptional string parameter increate-sessionandresume-sessionconfigs — pre-selects a custom agent by name when the session starts. Must match a name in:custom-agents. Equivalent to callingagent.selectafter creation (upstream PR #722).:on-list-modelsoptional handler in client options — zero-arg function returning model info maps. Bypasses themodels.listRPC call and does not requirestart!. Results use the same promise-based cache (upstream PR #730).log!session method — logs a message to the session timeline via"session.log"RPC. Accepts optional:level("info","warning","error") and:ephemeral?(transient, not persisted) options. Returns the event ID string (upstream PR #737).:is-child-process?client option — whentrue, the SDK connects via its own stdio to a parent Copilot CLI process instead of spawning a new one. Mutually exclusive with:cli-url; requires:use-stdio?to betrue(or unset) (upstream PR #737).
0.1.30.1 - 2026-03-07
disconnect!function as the preferred API for closing sessions, matching upstream SDK'sdisconnect()(upstream PR #599).destroy!is deprecated but still works as an alias.- 6 new broadcast event types from CLI protocol 0.0.421 (upstream PR #684):
:copilot/permission.requested,:copilot/permission.completed,:copilot/user_input.requested,:copilot/user_input.completed,:copilot/elicitation.requested,:copilot/elicitation.completed - New
interaction-eventscategory set for permission, user input, and elicitation flow events :memorypermission kind added to::permission-kindspec (upstream PR #684)- Protocol v3 support with backwards compatibility (supports v2 and v3). The SDK negotiates the protocol version with the CLI server at startup using a supported range
[2, 3]. Version 3 replacestool.callandpermission.requestRPC callbacks with broadcast events (external_tool.requested,permission.requested) and new RPC response methods (session.tools.handlePendingToolCall,session.permissions.handlePendingPermissionRequest). - Custom agents & sub-agent orchestration guide (
doc/guides/custom-agents.md)
stop!now usesdisconnect!internally instead ofdestroy!delete-session!docstring clarified to contrast withdisconnect!- Version negotiation now validates the CLI-reported protocol version is within the supported range
[2, 3]instead of requiring exact match on version 2
destroy!— usedisconnect!instead.destroy!delegates todisconnect!and will be removed in a future release.
0.1.30.0 - 2026-03-04
- Support overriding built-in tools via
:overrides-built-in-tooloption indefine-tool(upstream PR #636). Tools with this flag set totruecan override built-in tools likegreporedit_file. Without the flag, name clashes cause an error. set-model!function as alias forswitch-model!, matching the upstream SDK'ssetModel()API (upstream PR #621).
- Updated
switch-model!andget-current-modeldocstrings — removed stale "not yet implemented as of CLI 0.0.412" notes. These RPC methods are now supported.
0.1.29.0 - 2026-03-03
:copilot/subagent.deselectedevent type added to::event-typespec,event-typesvar, and API reference table (upstream PR #605 / CLI 0.0.420).:github-referenceattachment type: represents a GitHub issue, PR, or discussion attached to a user message. Added to::attachment-typespec and::attachmentspec. Data fields:number,title,reference-type("issue"/"pr"/"discussion"),state,url(upstream PR #605).::assistant.turn_start-dataspec withturn-id(required) andinteraction-id(optional).:interaction-idoptional field added to::user.message-data,::assistant.turn_start-data,::assistant.message_delta-data, and::tool.execution_complete-dataspecs (upstream PR #605).:modeloptional field added to::tool.execution_complete-dataspec — model used for the tool execution (upstream PR #605).:plugin-nameand:plugin-versionoptional fields added to::skill.invoked-dataspec (upstream PR #605).
- Azure Managed Identity BYOK guide (
doc/auth/azure-managed-identity.md): shows how to useDefaultAzureCredentialwith short-lived bearer tokens for Azure AI Foundry, with Clojure examples for basic usage and token refresh (upstream PR #498). - Updated BYOK limitations to link to the Managed Identity workaround instead of listing it as fully unsupported.
- Added Azure Managed Identity guide to
doc/auth/index.mdanddoc/index.md.
examples/file_attachments.clj— Demonstrates sending file attachments with prompts using:attachmentsin message options.examples/session_resume.clj— Demonstrates session resume: create session, send secret word, resume by ID, verify context preserved.examples/infinite_sessions.clj— Demonstrates infinite sessions with context compaction thresholds for long conversations.examples/lifecycle_hooks.clj— Demonstrates all 6 lifecycle hooks: session start/end, pre/post tool use, user prompt submitted, error occurred.examples/reasoning_effort.clj— Demonstrates the:reasoning-effortsession config option.
0.1.28.0 - 2026-02-27
- BREAKING:
:on-permission-requestis now required when callingcreate-session,resume-session,<create-session, and<resume-session. Calls without a handler throwExceptionInfowith a descriptive message. This matches upstream Node.js SDK whereonPermissionRequestis required inSessionConfigandResumeSessionConfig(upstream PR #554). create-sessionand<create-sessionno longer accept a 0-arity (no config) form — a config map with:on-permission-requestmust always be provided.resume-sessionand<resume-sessionno longer accept a 2-arity (no config) form — a config map with:on-permission-requestmust always be provided.- All examples, tests, and documentation updated to always pass
:on-permission-request.
:custom-toolpermission kind —::permission-kindspec now includes:custom-tool, matching the upstreamPermissionRequest.kindunion type. Permission handlers will receive{:permission-kind :custom-tool ...}for SDK-registered custom tool invocations (upstream PR #555).
:copilot/session.task_completeevent type added to::event-typespec andevent-typesvar. Previously it was in the spec but missing from the publicevent-typesset (upstream PR #544).:copilot/assistant.streaming_deltanew event type: emitted when the total response size changes during streaming. Data:{:total-response-size-bytes N}. Added to::event-typespec,event-typesvar, andassistant-eventsvar (upstream PR #544).:copilot/session.mode_changedevent type: emitted when the session agent mode changes. Data:{:previous-mode "...", :new-mode "..."}. Added to::event-typespec,event-typesvar, andsession-eventsvar.:copilot/session.plan_changedevent type: emitted when the session plan changes. Data:{:operation "create"|"update"|"delete"}. Added to::event-typespec,event-typesvar, andsession-eventsvar.:copilot/session.workspace_file_changedevent type: emitted when a workspace file is created or updated. Data:{:path "...", :operation "create"|"update"}. Added to::event-typespec,event-typesvar, andsession-eventsvar.- Data specs for new events:
::session.mode_changed-data,::session.plan_changed-data,::session.workspace_file_changed-data,::session.task_complete-data,::assistant.streaming_delta-data.
::assistant.message_delta-dataspec: removed::total-response-size-bytesfrom optional keys. The response size is now delivered via the separateassistant.streaming_deltaevent (upstream PR #544).
- Microsoft Foundry Local BYOK provider guide in
doc/auth/byok.md: quick start example, installation instructions, and connection troubleshooting (upstream PR #461). doc/reference/API.md: added:copilot/session.task_completeto the Event Reference table (from upstream PR #544 sync).doc/reference/API.md: added permission kind reference table (:shell,:write,:mcp,:read,:url,:custom-tool) in the Permission Handling section.
- Windows console window hiding: CLI process is spawned with explicit PIPE redirects ensuring the JVM sets
CREATE_NO_WINDOWon Windows — no console window appears in GUI applications. Equivalent to upstreamwindowsHide: true(upstream PR #329).
- Recommended default model for non-streaming examples is
claude-haiku-4.5instead ofgpt-5.2for faster response times
0.1.26.0-SNAPSHOT - 2026-02-20
:client-nameoption forcreate-sessionandresume-session— identifies the application using the SDK, included in the User-Agent header for API requests. Forwarded asclientNameon the wire (upstream PR #510).
- BREAKING: Deny all permissions by default —
requestPermissionis now alwaystrueon the wire, and permission requests are denied when no:on-permission-requesthandler is configured. Previously, omitting the handler meant the CLI never asked for permission. To restore the old behavior, pass:on-permission-request copilot/approve-allin your session config.
approve-all— convenience permission handler that approves all requests (copilot/approve-all). Equivalent to the upstream Node.js SDKapproveAllexport. Use as:on-permission-request copilot/approve-allin session config.- Integration tests for deny-by-default permission model: wire format assertions,
approve-allbehavior, handler dispatch with/without handler, custom selective handler
- MCP local server example now passes
:on-permission-request copilot/approve-all(required for MCP tool execution under deny-by-default)
- Permission denial result
:kindnow consistently uses keywords (not strings) in default handler responses, matching specs andapprove-allbehavior
0.1.25.1 - 2026-02-18
- Release pipeline: GPG signing now fails fast with a clear error when no key is available, instead of silently producing unsigned artifacts that Maven Central rejects
- Release pipeline:
stamp-changelogno longer throws when[Unreleased]is empty — prints a warning and exits cleanly
- Metadata API example: suppressed SDK INFO log noise, improved session display (short IDs, summaries, timestamps), clearer messaging for unsupported CLI methods
0.1.25.0 - 2026-02-18
- Core.async native async architecture — eliminates all blocking operations from the async API path:
<create-session/<resume-session— async session lifecycle functions that return channels deliveringCopilotSession, safe for use insidegoblocks- Protocol layer now uses core.async channels instead of Java promises for RPC responses
- Session send-lock replaced
java.util.concurrent.Semaphorewith a channel-based lock <send-async*— fully non-blocking send pipeline using parking channel operations- The idiomatic pattern is now
(go (let [s (<! (<create-session client opts))] (<! (<send! s {:prompt "..."}))))— no thread pool starvation
- Wire parity: always send
requestPermission,requestUserInput, andhooksfields (asfalsewhen not configured) to match upstream Node.js SDK — fixes 400 errors when creating sessions without specifying a model - MCP server environment variables now passed correctly as literal values to subprocesses — sends
envValueMode: "direct"on session create/resume wire payloads (upstream PR #484) - Fix potential semaphore deadlock in
send-and-wait!andsend-async*—tapon a closed mult could leave the send-lock permanently held; movedtapinside thetry/finallyblock that releases the lock - Multi-agent example parallelism: sessions and sends now run concurrently in
goblocks instead of sequentially blocking
- CLI stderr is now captured and forwarded to debug logging; included in error messages on startup failure for better diagnostics (inspired by upstream PR #492)
verify-protocol-version!now races the initial ping against process exit to detect early CLI failures instead of blocking for 60 seconds on timeoutlist-sessionsnow accepts optional filter map{:cwd :git-root :repository :branch}to narrow results by session context (upstream PR #427)- Session metadata from
list-sessionsnow includes:contextmap with working directory info ({:cwd :git-root :repository :branch}) when available (upstream PR #427) list-tools— list available tools with metadata; accepts optional model param for model-specific overrides (upstream PR #464)get-quota— get account quota information (entitlements, usage, overage) (upstream PR #464)get-current-model— get the current model for a session (session-scoped) (upstream PR #464)switch-model!— switch the model for a session (session-scoped) (upstream PR #464)- New event types:
session.context_changed,session.title_changed,session.warning(upstream PRs #396, #427) line-rangeoptional field on file/directory attachment specs (upstream session-events schema update)agent-modeoptional field onuser.messageevent data — one of:interactive,:plan,:autopilot,:shell(upstream session-events schema update)
- BREAKING: Namespace prefix renamed from
krukow.copilot-sdktogithub.copilot-sdk. All requires must be updated (e.g.,github.copilot-sdk.client,github.copilot-sdk.helpers). - Repository moved to
copilot-community-sdk/copilot-sdk-clojureon GitHub. Maven artifact unchanged:io.github.copilot-community-sdk/copilot-sdk-clojure. - Git dependency URL in README fixed to point to new org
- Selection attachment type support (
:selectionwith:file-path,:display-name,:selection-range,:text) - Session lifecycle event subscription via
on-lifecycle-event(:session.created,:session.deleted,:session.updated,:session.foreground,:session.background) - Enhanced model info with full capabilities (
:model-capabilities), billing (:model-billing), and policy (:model-policy) structures session.shutdownandskill.invokedevent types"xhigh"reasoning effort level
- GitHub Actions CI workflow: runs
bb ci(unit/integration tests, doc validation, jar build) on PRs andmainpushes - Daily documentation updater agentic workflow: automatically scans for merged PRs and updates docs
.github/instructions/documentation.instructions.md: guidelines for AI agents updating documentation- GitHub Actions Release workflow: manual dispatch with version management inputs (
sync-upstream,bump-clj-patch,set-version), GPG signing, Maven Central deploy, and SLSA build provenance attestation bb citask: runs tests, doc validation, and jar build (no copilot CLI required)bb ci:fulltask: full pipeline including E2E tests and examples (requires copilot CLI)- Cross-platform
build.clj:md5-hashandsha1-hashhelpers with macOS/Linux fallback - Idempotent
update-readme-sha: succeeds when README already has current SHA stamp-changelogbuild task: automatically moves[Unreleased]entries to a versioned section with today's date and updates comparison links; integrated into the release workflow
- Release workflow now creates a PR with auto-merge instead of pushing directly to
main, compatible with branch protection rules requiring PRs and status checks - Release workflow creates a
vX.Y.Z.Ntag after successful deploy
doc/index.md— Documentation hub / table of contentsdoc/style.md— Documentation authoring style guidedoc/reference/API.md— API reference (moved fromdoc/API.md)PUBLISHING.md— Maven Central publishing guidescript/validate_docs.clj— Documentation validation script (bb validate-docs).github/skills/update-docs/SKILL.md— Update-docs skill for regenerating docs after source changes
- BREAKING: Version scheme changed to 4-segment format
UPSTREAM.CLJ_PATCH(e.g.,0.1.22.0) to track upstream copilot-sdk releases. See PUBLISHING.md for details. - New build tasks:
sync-version(align to upstream),bump-version(increment clj-patch) - Replaced
cheshire/cheshire(Clojars) withorg.clojure/data.json(Maven Central) for JSON processing — eliminates Clojars and Jackson transitive dependencies - Deprecated Clojars publishing (
net.clojars.krukow/copilot-sdk). Use Maven Central (io.github.copilot-community-sdk/copilot-sdk-clojure) going forward.
- Java API (
java_api.clj), Java examples, and AOT compilation. For Java/JVM usage, see copilot-sdk-java. doc/intro.mdanddoc/java-async-api.md(replaced by reorganized documentation)
- Resume session config parity with create-session (upstream PR #376):
resume-sessionnow accepts:model,:system-message,:available-tools,:excluded-tools,:config-dir, and:infinite-sessionsoptions
- API parity with official Node.js SDK (
@github/copilot-sdk)::working-directoryoption forcreate-sessionandresume-session:disable-resume?option forresume-sessionget-foreground-session-idandset-foreground-session-id!client methods (TUI+server mode):large-outputmarked as experimental (CLI protocol feature, not in official SDK)
- New metadata APIs (upstream PR #77):
get-status- Get CLI version and protocol informationget-auth-status- Get current authentication statuslist-models- List available models with metadata
- New event type
:copilot/tool.execution_progressfor progress updates during long-running tool executions - Infinite sessions support (upstream PR #76):
:infinite-sessionsconfig option forcreate-session- Automatic context compaction when approaching context window limits
- New event types:
:copilot/session.compaction_start,:copilot/session.compaction_complete
- Session workspace path accessors for Clojure and Java APIs
- New event type
:copilot/session.snapshot_rewindfor session state rollback (upstream PR #208) - Exported event type constants:
event-types- All valid event typessession-events- Session lifecycle and state eventsassistant-events- Assistant response eventstool-events- Tool execution events
- New example:
session_events.clj- demonstrates monitoring session state events - Authentication options for client (upstream PR #237):
:github-token- GitHub token for authentication (setsCOPILOT_SDK_AUTH_TOKENenv var):use-logged-in-user?- Whether to use logged-in user auth (default: true, false when token provided)
- Hooks and user input handlers (upstream PR #269):
:on-user-input-request- Handler forask_usertool invocations:hooks- Lifecycle hooks map with callbacks::on-pre-tool-use- Called before tool execution:on-post-tool-use- Called after tool execution:on-user-prompt-submitted- Called when user sends a prompt:on-session-start- Called when session starts:on-session-end- Called when session ends:on-error-occurred- Called on errors
- Reasoning effort support (upstream PR #302):
:reasoning-effortsession config option ("low", "medium", "high", "xhigh")- Model info now includes
:supports-reasoning-effort,:supported-reasoning-efforts,:default-reasoning-effort
- Documentation:
doc/getting-started.md— Comprehensive tutorialdoc/auth/index.md— Authentication guide (all methods, priority order)doc/auth/byok.md— BYOK (Bring Your Own Key) guide with examples for OpenAI, Azure, Anthropic, Ollamadoc/mcp/overview.md— MCP server configuration guidedoc/mcp/debugging.md— MCP debugging and troubleshooting guide
- New examples:
examples/byok_provider.clj— BYOK provider configurationexamples/mcp_local_server.clj— MCP local server integration
- BYOK validation:
create-sessionandresume-sessionnow throw when:provideris specified without:model
- BREAKING: Event types are now namespaced keywords (e.g.,
:copilot/session.idleinstead of:session.idle)- Migration: Add
copilot/prefix to all event type keywords in your code
- Migration: Add
- FIX: MCP server config wire format now correctly strips
:mcp-prefix before sending to CLI. Previously:mcp-command,:mcp-args,:mcp-tools, etc. were sent asmcpCommand,mcpArgs,mcpToolson the wire; they are now correctly sent ascommand,args,toolsto match the upstream Node.js SDK. The Clojure API keys (:mcp-command,:mcp-args, etc.) are unchanged. - Protocol version bumped from 1 to 2 (requires CLI 0.0.389+)
- Removed
helpers/query-seqin favor ofhelpers/query-seq!andhelpers/query-chan list-modelsnow caches results per client connection to prevent 429 rate limiting under concurrency (upstream PR #300)- Cache is cleared on
stop!andforce-stop!
- Cache is cleared on
0.1.0 - 2026-01-18
- Initial release of copilot-sdk-clojure
- Full port of JavaScript Copilot SDK to idiomatic Clojure
- JSON-RPC protocol layer with Content-Length framing
- CopilotClient for managing CLI server lifecycle
- stdio and TCP transport support
- Auto-start and auto-restart capabilities
- CopilotSession for conversation management
send!,send-and-wait!,send-asyncmessage methods- Event handling via core.async mult channels
- Tool registration and invocation
- Permission request handling
- Tool definition helpers with result builders
- System message configuration (append/replace modes)
- MCP server configuration support
- Custom agent configuration support
- Provider configuration (BYOK - Bring Your Own Key)
- Streaming support for assistant messages
- Comprehensive clojure.spec definitions
- Example applications:
- Basic Q&A conversation
- Custom tool integration
- Multi-agent orchestration with core.async
- org.clojure/clojure 1.12.4
- org.clojure/core.async 1.6.681
- org.clojure/spec.alpha 0.5.238
- cheshire/cheshire 5.13.0