Files
msd-core/sdk
Tom Boucher ffeeb92c14 fix(#2997): mask SECRET_CONFIG_KEYS in SDK config-set/get and init responses (#2999)
* fix(#2997): mask SECRET_CONFIG_KEYS in SDK config-set/get and init responses

The CJS→TS port at sdk/src/query/config-mutation.ts:240,243 and
config-query.ts:122,128,132 dropped the masking layer that secrets.cjs
spec defines for brave_search/firecrawl/exa_search. Result: the SDK
echoed plaintext API keys into machine-readable JSON output (stdout,
transcripts, CI logs).

Adjacent leak in init.ts:673-675 / init.cjs:728-730: the init bundle
passed config.brave_search through raw, leaking the API key whenever
the user had stored one.

Fix:
- New sdk/src/query/secrets.ts ports SECRET_CONFIG_KEYS, isSecretKey,
  maskSecret, maskIfSecret. Exact CJS parity (verified by 17 tests
  in secrets.test.ts that import secrets.cjs and compare).
- config-set masks value + previousValue in response; on-disk plaintext
  intact (key stays usable).
- config-get masks read response. --default flows through unmasked
  (user's own input, not stored secret).
- init.ts/init.cjs mask string values only; booleans (availability
  flags) pass through unchanged so the typed contract is preserved.

Tests: 17 in secrets.test.ts (including CJS parity), 5 in
config-mutation.test.ts (#2997 block — covers on-disk-preserved,
previousValue masking, short-value, unset, non-secret pass-through),
4 in config-query.test.ts.

Closes #2997

* chore(#2997): add changeset fragment for PR #2999

* chore(#2997): add changeset fragment for PR #2999

* chore(#2999): drop direct CHANGELOG.md edit; release entry now lives in .changeset/

The changeset-fragment workflow (#2975) renders fragments into
CHANGELOG.md at release time. Direct edits to [Unreleased] on
each PR caused merge conflicts on every concurrent PR. This commit
restores CHANGELOG.md to match origin/main; the release entry for
this fix is preserved in the .changeset/*.md fragment(s) on this
branch, which the release workflow consolidates.
2026-05-02 00:17:45 -04:00
..

@gsd-build/sdk

TypeScript SDK for Get Shit Done: deterministic query/mutation handlers, plan execution, and event-stream telemetry so agents focus on judgment, not shell plumbing.

Install

npm install @gsd-build/sdk

Quickstart — programmatic

import { GSD, createRegistry } from '@gsd-build/sdk';

const gsd = new GSD({ projectDir: process.cwd(), sessionId: 'my-run' });
const tools = gsd.createTools();

const registry = createRegistry(gsd.eventStream, 'my-run');
const { data } = await registry.dispatch('state.json', [], process.cwd());

Quickstart — CLI

From a project that depends on this package, invoke the CLI with Node (recommended in CI and local dev):

node ./node_modules/@gsd-build/sdk/dist/cli.js query state.json
node ./node_modules/@gsd-build/sdk/dist/cli.js query roadmap.analyze

If no native handler is registered for a command, the CLI can transparently shell out to get-shit-done/bin/gsd-tools.cjs (see stderr warning), unless GSD_QUERY_FALLBACK=off.

What ships

Area Entry
Query registry createRegistry() in src/query/index.ts — same handlers as gsd-sdk query
Tools bridge GSDTools — native dispatch with optional CJS subprocess fallback
Orchestrators PhaseRunner, InitRunner, GSD
CLI gsd-sdk — query, run, init, auto

Guides

  • Handler registry & contracts: src/query/QUERY-HANDLERS.md
  • Repository docs (when present): docs/ARCHITECTURE.md, docs/CLI-TOOLS.md at repo root

Environment

Variable Purpose
GSD_QUERY_FALLBACK off / never disables CLI fallback to gsd-tools.cjs for unknown commands
GSD_AGENTS_DIR Override directory scanned for installed GSD agents (~/.claude/agents by default)