DevStackMenu is a native macOS menu bar application built with AppKit and packaged with Swift Package Manager.
The repository is intentionally small and split into three main targets:
DevStackCore: application logic, AppKit windows, profile persistence and shell integrationDevStackMenu: executable entry point that boots the menu bar appDevStackSmokeTests: lightweight verification target for parser and normalization checks
The app is self-contained at the orchestration layer:
- it stores profiles in its own Application Support directory
- it stores reusable runtime target definitions in its own Application Support directory
- it stores managed shared env variables in its own Application Support directory
- it keeps managed bind-mount data next to the source compose project under
data/<service> - it switches Docker contexts directly through the Docker CLI
- it writes and manages launchd plists for SSH tunnels itself
- it runs
docker composedirectly for local container lifecycle - it prevents duplicate app launches with a process lock in Application Support
- it keeps a lightweight file-watch loop over profile storage, compose project roots and supported IDE state files
- it can prepare remote Docker hosts by checking SSH access, bootstrapping Docker and creating a managed Docker context
- it plans compose operations through
docker compose config --format json, with a fallback parser only for degraded import scenarios - it syncs project-relative bind mounts to remote servers before compose startup and rejects host paths outside the project tree
- it removes imported profiles if their tracked source compose file disappears
- it resolves compose env input from managed variables, project env files and Keychain-backed secrets
- it can prompt for profile activation when PyCharm or VS Code already has a matching project open
- it writes text reports for compose previews, logs, volumes, metrics and remote file listings, then opens them in the standard macOS viewer
There is no external helper CLI dependency in the runtime path anymore.
Phase 1 keeps one core target, but the code is now split by responsibility inside DevStackCore.
Models/: profile, runtime, compose, environment, and snapshot model typesValidation/: validation errors and normalization helpers
Shell/: command execution, tool path resolution, shell result typesStorage/:ProfileStoreand filesystem path contracts
ComposePlan.swift: compose planning and environment model typesComposePlanBuilder.swift: normalized compose planning throughdocker compose config --format jsonComposeEnvironmentService.swift:.env, managed variable, and missing-env resolutionComposeFileGenerationService.swift: generated compose YAML emissionComposePreviewFormatter.swift: plan/report formattingComposeSecretSupport.swift: Keychain-backed secret integration
Sources/DevStackCore/ComposeSupport.swift now exists only as a thin facade over those services.
RuntimeStatusService.swift: docker context discovery, status snapshots, stale profile cleanupRuntimeLifecycleService.swift: orchestration facade for profile and compose action flowsRuntimeComposeFlowService.swift: profile compose up/down/restart wiring and context switchingRuntimeServerPreparationService.swift: local/remote server checks, bootstrap and context preparationRuntimeProfileHooksService.swift: hook execution and shell exports helpersTunnelService.swift: launchd tunnel setup and teardownRemoteSyncService.swift: managed bind-mount rewrite and remote project syncRuntimeDiagnosticsService.swift: compose and remote diagnosticsRuntimeDeletionService.swift: deletion plans and cleanupRuntimeReportService.swift: logs, volumes, metrics, and remote file reports
Sources/DevStackCore/RuntimeController.swift is now a thin compatibility facade.
- menu assembly is split into status, profile, runtimes, and variables builders
- runtime, profile, and report-related menu actions are grouped by workflow
AppDelegate is reduced to app lifecycle wiring, status item ownership, menu coordination, and shared UI helpers.
Owns snapshot collection, watcher refreshes, and IDE activation prompts.
Owns editor/import window coordination and profile persistence callbacks.
ProfileEditor.swift: profile editor shell and shared window helpersProfileEditor/: profile editor layout, runtime/compose source flows, environment tooling, and service dialogServerWizard.swift: runtime creation UI flowServerWizard/ServerWizardService.swift: server validation, preparation orchestration, and persistence hooksComposeImport.swift: compose import flowVariableManager.swift: shared env variable managerVariableManager/VariableManagerDataService.swift: import/suggested profile support for variable syncVariableManager/VariableManagerDialogs.swift: add/edit/import modal dialogsSecretManager.swift: profile secret managerSecretManager/SecretManagerDataService.swift: secret overview/load/save/delete service methodsSecretManager/SecretManagerDialogs.swift: secret save value dialog
Sources/DevStackCore/DXCLI.swift: CLI parsing and workflow servicesSources/dx/main.swift: CLI command parsing and orchestration entrypointSources/dx/DXWorkflowHandlers.swift: command handlers and helper flow fordxSources/dx/DXTerminal.swift: terminal I/O helpers for interactive commandsSources/dx/AppLauncher.swift: macOS app bridgeSources/DevStackMenu/main.swift: thin app entry pointSources/DevStackSmokeTests/main.swift: thin smoke runnerSources/DevStackSmokeTests/SmokeChecks.swift: smoke verification logic kept out of shipping core
Sources/DevStackCore/Common.swift: thin compatibility/helper file with shared parsing helpersSources/DevStackCore/SingleInstanceCoordinator.swift: single-instance process lockSources/DevStackCore/ProjectContext.swift: Git and IDE state integrationSources/DevStackCore/ProfileImportService.swift: compose import to draft-profile wiringSources/DevStackCore/Context/ContextValueGenerator.swift: value generators and env helperSources/DevStackCore/Context/ClipboardSmartParser.swift: clipboard content parser for quick env heuristics
Profiles are stored outside the repository in the user's home directory:
~/Library/Application Support/DevStackMenu/profiles/*.json~/Library/Application Support/DevStackMenu/runtimes/*.json~/Library/Application Support/DevStackMenu/managed-vars.json~/Library/Application Support/DevStackMenu/current-profile~/Library/Application Support/DevStackMenu/active-profiles.json~/Library/Application Support/DevStackMenu/app.lock~/Library/Application Support/DevStackMenu/generated/...<compose-project>/<relative-bind-path>
The app does not maintain its own database.
Env resolution order for compose runs is:
- managed variables from the global variable manager
- project env files such as
.env,.env.local,.env.devstack - generated Keychain-backed secret env file for still-missing
${VAR}references
The package build creates the executable. App bundle assembly is handled separately in Scripts/build-app.sh, which:
- builds the
DevStackMenubinary in release mode - copies
Resources/Info.plist - assembles
DevStackMenu.appindist/ - compiles the AppleScript helper app used for compose-file opening integration with its own bundle identifier
Release distribution is produced through Scripts/package-release.sh and uses an unsigned .pkg artifact containing:
DevStackMenu.appin/ApplicationsImport Compose To DX.appin/Applicationsdxbinary in/usr/local/bin
- macOS-only by design
- minimal external dependencies
- local-first workflows over cloud integration
- developer ergonomics matter more than visual complexity
- canonical compose planning depends on
docker compose config; the fallback parser exists only for degraded import scenarios - remote host bootstrap is currently optimized for apt-based Linux dev hosts
- the profile editor is split by workflow, but still remains an AppKit-heavy surface without dedicated UI tests
- smoke checks validate critical logic, but there is no full UI automation