Releases: Luminoid/Monolith
Releases · Luminoid/Monolith
Release list
0.4.0
[0.4.0] - 2026-05-25
Added
--localesflag onnew app: comma-separated locale codes for the generatedLocalizable.xcstringscatalog. First locale is the source language; non-source entries start atstate: "new"so the localization audit surfaces them as outstanding work. Default remains["en"].--categoryflag onnew app: App Store category (e.g.public.app-category.productivity). Defaults topublic.app-category.utilities. Emitted both asLSApplicationCategoryTypein the Info.plist andINFOPLIST_KEY_LSApplicationCategoryTypein build settings, soxcodebuild archivedoesn't emit the non-fatal "No App Category is set" warning that App Store Connect rejects on upload.- 3-variant AppIcon skeleton:
AssetGenerator.generateAppIconContents()emits three entries: no-appearance (light),luminosity: dark, andluminosity: tinted. Adopters drop PNGs in instead of restructuring the asset catalog later. make build-cleantarget in generated Makefiles: runsxcodebuild clean buildto surface warnings that incremental builds hide.- Persistence demo test: when SwiftData is enabled,
TestGenerator.generateAppTestemits one@Testthat exercisesTestContext.makeContainer()+TestDataFactory.makeSampleItem(...)so adopters get a green signal on firstmake testand the helper APIs are referenced. - Compact theme via LumiKit 0.9
UIColor.lmk_dynamic:ColorCodeGeneratoremits one-liner light/dark colors. Generated themes drop ~56% in line count. RequiresDependencyVersion.lumiKit = "0.9.0". InfoPlistGeneratoroptions:urlIdentifier(emitsCFBundleURLNameinCFBundleURLTypes; defaults tobundleID) andapplicationCategoryType(plumbed from--category).- Standard bundle-metadata keys in Info.plist:
CFBundleIdentifier,CFBundleVersion,CFBundleShortVersionString,CFBundleName,CFBundleDisplayName,CFBundleExecutable,CFBundleDevelopmentRegion,CFBundleInfoDictionaryVersion,CFBundlePackageType,LSRequiresIPhoneOS.
Changed
GENERATE_INFOPLIST_FILE: NOin generated XcodeGen YAML when a hand-writtenINFOPLIST_FILEis also declared. Single source of truth instead of opaque merge precedence.LSApplicationCategoryTypelives in both Info.plist and XcodeGen build settings: required byxcodebuild archiveto silence the non-fatal "No App Category" warning that App Store Connect rejects.ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColorset explicitly alongside the existingASSETCATALOG_COMPILER_APPICON_NAME = AppIconso asset wiring is visible in the pbxproj.MacWindowconsolidated toAppConstants:SceneDelegate's Mac Catalyst block callsMacWindowConfig.configure(_:);DesignSystemGeneratorno longer re-emitsenum MacWindow. One canonical home (AppConstants.MacWindow) instead of three copies of the same magic numbers.AppDelegate.modelContainernon-optional +fatalErroron init failure: matches Apple's sample-code pattern; surfaces container-init failures at the load site instead of as misleading "no persistent stores" crashes later. The no-tabs SwiftData scaffold drops the now-deadguard modelContainer != nil.disableTestParallelismgated on(coreData || swiftData) && cloudKit: plain SwiftData (no CloudKit) has no shared-repository singleton race, so it no longer pays the serial-test-execution cost.-quieton everyxcodebuildinvocation in generated Makefiles; per-file compile output stays out of recipes, warnings/errors still surface.ColorDeriversecondary/tertiary use an analogous palette (±30° hue shift) instead of triadic (+150°/+210°). Reads as "variants of the primary" instead of jarring complementaries.- Generated
Localizable.xcstringsis multi-locale: when--localesdeclares more than one, each key emits alocalizationsentry per locale. Source-language entries arestate: "translated"; non-source entries arestate: "new".
Removed
--features snapKitand--features lookin: removed per the v0.3 deprecation. The auto-translating shim is gone; the CLI now raises aValidationErrorlisting the migration (snapKit → --use-packages SnapKit,lookin → --use-packages LookinServer).AppFeature.deprecatedPackageFeatureNamesreplaced byKnownPackages.removedFeatureAliases.monolith add snapKitandmonolith add lookin: removed. Existing projects retrofit via Xcode's native Add Package flow (URLs inKnownPackages.registry).monolith add lottieis unaffected.ColorDeriver.DerivedPalette.photoBrowserBackground: every derived value was identical, making the dynamic-color wrapper pointless. LumiKit 0.9'sLMKThemeships a default; generated themes omit the override.DesignSystem.MacWindow: see Changed; canonical home isAppConstants.MacWindow.DataPublisher.swiftsample singleton from thecombinefeature: no real consumers, no integration coverage.generateAsyncService()(the actual reference template for Task cancellation) stays; thecombinefeature now writes one file.
Tests
- 774 → 794 tests, 70 → 71 suites, zero regressions. New coverage spans
--locales/--categoryflag plumbing, the 3-variant AppIcon skeleton, the SwiftData persistence demo test, and multi-locale xcstrings emission.
0.3.0
[0.3.0] - 2026-05-24
Added
--use-packagesflag onnew appandnew package— built-in registry of well-known third-party packages.--use-packages 'SnapKit,Lottie:5.0.0,LookinServer'wires the dep without URL typing. Optional:versionper identifier overrides the registry default; unknown identifiers raise a config-time error with a "did you mean…?" suggestion. Adding a new well-known package is now a registry entry, not a generator change.--external-packages+--target-depsonnew app— ports the package generator's flags to the app generator so apps can wire arbitrary SPM frameworks (any third-party library) outside the built-in registry. URL form:'Name=url:requirement[:packageName];...'(requirement is verbatim SPM:from: "0.1.0",branch: "main",exact: "1.0.0"). Path form:'Name=path[:packageName]'(no requirement; for local-package development where the adopting project sits alongside the library).--target-deps 'Product1,Product2,...'wires products into the app target. Routing: direct name match → longest-prefix match (PrismCore→Prism) → single-external fallback → explicit:packageNamedisambiguation. Externals override built-ins:--external-packages 'LumiKit=path:../LumiKit'replaces the default GitHub URL with a local path.--executable-targetsonnew package— emits ArgumentParser-wired@mainSwift executables alongside the library targets, withswift run tool1instructions in the generated README. Auto-addsswift-argument-parseras a transitive dep.--test-helper-targetsonnew package— declares test-helper library targets (typically a<Name>Testingsibling consumed by adopter test targets). Generates a Swift Testing stub (import Testing, public expectations namespace) instead of a plain library placeholder; XCTest interop is opt-in (import XCTestlinks it on demand). Rejects@MainActor-named helpers — Swift Testing'sawaitsemantics fight MainActor isolation on shared helpers.- Config-time validation for package wiring —
AppConfig.validate()andPackageConfig.validate()reject unconsumed--external-packages(declared but never referenced from--target-deps), bare-product typos (e.g.--target-deps LumiKitagainst a package whose products areLumiKitCore/LumiKitUI— previously matched by package-name fallback, generated bad XcodeGen YAML, and failed atxcodebuild), and target-name collisions with the app target. - Path-traversal guard in
FileWriter— rejects relative output paths containing..segments that resolve outside the project root.
Changed
snapKitandlookinremoved fromAppFeature— replaced by theKnownPackagesregistry (consumed via--use-packages).--features snapKit,lookinstill works for one minor version via a deprecation shim that auto-translates and emits a stderr warning. Removed entirely in v0.4. Principle:--featuresis for code-shaping integrations (LumiKit's theme +LMKNavigationController+ LMKLogger; Lottie'sLottieHelper.swifttemplate); the registry is for "just wire the dep" cases.- Generated packages are lint-clean and build clean on first run — platform-floor merged across targets, imports sorted,
// TODO:placeholders dropped, internal-lib imports auto-added to source stubs, external deps imported in placeholders, organization-name case preserved,make build/make testpreferred over rawxcodebuildsnippets, Brewfile pins centralized. - App scaffolds are App Store-ready out of the box —
INFOPLIST_KEY_LSApplicationCategoryTypebaked into Debug + Release (silent upload rejection otherwise), automatic code signing enabled, shared Xcode scheme generated,validate-app-icon.shwired into the Makefile whenappIconValidationis on, YAGNI coordinator stubs pruned. - Widget
PrivacyInfo.xcprivacyis now unconditional — every shipped widget bundle gets its own manifest with baseline values (NSPrivacyTracking=false, empty arrays). App Store privacy-report generation concatenates per-bundle manifests; missing files produce "Missing API usage description" feedback at upload. Was previously gated behind theprivacyManifestfeature. MakefileGeneratorgainsdisableTestParallelism— auto-on for any app that selects Core Data / SwiftData. Emits-parallel-testing-enabled NOon the test target to match the documented*.sharedsingleton race seen in Petfolio.- SnapKit wires transitively through LumiKit — when LumiKit is selected, the SnapKit dep is no longer duplicated at the app level (LumiKit re-exports SnapKit's public surface).
swift package resolvebranches by project system — runs forxcodeProj/ SPM packages (where the resolved file is committed); skipped forxcodeGen(XcodeGen owns resolution).strictConcurrencyis a no-op atswift-tools-version: 6.2— dropped from thefullpreset and fromXcodeGenGenerator's emitted settings; strict concurrency is the language default. Flag still accepted for backwards-compat with a stderr warning.
Tests
- 717 → 774 tests, 68 → 70 suites, zero regressions. New coverage spans the
--use-packages/--external-packages/--target-depsflag matrix (registry lookup, version override, unknown identifier, platform conditional emit, deprecation shim, unconsumed externals, bare-product typos, multi-product routing, local-path emit), package sibling targets (executables, test helpers), App Store hygiene (widgetPrivacyInfo,disableTestParallelism),FileWriterpath-traversal guard, transitive SnapKit-via-LumiKit detection, and project-system-branchedswift package resolve.
0.2.0
[0.2.0] - 2026-05-20
Added
LocalizationAuditGenerator— emitsScripts/localization/audit_strings.pywhenever thelocalizationfeature is on (bothnew appandadd localization). Flags missing locales, untranslated state, placeholder-arity mismatches between locales, and the silent-fail Swift\(...)interpolation bug from workspace lessons.mdmake audit-stringsMakefile target — wired automatically whenlocalization+devToolingare both selected.make checkinvokes it alongside SwiftLint and SwiftFormatShellRunnerutility — centralized wrapper aroundProcess()with three entry points (run,runDiscardingOutput,runCapturingStdout). Replaces 14 hand-rolledProcess()setups acrossXcodeGenRunner,PackageResolver,ProjectOpener,ToolChecker,FileWriter.gitInit+gitAuthorNameUISymbolsenum — named constants for ✓ ✗ ⚠ ↻ ─ ↑. Replaces inline"\u{2713}"/ literal"✓"mixSignalHandlerutility — registers a SIGINT handler that removes the partial output directory if the user hits Ctrl-C mid-generation. Wired intonew app,new package,new cli. The wizard's raw-mode0x03path nowraise(SIGINT)s instead ofexit(0)-ing, so the same cleanup runs even when interrupted during the wizardxcodeProjproject system — New default for iOS apps. Generates a committed.xcodeprojby running XcodeGen once then removingproject.yml, giving users a standard Xcode project with no XcodeGen dependency. NewXcodeGenRunnerutility handles the subprocessLookinServerAppFeature — iOS-only UI debugging dependency (v1.2.8). Platform-conditional in both SPM (.when(platforms: [.iOS])) and XcodeGen (platforms: [iOS])--licenseflag on allnewcommands — Supportsmit,apache2,proprietarywith per-type defaults (app=proprietary, package=MIT, CLI=Apache 2.0). NewLicenseTypeenum with full Apache 2.0 and Proprietary license templates- SwiftLint and SwiftFormat Xcode build phase scripts — XcodeGen-generated projects include
preBuildScripts(SwiftFormat) andpostCompileScripts(SwiftLint) with ARM64 Homebrew PATH detection - Next steps in generated output — All three project types print actionable next steps to console after generation. App and package READMEs include a "Next Steps" section
Defaultsconstants enum — CentralizedprimaryColor,deploymentTarget,simulatorOS,simulatorDevice,simulatorDestination,defaultPlatform. Eliminates scattered magic strings across commands and generatorsProjectDetectordetects.xcodeprojbundles — Can now detect committed Xcode projects (not justproject.ymlorPackage.swift)- XcodeGen build settings —
GENERATE_INFOPLIST_FILE,SWIFT_APPROACHABLE_CONCURRENCY,SWIFT_UPCOMING_FEATURE_MEMBER_IMPORT_VISIBILITY,MARKETING_VERSION,CURRENT_PROJECT_VERSION DerivedData/added to generated.gitignore
Changed
- Generators refactored to multiline string literals — Converted
lines.append(...)blocks to"""strings across 12+ generators (AppDelegate, SceneDelegate, TabBar, AppConstants, ViewController, DarkMode, Localization, Theme, CLIPackageSwift, PackageSwift, SPMApp). Improves template readability - Generated code aligned with SwiftFormat rules — Removed blank lines after opening
{, addedfinalto generated classes, sorted imports alphabetically - LumiKit version bumped 0.2.0 → 0.8.0. Generated code uses
LMKThemeManager.shared.apply(theme)instead of.setTheme(theme) - Swift 6 concurrency in templates — Added
@MainActorto generatedDataPublisherclass,SWIFT_APPROACHABLE_CONCURRENCYandSWIFT_UPCOMING_FEATURE_MEMBER_IMPORT_VISIBILITYto XcodeGen settings - Makefile generator — Added
PROJECTvariable and-project $(PROJECT)flag for xcodeProj/xcodeGen. UsesDefaults.simulatorDestinationwithOS=version. Removed-skipPackagePluginValidation - License changed from MIT to Apache 2.0 (Monolith's own
LICENSEfile) - SwiftLint
type_name.max_lengthrelaxed — warning: 40→60, error: 50→70 (own config and generated configs) - SwiftFormat config updates —
--commas always→--trailing-commas collections-only,--enable redundantProperty→--enable redundantVariable(renamed rule), added--disable wrapPropertyBodies - Removed
Sendableconformance from all internal types — Not needed since they don't cross isolation boundaries - Trailing commas removed from function calls throughout codebase (consistent with
--trailing-commas collections-only) ProjectOpenerrewritten — Uses project name for.xcodeprojfilename, fallback logic checks forproject.ymlwhen.xcodeprojdoesn't exist- README and CLAUDE.md generators — Build instructions use
make build/make testfor xcodeProj/xcodeGen instead of rawxcodebuildcommands - Error diagnostics surfaced from shell-outs — previously silent
catch { return false }paths inXcodeGenRunner,ProjectOpener,FileWriter.gitInit, etc. now printerror.localizedDescriptionand any captured stderr throughUISymbols.warn. Users can finally tell "tool missing" from "permission denied" from "exit 1 with stderr message"
Tests
FileWriterTests(11 tests) — coverswriteFilewith nested dirs, executable bit,gitInithappy path +hasGitHooks+ nonexistent dir,gitAuthorName,resolveOutputPath. Previously zero coverage on a 286-line file every integration test depends onProjectYamlEditorTests(20 tests) — covers every editor (addPackage,addTargetDependency,enableMacCatalyst,addWidgetTarget,wireAppForWidget, end-to-end widget flow). Confirms idempotency and failure-mode messages. Previously zero coverage on 290 lines of hand-rolled YAML parsingShellRunnerTests+SignalHandlerTests(15 tests) — exercise capture/discard/launch-failure paths, mergeStderr, cwd, partial-output cleanupPromptEngineTests(16 tests) —parseFeaturesacross all three feature enums,parseTabs,isBackCommandWizardEngineTests(9 tests) — navigation helpers (visibleIndex,visibleCount,previousVisibleIndex) under hidden-step scenarios. Helpers madeinternalso the state machine can be tested without a TTYLocalizationAuditGeneratorTests(8 tests) — including a Pythonast.parseround-trip that catches escape-sequence regressions before they SyntaxWarning in user terminalsMakefileGeneratorTests— added two cases for the newhasLocalizationswitch (audit-strings target wired intocheck+help; omitted otherwise)- Generator output sanity checks (8 tests in
IntegrationTests) — structural assertions covering YAML indentation ofpreBuildScripts/postCompileScripts, theLumiKit→product: LumiKitUIline pair, test-source-file ordering before xcodegen,validate-app-icon.shPOSIX permissions = 0o755,MainTabBarControllerinit()declaration, and@MainActorisolation on the Core Data stack +TestContext. Each backed by a comment naming the regression it prevents - Total test count: 542 → 631
Fixed
GENERATE_INFOPLIST_FILE: YESadded to app template — prevents missingCFBundleIdentifierbuild error- GitHooksGenerator: removed
--quietfrom swiftformat — was suppressing lint output in pre-commit hook, making failures silent - Missing
OS=in package simulator destinations — Package README/CLAUDE.md generators had bareplatform=iOS Simulator,name=iPhone 17withoutOS=version
Removed
- SPM as a project system for iOS apps —
ProjectSystem.appOptionsnow only includesxcodeProjandxcodeGen(SPMexecutableTargetcan't handle signing, entitlements, or capabilities)
0.1.0
Changelog
All notable changes to Monolith will be documented in this file.
The format is based on Keep a Changelog,
and this project adheres to Semantic Versioning.
[Unreleased]
0.1.0 - 2026-03-03
Added
Commands
new app— Scaffold iOS apps with interactive wizard or--no-interactiveflagsnew package— Scaffold Swift Packages with multi-target supportnew cli— Scaffold Swift CLI tools with optional ArgumentParserlist features— List available features filtered by project type (--type app|package|cli)add <feature>— Add features to existing projects (devTooling,gitHooks,claudeMD,licenseChangelog)doctor— Check availability of required and optional toolscompletions— Generate shell completions (zsh, bash, fish)version— Print current version
Interactive Wizard
- Full-page guided setup with step progress (Step N of M)
- Summary of previous answers displayed on each page
- Back navigation (press
↑or typeback) with answer preservation - Native arrow key support via macOS editline (
CEditLinesystem library) - Confirmation page before generating
iOS App Features (15)
- SwiftData —
@Model,ModelContainersetup, in-memory test helpers - LumiKit — Package dependency with 22-color
LMKThemegeneration from primary color viaColorDeriver - SnapKit — Programmatic Auto Layout dependency
- Lottie — Animation dependency with optional
LumiKitLottieintegration - Dark Mode — Standalone
AppThemewith adaptiveUIColorpatterns (auto-enabled with LumiKit) - Combine — Publisher/subscriber boilerplate and async Task patterns
- Localization — String Catalog +
L10nhelper withString(localized:) - Dev Tooling — SwiftLint, SwiftFormat, Makefile, Brewfile (one toggle, four files)
- Git Hooks — Pre-commit hook (lint + format check on staged files)
- R.swift — Code generation + Mintfile (XcodeGen only)
- Fastlane — Gemfile, Appfile, Fastfile (XcodeGen only)
- CLAUDE.md — Project-specific Claude Code guide following ecosystem template
- License + Changelog — MIT license and Keep a Changelog template
- Tabs — Tab bar controller with nav-controller-per-tab pattern (auto-enabled from
--tabs) - Mac Catalyst — Window config and menu bar (auto-enabled from
--platforms macCatalyst)
iOS App Project Systems
- SPM —
Package.swiftwith.executableTarget(default) - XcodeGen —
project.ymlwithxcodegen generate
Package Features (6)
- Strict concurrency, default isolation (
MainActorper target), dev tooling, git hooks, CLAUDE.md, license + changelog - Multi-target support with inter-target dependencies (
--target-deps) - Multi-platform support (
--platforms "iOS 18.0,macOS 15.0,macCatalyst 18.0")
CLI Features (6)
- ArgumentParser dependency, strict concurrency, dev tooling, git hooks, CLAUDE.md, license + changelog
Generation Options
--preset— Pre-select features:minimal(none),standard(devTooling, gitHooks, claudeMD),full(all)--force— Overwrite existing project directory--open— Open in Xcode after generation--resolve— Runswift package resolveafter generation--save-config/--load-config— Save and reuse project configurations as JSON--output— Custom output directory--dry-run— Preview generated files without writing
Utilities
- ColorDeriver — HSB manipulation from 1 hex color to 22
LMKThemecolors - ToolChecker — Verify tool availability (
swift,git,swiftlint,swiftformat,xcodegen,mint,fastlane) - OverwriteProtection — Prevent accidental directory overwrites (respects
--force) - ProjectDetector — Detect existing project type in a directory
- ProjectOpener — Open generated projects in Xcode
- PackageResolver — Run
swift package resolveon generated projects - FileWriter — Write files with progress reporting and directory creation
Infrastructure
- Swift 6.2, macOS 14+
MonolithLib(testable library) +monolith(thin executable) architecture- Pure function generators:
(Config) -> Stringwith no side effects - ArgumentParser 1.7.0+ dependency
- 69 source files, 45 test files
- 378 tests across 52 suites (Swift Testing)
- MIT License