morphkit-cli 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 AshlrAI
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,449 @@
1
+ # Morphkit
2
+
3
+ > Your React app → Native iOS. In seconds.
4
+
5
+ Morphkit is a semantic AI agent that understands your TypeScript/React web app's *intent* — not just its code — and generates a production-quality SwiftUI Xcode project. It parses your components, routes, state, and API calls, builds a framework-agnostic semantic model, then emits idiomatic Swift targeting iOS 17+.
6
+
7
+ [![npm version](https://badge.fury.io/js/morphkit.svg)](https://www.npmjs.com/package/morphkit)
8
+ [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE)
9
+
10
+ **[morphkit.dev](https://morphkit.dev)**  |  **[GitHub](https://github.com/ashlrai/morphkit)**  |  **[Issues](https://github.com/ashlrai/morphkit/issues)**
11
+
12
+ ---
13
+
14
+ ## Quick Start
15
+
16
+ ```bash
17
+ # Install dependencies
18
+ bun install
19
+
20
+ # Analyze your web app and see the semantic model
21
+ bunx morphkit analyze ./my-nextjs-app
22
+
23
+ # Generate a full SwiftUI Xcode project
24
+ bunx morphkit generate ./my-nextjs-app --output ./ios-app
25
+
26
+ # Open in Xcode
27
+ open ./ios-app/MyNextjsApp/Package.swift
28
+ ```
29
+
30
+ That's it. Three commands from web app to Xcode project.
31
+
32
+ ---
33
+
34
+ ## What Gets Generated
35
+
36
+ Morphkit produces a complete, buildable Swift Package with this structure:
37
+
38
+ ```
39
+ ios-app/
40
+ ├── Package.swift # Swift Package manifest (iOS 17+)
41
+ ├── MyApp/
42
+ │ ├── MyAppApp.swift # @main app entry point
43
+ │ ├── ContentView.swift # Root navigation (TabView + NavigationStack)
44
+ │ ├── Info.plist # App configuration
45
+ │ ├── Assets.xcassets/ # Colors, app icon placeholders
46
+ │ ├── Models/ # Codable structs from your TS interfaces
47
+ │ ├── Views/ # SwiftUI views from your React components
48
+ │ ├── Navigation/ # Router, routes enum, tab configuration
49
+ │ ├── Networking/ # Typed URLSession API client
50
+ │ └── State/ # @Observable stores from your state management
51
+ ├── Tests/
52
+ │ └── MyAppTests.swift # Test stubs
53
+ └── README.md # Generated project documentation
54
+ ```
55
+
56
+ Every generated file includes a source mapping comment tracing back to the original web file:
57
+
58
+ ```swift
59
+ // Generated by Morphkit from: types/product.ts
60
+ ```
61
+
62
+ ---
63
+
64
+ ## Features
65
+
66
+ - **Semantic understanding** — Morphkit doesn't do string replacement. It builds an intermediate *semantic model* that captures what your app does, then generates native code from that understanding.
67
+ - **Full TypeScript type extraction** — Interfaces, type aliases, enums, and union types are converted to `Codable` Swift structs and enums with full fidelity.
68
+ - **React component analysis** — Detects layout patterns (list, detail, form, dashboard, settings) and generates the appropriate SwiftUI view composition.
69
+ - **Route-to-navigation mapping** — Next.js App Router file-based routes become `TabView`, `NavigationStack`, and deep link handlers.
70
+ - **State management translation** — `useState`, Zustand stores, Redux, and Context patterns map to `@Observable` classes and `@State` bindings.
71
+ - **API client generation** — `fetch` calls and API routes become a typed `URLSession` networking layer with `async/await`.
72
+ - **Confidence scoring** — Every generated file is tagged high/medium/low confidence so you know what to review first.
73
+ - **Preview data factories** — `#if DEBUG` extensions with `.preview()` methods for every model, so SwiftUI previews work out of the box.
74
+ - **AI-enhanced analysis (optional)** — Connect xAI Grok for deeper intent extraction, smarter component mapping, and navigation planning.
75
+ - **Zero runtime dependencies** — Generated Swift code uses only Foundation and SwiftUI. No third-party pods or packages.
76
+
77
+ ---
78
+
79
+ ## How It Works
80
+
81
+ Morphkit runs a three-stage pipeline:
82
+
83
+ ```
84
+ ┌─────────────┐ ┌──────────────────┐ ┌─────────────────┐
85
+ │ 1. Analyze │ → │ 2. Semantic │ → │ 3. Generate │
86
+ │ │ │ Model │ │ │
87
+ │ ts-morph │ │ Zod-validated │ │ SwiftUI views │
88
+ │ AST parsing │ │ app description │ │ Swift models │
89
+ │ Route scan │ │ Platform adapt │ │ Navigation │
90
+ │ State scan │ │ │ │ Networking │
91
+ │ API scan │ │ │ │ State stores │
92
+ └─────────────┘ └──────────────────┘ └─────────────────┘
93
+ ```
94
+
95
+ **Stage 1: Analyze** — Uses [ts-morph](https://ts-morph.com) to parse your TypeScript AST. Extracts components, routes, state patterns, API calls, types, and framework metadata. Detects Next.js App Router, Pages Router, or plain React.
96
+
97
+ **Stage 2: Semantic Model** — Builds a framework-agnostic `SemanticAppModel` (validated with Zod schemas) that describes *what* the app does: its entities, screens, navigation flows, state management, API endpoints, auth patterns, and theme. An optional platform adapter then maps web patterns to iOS equivalents.
98
+
99
+ **Stage 3: Generate** — Five specialized generators emit Swift code from the semantic model: views, models, navigation, networking, and state. The output is a complete Swift Package that opens directly in Xcode.
100
+
101
+ ---
102
+
103
+ ## Example
104
+
105
+ Given this TypeScript in your Next.js app:
106
+
107
+ ```typescript
108
+ // types/product.ts
109
+ export interface Product {
110
+ id: string;
111
+ name: string;
112
+ description: string;
113
+ price: number;
114
+ imageUrl: string;
115
+ category: string;
116
+ inStock: boolean;
117
+ rating?: number;
118
+ createdAt: Date;
119
+ }
120
+
121
+ export type SortOrder = 'price-asc' | 'price-desc' | 'name' | 'rating';
122
+ ```
123
+
124
+ Morphkit generates:
125
+
126
+ ```swift
127
+ // Generated by Morphkit from: types/product.ts
128
+
129
+ import Foundation
130
+
131
+ struct Product: Codable, Identifiable, Hashable {
132
+ let id: String
133
+ var name: String
134
+ var description: String
135
+ var price: Double
136
+ var imageUrl: String
137
+ var category: String
138
+ var inStock: Bool
139
+ var rating: Double?
140
+ var createdAt: Date
141
+ }
142
+
143
+ enum SortOrder: String, Codable, CaseIterable {
144
+ case priceAsc = "price-asc"
145
+ case priceDesc = "price-desc"
146
+ case name
147
+ case rating
148
+ }
149
+
150
+ // MARK: - Preview Data
151
+
152
+ #if DEBUG
153
+ extension Product {
154
+ static func preview() -> Product {
155
+ Product(
156
+ id: "preview-1",
157
+ name: "Sample Product",
158
+ description: "A sample product for previewing",
159
+ price: 29.99,
160
+ imageUrl: "https://picsum.photos/200",
161
+ category: "Sample",
162
+ inStock: true,
163
+ rating: nil,
164
+ createdAt: .now
165
+ )
166
+ }
167
+ }
168
+ #endif
169
+ ```
170
+
171
+ And your `app/products/page.tsx` list component becomes a native SwiftUI view:
172
+
173
+ ```swift
174
+ // Generated by Morphkit from: app/products/page.tsx
175
+
176
+ import SwiftUI
177
+
178
+ struct ProductsView: View {
179
+ @State private var products: [Product] = []
180
+ @State private var searchQuery: String = ""
181
+ @State private var sortOrder: SortOrder = .priceAsc
182
+ @State private var isLoading: Bool = false
183
+ @State private var errorMessage: String?
184
+
185
+ var body: some View {
186
+ List {
187
+ ForEach(products) { product in
188
+ NavigationLink(value: AppRoute.productsDetail(id: product.id)) {
189
+ HStack(spacing: 12) {
190
+ AsyncImage(url: URL(string: product.imageUrl)) { image in
191
+ image.resizable().aspectRatio(contentMode: .fill)
192
+ } placeholder: {
193
+ Image(systemName: "photo.circle.fill")
194
+ .foregroundStyle(.secondary)
195
+ }
196
+ .frame(width: 44, height: 44)
197
+ .clipShape(RoundedRectangle(cornerRadius: 8))
198
+ VStack(alignment: .leading, spacing: 4) {
199
+ Text(product.name)
200
+ .font(.headline)
201
+ Text(product.category)
202
+ .font(.subheadline)
203
+ .foregroundStyle(.secondary)
204
+ Text(product.price, format: .currency(code: "USD"))
205
+ .font(.subheadline)
206
+ .fontWeight(.semibold)
207
+ }
208
+ Spacer()
209
+ }
210
+ }
211
+ }
212
+ }
213
+ .searchable(text: $searchQuery)
214
+ .refreshable { await loadData() }
215
+ .navigationTitle("Products")
216
+ .task { await loadData() }
217
+ }
218
+
219
+ private func loadData() async {
220
+ isLoading = true
221
+ defer { isLoading = false }
222
+ do {
223
+ products = try await APIClient.shared.fetchProduct()
224
+ } catch {
225
+ errorMessage = error.localizedDescription
226
+ }
227
+ }
228
+ }
229
+ ```
230
+
231
+ The root `ContentView.swift` wires everything together with tab-based navigation:
232
+
233
+ ```swift
234
+ // Generated by Morphkit
235
+
236
+ import SwiftUI
237
+
238
+ struct ContentView: View {
239
+ @State private var router = Router()
240
+
241
+ var body: some View {
242
+ TabView(selection: $router.selectedTab) {
243
+ NavigationStack {
244
+ HomeView()
245
+ .navigationDestination(for: AppRoute.self) { route in
246
+ routeView(for: route)
247
+ }
248
+ }
249
+ .tabItem {
250
+ Label(AppTab.home.title, systemImage: AppTab.home.systemImage)
251
+ }
252
+ .tag(AppTab.home)
253
+ // ... Products, Cart tabs
254
+ }
255
+ .environment(router)
256
+ .onOpenURL { url in
257
+ router.handleDeepLink(url)
258
+ }
259
+ }
260
+ }
261
+ ```
262
+
263
+ ---
264
+
265
+ ## CLI Reference
266
+
267
+ ### `morphkit analyze <path>`
268
+
269
+ Analyze a web app and output its semantic model as JSON.
270
+
271
+ ```bash
272
+ bunx morphkit analyze ./my-app
273
+ bunx morphkit analyze ./my-app --output model.json
274
+ bunx morphkit analyze ./my-app --verbose
275
+ ```
276
+
277
+ | Option | Description |
278
+ |--------|-------------|
279
+ | `-o, --output <file>` | Write the semantic model JSON to a file instead of stdout |
280
+ | `-v, --verbose` | Show detailed analysis output (component counts, route counts, etc.) |
281
+
282
+ ### `morphkit generate <path>`
283
+
284
+ Generate a complete SwiftUI Xcode project from a web app.
285
+
286
+ ```bash
287
+ bunx morphkit generate ./my-app
288
+ bunx morphkit generate ./my-app --output ./ios-app --name ShopKit
289
+ bunx morphkit generate ./my-app --model model.json
290
+ ```
291
+
292
+ | Option | Description |
293
+ |--------|-------------|
294
+ | `-o, --output <dir>` | Output directory for the iOS project (default: `./ios-app`) |
295
+ | `-n, --name <name>` | App name — must be PascalCase (default: from `package.json`) |
296
+ | `--model <file>` | Use a pre-built semantic model JSON instead of re-analyzing |
297
+ | `-v, --verbose` | Show detailed generation output |
298
+
299
+ ### `morphkit preview <path>`
300
+
301
+ Preview what would be generated without writing any files to disk.
302
+
303
+ ```bash
304
+ bunx morphkit preview ./my-app
305
+ bunx morphkit preview ./my-app --screen Products
306
+ ```
307
+
308
+ | Option | Description |
309
+ |--------|-------------|
310
+ | `-s, --screen <name>` | Preview only files matching a specific screen name |
311
+
312
+ ---
313
+
314
+ ## Configuration
315
+
316
+ ### Environment Variables
317
+
318
+ | Variable | Required | Description |
319
+ |----------|----------|-------------|
320
+ | `XAI_API_KEY` | No | xAI API key for AI-enhanced analysis. When set, Morphkit uses Grok (`grok-4-1-fast-reasoning`) for deeper intent extraction, component mapping, navigation planning, and state architecture recommendations. Without it, Morphkit falls back to heuristic-based analysis. |
321
+
322
+ ### AI Enhancement (Optional)
323
+
324
+ When `XAI_API_KEY` is set, Morphkit can use xAI Grok to:
325
+
326
+ - **Analyze intent** — understand *why* a component exists, not just what it renders
327
+ - **Map components** — intelligently match React patterns to SwiftUI equivalents
328
+ - **Plan navigation** — decide whether tabs, stacks, or mixed patterns are most idiomatic
329
+ - **Architect state** — recommend `@Observable` store structure based on your Zustand/Redux/Context patterns
330
+ - **Generate code** — produce more nuanced SwiftUI for complex screen layouts
331
+
332
+ The AI layer is fully optional. All core functionality works without it.
333
+
334
+ ---
335
+
336
+ ## Supported Frameworks
337
+
338
+ | Framework | Status | Notes |
339
+ |-----------|--------|-------|
340
+ | Next.js App Router | Supported | Full support for file-based routing, layouts, loading states, API routes |
341
+ | Next.js Pages Router | Planned | Route detection works; component analysis coming |
342
+ | React + Vite | Planned | Component and state extraction works; routing TBD |
343
+ | React + CRA | Planned | Same as Vite support |
344
+
345
+ ### Supported Web Patterns
346
+
347
+ | Web Pattern | iOS Equivalent |
348
+ |-------------|----------------|
349
+ | `useState` | `@State` |
350
+ | Zustand stores | `@Observable` classes |
351
+ | Redux stores | `@Observable` singletons via `@Environment` |
352
+ | React Context | `@Environment` with custom `EnvironmentKey` |
353
+ | React Query / SWR | `async/await` with `.task { }` |
354
+ | `fetch` / `axios` | Typed `URLSession` via `APIClient` |
355
+ | Next.js file routing | `NavigationStack` + `TabView` |
356
+ | Dynamic routes (`[id]`) | `.navigationDestination(for:)` |
357
+ | CSS / Tailwind | SwiftUI modifiers + theme configuration |
358
+
359
+ ---
360
+
361
+ ## Architecture
362
+
363
+ ```
364
+ src/
365
+ ├── index.ts # CLI entry (Commander.js + chalk + ora)
366
+ ├── analyzer/ # Stage 1: Web app analysis
367
+ │ ├── repo-scanner.ts # File discovery, framework detection
368
+ │ ├── ast-parser.ts # TypeScript AST parsing (ts-morph)
369
+ │ ├── component-extractor # React component analysis
370
+ │ ├── route-extractor # Next.js route tree extraction
371
+ │ ├── state-extractor # State management detection
372
+ │ └── api-extractor # API endpoint extraction
373
+ ├── semantic/ # Stage 2: Semantic model
374
+ │ ├── model.ts # Zod schemas (single source of truth for all types)
375
+ │ ├── builder.ts # Analyzer output → SemanticAppModel
376
+ │ └── adapter.ts # Web patterns → iOS patterns
377
+ ├── generator/ # Stage 3: SwiftUI code generation
378
+ │ ├── swiftui-generator # View generation (List, Form, Detail, Dashboard)
379
+ │ ├── model-generator # Swift Codable structs from entities
380
+ │ ├── navigation-generator # TabView, NavigationStack, Router
381
+ │ ├── networking-generator # URLSession API client
382
+ │ └── project-generator # Xcode project orchestrator
383
+ └── ai/ # AI integration (optional)
384
+ ├── grok-client.ts # OpenAI SDK → xAI endpoint
385
+ ├── structured-output.ts # Zod schemas for AI responses
386
+ └── prompts/ # Intent, component, code gen prompts
387
+ ```
388
+
389
+ The `SemanticAppModel` (defined as Zod schemas in `src/semantic/model.ts`) is the central contract. Everything before it is analysis; everything after it is generation. This separation means you can swap out the analyzer (to support Vue, Angular, etc.) or the generator (to target Kotlin/Compose, Flutter, etc.) without touching the other side.
390
+
391
+ ---
392
+
393
+ ## Development
394
+
395
+ ### Prerequisites
396
+
397
+ - [Bun](https://bun.sh) 1.0+
398
+ - Node.js 20+ (alternative runtime)
399
+ - TypeScript 5.7+
400
+
401
+ ### Setup
402
+
403
+ ```bash
404
+ git clone https://github.com/ashlrai/morphkit.git
405
+ cd morphkit
406
+ bun install
407
+ ```
408
+
409
+ ### Commands
410
+
411
+ ```bash
412
+ # Run all tests (53 tests, 376 assertions)
413
+ bun test
414
+
415
+ # TypeScript strict type checking
416
+ bun run typecheck
417
+
418
+ # Run against a local web app
419
+ bun run src/index.ts analyze ./path-to-app
420
+ bun run src/index.ts generate ./path-to-app --output ./ios-output
421
+ bun run src/index.ts preview ./path-to-app
422
+ ```
423
+
424
+ ### Test Suite
425
+
426
+ The test suite covers the full pipeline with a sample Next.js e-commerce app (`test/__fixtures__/sample-nextjs-app/`):
427
+
428
+ - **Analyzer tests** — AST parsing, component extraction, route detection, state pattern recognition
429
+ - **Semantic tests** — Model building, type mapping, adapter transformations
430
+ - **Generator tests** — Swift model output, view generation, navigation, networking
431
+ - **E2E tests** — Full pipeline from source scan to generated Xcode project
432
+ - **Swift quality tests** — Validates generated code compiles and follows iOS conventions
433
+
434
+ ```
435
+ 53 pass | 0 fail | 376 expect() calls
436
+ ```
437
+
438
+ ### Project Conventions
439
+
440
+ - All types are Zod schemas first, TypeScript types inferred via `z.infer<>` (see `src/semantic/model.ts`)
441
+ - Generated Swift targets iOS 17+ (`@Observable`, not `ObservableObject`; `#Preview`, not `PreviewProvider`)
442
+ - Entity names are PascalCase, variables camelCase in generated Swift
443
+ - Every generated file carries confidence scoring and source provenance
444
+
445
+ ---
446
+
447
+ ## License
448
+
449
+ MIT — [AshlrAI](https://ashlr.ai)