Skip to content

Extract PreviewsEngine library target from PreviewsCLI monolith#121

Merged
obj-p merged 2 commits intocli-mcp-parityfrom
extract-previews-engine
Apr 16, 2026
Merged

Extract PreviewsEngine library target from PreviewsCLI monolith#121
obj-p merged 2 commits intocli-mcp-parityfrom
extract-previews-engine

Conversation

@obj-p
Copy link
Copy Markdown
Owner

@obj-p obj-p commented Apr 16, 2026

Summary

PR 1 of the package rearchitecture (plan at .claude/plans/package-rearchitecture.md). Creates a new PreviewsEngine library target containing business logic that has no MCP or ArgumentParser dependency.

What moved to PreviewsEngine

  • IOSStateIOSSessionManager (public actor)
  • ConfigCache (public actor)
  • traitsSummary, formatPreviewList (public functions)
  • cleanupStaleTempDirs (public function)
  • BuildHelpers.swift (entire file: StderrProgressReporter, loadProjectConfig, detectAndBuild, resolveDeviceUDID, buildSetupFromConfig)

What stays in PreviewsCLI

  • MCPServer.swift (handler functions, MCP wiring, param extraction — all depend on MCP types)
  • All CLI commands, DaemonClient, daemon infrastructure

Dependency graph

PreviewsEngine → PreviewsCore, PreviewsMacOS, PreviewsIOS  (NO MCP, NO ArgumentParser)
PreviewsCLI → PreviewsEngine, MCP, ArgumentParser

Injection

  • configureMCPServer(host:iosManager:configCache:sharedCompiler:) — all engine instances injected
  • DaemonListener.start creates ONE shared IOSSessionManager + ConfigCache for all connections
  • ServeCommand.runStdio creates its own instances (single-connection)

Test plan

  • swift build — clean
  • Manual smoke: simulators, list --json, status all work through the daemon
  • Full test suite running in background (~5m)

🤖 Generated with Claude Code

obj-p and others added 2 commits April 16, 2026 05:10
Creates a new `PreviewsEngine` library containing the business logic
that has no MCP or ArgumentParser dependency:

Moved from MCPServer.swift:
- IOSState → IOSSessionManager (public actor)
- ConfigCache (public actor)
- traitsSummary, formatPreviewList (public functions)
- cleanupStaleTempDirs (public function)

Moved from BuildHelpers.swift (entire file):
- StderrProgressReporter, loadProjectConfig, buildSetupFromConfig,
  detectAndBuild, resolveDeviceUDID

PreviewsEngine depends on PreviewsCore, PreviewsMacOS, PreviewsIOS.
It does NOT depend on MCP or ArgumentParser — it can be consumed
independently for embedding preview capabilities in any Swift app.

Injection changes:
- configureMCPServer now takes (host:iosManager:configCache:
  sharedCompiler:) — all engine instances are injected rather than
  created internally.
- DaemonListener.start creates ONE shared IOSSessionManager and
  ConfigCache for all connections (preserves session persistence
  across CLI invocations).
- ServeCommand.runStdio creates its own instances (single-connection
  mode, no sharing needed).
- MCPServer.swift stores the injected instances in
  nonisolated(unsafe) file-private vars (set-once-before-use
  pattern, Swift 6 requires the annotation).

MCPServer.swift is ~100 lines shorter. Everything that remains in
it depends on MCP types (CallTool.Parameters, Server, Value).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Critical:
- NoSimulatorError now conforms to LocalizedError with
  errorDescription (was CustomStringConvertible, which causes
  localizedDescription to return the generic "operation could not
  be completed" per AGENTS.md convention).

Important:
- Removed PreviewsMacOS from PreviewsEngine's Package.swift
  dependencies — no engine file imports it. Engine stays
  platform-agnostic.
- Deleted orphaned doc comment in MCPServer.swift (leftover from
  cleanupStaleTempDirs extraction).
- Updated DaemonListener doc comment: IOSState → IOSSessionManager,
  module-level → shared instances.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@obj-p obj-p merged commit 14dec0d into cli-mcp-parity Apr 16, 2026
@obj-p obj-p deleted the extract-previews-engine branch April 16, 2026 10:36
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant