Skip to content

chore: consolidate duplicated runtime dependencies into the root package.json #2195

Description

@cliffhall

Sub-issue of #2030 — step 1 of two.

Consolidate the runtime dependencies that are declared identically in the root package.json and in one or more clients/*/package.json. A package can only be installed into an install root that declares it, so deleting the redundant client-side declarations does not merely align the copies — it makes a second copy impossible to create, which is the failure class #1896 was opened for and #1965 / #2029 built a guard to detect.

Scope

Move to the root manifest and delete the client-side declarations (they resolve from the root install by walk-up):

ajv, atomically, chokidar, commander, open, pino, undici, zod, @napi-rs/keyring, hono, @hono/node-server

These are exactly the packages core/ imports at runtime, which AGENTS.md already requires to be root-only — the rule was simply never applied beyond the SDK packages #1970 cleaned up.

Leave where they are — neither may become a root dependency:

  • ink-form, ink-scroll-view — deliberately inlined into the TUI bundle (TUI Error when pressing Enter to call a tool #1952). A root dependency would make consumers install unused copies; clients/tui/__tests__/tsupConfig.test.ts enforces this.
  • Web's UI stack (@mantine/*, @dnd-kit/*, @emotion/react, react-dom, react-icons, react-markdown, react-syntax-highlighter, remark-gfm, papaparse) — bundled into dist, so shipping them to consumers is pointless.

Constraints

  • react must stay ^19.0.0 at the root. Narrowing it reopens TUI Error when pressing Enter to call a tool #1952 for the ink renderer itself, which breaks TUI startup, not just its forms. The clients' ^19.2.4 is the declaration that goes away, not the root's open range.
  • A root-declared package that core/ imports at runtime must also be named in each client's bundler external list (clients/cli/tsup.config.ts, clients/tui/tsup.config.ts, clients/web/tsup.runner.config.ts) — tsup externalizes only what the nearest manifest declares, and a root-only package is in none of them. npm run verify:bundle-externals is the guard.
  • Regenerate the lockfiles, and gate with npm run local:gate and npm run pack:verify — this changes what the published tarball resolves against, which the local gate alone does not cover.
  • Re-run npm run verify:dep-lockstep afterward and record the new candidate set in the PR. TOLERATED_SKEW is empty as of chore(scripts): derive dep-lockstep candidates from what enters each tsc program #2029 and should stay empty.
  • Confirm the postinstall cascade (scripts/install-clients.mjs) still behaves when a client manifest declares few or no runtime dependencies.
  • Check whether the dedupe + alias pins in vitest.shared.mts can retire — worth checking, not assumed.

Done when

  • The duplicated runtime deps are declared once, at the root.
  • npm run local:gate and npm run pack:verify both pass.
  • AGENTS.md's dependency-placement section and the root README's matching section describe the consolidated layout, with the .github/copilot-instructions.md mirror updated in the same PR.

Metadata

Metadata

Assignees

Labels

choreMaintenance: deps, build tooling, CI, cleanup — no user-facing behavior changev2Issues and PRs for v2

Type

No type

Projects

No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions