Architecture Overview¶
Sidekick Docker is a monorepo with three packages that share a common Docker API layer.
Package Structure¶
graph TD
CLI["sidekick-docker-cli<br/>(TUI Dashboard)"]
VSC["sidekick-docker-vscode<br/>(VS Code Extension)"]
SHR["sidekick-docker-shared<br/>(Docker API Layer)"]
DOC["Docker Daemon"]
CLI --> SHR
VSC --> SHR
SHR --> DOC
| Package | Build Tool | Output | Module Format |
|---|---|---|---|
sidekick-docker-shared |
tsc | dist/ |
CommonJS + declarations (Docker API, state store, stream policy, log analytics) |
sidekick-docker-cli |
esbuild | dist/sidekick-docker.mjs |
ESM (single file) |
sidekick-docker-vscode |
esbuild | out/extension.js + out/webview/dashboard.js |
CJS (extension) + IIFE (webview) |
Data Flow¶
flowchart LR
DE["Docker Events"] --> EW["EventWatcher"]
EW --> ST["DockerStateStore<br/>(shared)"]
ST --> SR["scheduleRender()"]
SR --> UI["Dashboard UI"]
PR["Periodic Refresh<br/>(30s fallback)"] --> ST
CR["Ctrl+R"] --> ST
- Docker events stream from the daemon via
EventWatcher - Events go to the shared
DockerStateStore(wrapped by the TUI'sDockerState; the VS Code extension wraps the same store inDockerServiceandContainerWatcherService). It patches its resource lists immediately where it can, ignores no-op events such as healthcheckexec_*, and otherwise requests a refresh debounced by 500ms - The store reports a change only when something actually changed;
scheduleRender()then re-renders the dashboard (batched at 200ms), and finished log/stats streams of a container that just started resume - A 30-second periodic refresh provides a fallback in case events are missed;
Ctrl+Rrefreshes immediately
A refresh pass makes a single container listing that also feeds volume and network usage (DockerClient.listResources()), reads compose config through a cache that runs docker compose config only when the compose files change, always commits (events that arrive mid-pass are replayed over its result), and is abandoned after 20 seconds, keeping the previous data. See Streaming Architecture for the stream side.
Build System¶
The shared library must be built first — both CLI and VS Code packages depend on it via a local file path (file:../sidekick-docker-shared).
# Full build order
npm run build:shared # tsc
npm run build:cli # esbuild
npm run build:vscode # esbuild
esbuild Plugins (CLI)¶
The CLI build uses custom esbuild plugins to handle Node.js-specific modules:
- SSH: bundles
ssh2; optionalcpu-featuresandsshcrypto.nodeaccelerators use the library’s JavaScript fallback in both consumers. - Stub:
react-devtools-core(optional development tooling) - Externals:
node-pty— an optional native module the npm package does not ship. When it cannot be loaded (the usual case fornpm install -g), Exec hands the terminal todocker exec -itwith the dashboard suspended; with it, the shell runs embedded in an overlay - Defines:
__CLI_VERSION__injected frompackage.json - Banner: the
#!/usr/bin/env nodeshebang (the output is chmodded 0755, so it runs directly) and a line mappingNO_COLORtoFORCE_COLOR=0, because chalk — which colours Ink's output — does not readNO_COLOR
esbuild Output (VS Code)¶
The VS Code extension produces two bundles:
out/extension.js— CJS, runs in the Node.js extension hostout/webview/dashboard.js— IIFE, runs in the browser webview context- Defines:
__VERSION__injected frompackage.json(used for status bar display)
The webview source is modular — dashboard.ts orchestrates rendering, with keyboard handling (keyboard.ts), overlays (overlays.ts), and per-resource renderers (panels/) in separate modules — all bundled into the single IIFE file above.
Dashboard Decomposition¶
The main Dashboard component delegates input handling to extracted modules:
keyRegistry.ts— declarative registry of global keybindings; the single source of truth that drives dispatch, the help overlay, and status-bar hintsuseKeyboardHandler— keyboard input router with a fixed dispatch order: exec passthrough → Ctrl+C → active overlay handler → global bindings from the key registry → per-panel action shortcutsuseMouseHandler— mouse click, scroll, and right-click handling, including clickable overlaysDashboard.tsx— state management (useReducer) and render orchestration