Skip to content

Introduce packages/codev-sdk: client SDK for Tower (server/client dependency isolation) #1189

Description

@amrmelsayed

Goal

Introduce packages/codev-sdk (@cluesmith/codev-sdk): the single client implementation of "how anything talks to Tower". Restructure the shared-package taxonomy so server and client dependencies are isolated at the package level:

  • codev-types: wire contracts. The only package imported by both sides. Unchanged.
  • codev-core: server-side implementation only (local-key auth issuance, homedir-derived path constants, and over time Tower internals).
  • codev-sdk (new): Tower API client, WS/message-bus client, and the client-side pure helpers. Consumed by the web dashboard, the VS Code extension, the CLI's Tower-facing commands, and the future mobile app.

Invariant: codev-core and codev-sdk never import each other; both import codev-types.

Motivation

codev-core is currently consumed from both server (Tower, CLI) and client (dashboard browser bundle, VS Code extension host) contexts. The boundary between its Node-only modules and its environment-agnostic ones is enforced only by convention (subpath exports plus reviewer vigilance). Two concrete problems observed:

  1. constants.ts imports node:path/node:os, so a pure value like DEFAULT_TOWER_PORT is unreachable from any bundler that cannot resolve Node builtins (Metro for the planned mobile app fails loudly on it).
  2. Nothing structural prevents a server-side need from adding a runtime dependency that every client then inherits.

Package-level separation makes the package manager enforce the boundary instead of review discipline. The mobile workstream (issue #1147, research in codev/research/mobile/) makes a third client environment (React Native / Metro) concrete, but the split stands on its own for the two existing clients.

Import census (verified 2026-07-16)

Who imports each codev-core leaf today:

Leafcodev (CLI/server)dashboardvscodeDisposition
tower-clientCLI commands-yessdk (auth/transport injected)
auth(via tower-client)-yesissuance stays core; sdk takes injected getToken
workspaceyes-yessdk (URL grammar is contract-adjacent)
constantsyes-yessplit: pure values to sdk, homedir paths stay core
escape-buffer-yesyessdk
reconnect-policyTower (tunnel-client, tower-websocket)yesyessdk owns it; core keeps a private copy (see exception)
agent-namesyes-yessdk
architect-nameyes-yessdk
builder-helpers-yesyessdk
area-grouping--yessdk
phase-grouping--yessdk
review-markers--yessdk

Note on packages/codev: the server/client line runs through this package, not around it. It hosts Tower (server) and also the afx/porch/consult CLI commands, which are Tower API clients. The CLI's Tower-facing slice consumes the sdk like every other client; the rest of the CLI (worktree surgery, porch state machine, scaffolding) stays where it is.

The one exception: reconnect-policy

Genuinely dual-use: Tower itself uses it in tunnel-client.ts (Tower acting as a WS client of the cloud) and tower-websocket.ts. Resolution: the sdk owns the module; codev-core keeps a private copy of the backoff math (~40 lines of pure code) for the tunnel. Accepted duplication, recorded here deliberately; the alternatives (core importing the client sdk, or algorithm code in codev-types) each break a rule worth more than 40 lines.

SDK constraints (the guardrails)

Its consumers span browser (dashboard), React Native / Metro (mobile), and Node (VS Code extension host, CLI). Therefore:

  • Zero runtime dependencies. dependencies: {} is a reviewable contract.
  • Environment-agnostic: no DOM, no node:*, no fetch assumptions. Transport, storage, and auth arrive as injected adapters (the VS Code extension injects a local-key reader; the browser injects its stored key; mobile injects secure-store).
  • CI-enforced boundary: an import-boundary test in the style of packages/artifact-canvas/src/__tests__/import-boundary.test.ts, failing the suite if any shipped module imports Node builtins, vscode, or uses fetch directly.
  • Framework-free: no React in v1. The extension host and CLI cannot use hooks. An optional /react subpath entry (React as optional peer) can be added later if web and mobile demonstrably duplicate hook logic; that addition requires its own proposal.

Explicitly deferred: apps/cli

Considered and rejected for now: moving the CLI to apps/cli on top of the sdk. The CLI is not a Tower client; it is local runtime sharing a machine and filesystem with Tower (launches the daemon, performs git worktree operations, runs porch over local state, scaffolds from the bundled skeleton). It would still need codev-core and most of packages/codev, and npm install -g @cluesmith/codev deliberately ships CLI and Tower as one artifact. Revisit only if Tower ships as a standalone daemon/service with its own release cadence, or a genuinely thin remote-only CLI is wanted. (Same defer-until-trigger pattern as #1029.)

Sequencing and operational touchpoints

  • Land after Monorepo layout: introduce apps/ for end-user surfaces #855 merges: Monorepo layout: introduce apps/ for end-user surfaces #855 relocates packages/dashboard to apps/web, and this refactor touches the same import lines; doing them serially avoids double churn.
  • scripts/local-install.sh packs codev-core and codev into one global install; codev-sdk must join the pack set or global installs break on the unresolvable workspace dep.
  • Publish with pnpm publish (workspace:* resolution).
  • Release protocol version-bump set grows by one package.
  • Mobile is not blocked on this: spike work talks raw fetch/WS to Tower; the PoC implementation builds on the sdk.

Origin

Mobile workstream architecture discussion (2026-07-16), evolving the retired packages/tower-sdk concept from codev/research/mobile/interaction-model.md section 7.2 into a dependency-isolation split with existing consumers. A docs amendment to the mobile research (replacing the tower-sdk section with this design) follows separately.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

area/coreArea: shared core library / forge abstraction (packages/core, packages/codev/src/lib)

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions