codz-cli 0.0.0-stage → 0.1.2

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.
Files changed (118) hide show
  1. package/BETA.md +91 -0
  2. package/LICENSE +21 -0
  3. package/README.md +525 -2
  4. package/assets/gradle-wrapper/README.txt +2 -0
  5. package/assets/gradle-wrapper/gradle-wrapper.jar +0 -0
  6. package/assets/gradle-wrapper/gradlew +251 -0
  7. package/assets/gradle-wrapper/gradlew.bat +94 -0
  8. package/bin/codz.js +33 -0
  9. package/dist/adapters/android.js +321 -0
  10. package/dist/adapters/androidSetup.js +277 -0
  11. package/dist/adapters/common.js +114 -0
  12. package/dist/adapters/dartGen.js +83 -0
  13. package/dist/adapters/flutter.js +291 -0
  14. package/dist/adapters/flutterGen.js +204 -0
  15. package/dist/adapters/flutterScan.js +312 -0
  16. package/dist/adapters/flutterSetup.js +252 -0
  17. package/dist/adapters/flutterStyles.js +130 -0
  18. package/dist/adapters/generic.js +20 -0
  19. package/dist/adapters/getx.js +423 -0
  20. package/dist/adapters/index.js +28 -0
  21. package/dist/adapters/ios.js +440 -0
  22. package/dist/adapters/kotlinGen.js +110 -0
  23. package/dist/adapters/models.js +116 -0
  24. package/dist/adapters/nextjs.js +243 -0
  25. package/dist/adapters/nextjsGen.js +285 -0
  26. package/dist/adapters/nextjsScan.js +364 -0
  27. package/dist/adapters/nextjsSetup.js +119 -0
  28. package/dist/adapters/react.js +89 -0
  29. package/dist/adapters/reactNative.js +109 -0
  30. package/dist/adapters/reactNativeSetup.js +236 -0
  31. package/dist/adapters/reactQuery.js +89 -0
  32. package/dist/adapters/reactSetup.js +150 -0
  33. package/dist/adapters/source.js +165 -0
  34. package/dist/cli.js +1175 -0
  35. package/dist/core/cache.js +76 -0
  36. package/dist/core/changeset.js +404 -0
  37. package/dist/core/commands.js +239 -0
  38. package/dist/core/config.js +45 -0
  39. package/dist/core/diff.js +143 -0
  40. package/dist/core/events.js +41 -0
  41. package/dist/core/fsutil.js +122 -0
  42. package/dist/core/git.js +36 -0
  43. package/dist/core/jsonEdit.js +113 -0
  44. package/dist/core/merge.js +159 -0
  45. package/dist/core/proc.js +23 -0
  46. package/dist/core/safe.js +75 -0
  47. package/dist/core/templates.js +100 -0
  48. package/dist/core/tsAst.js +112 -0
  49. package/dist/core/types.js +12 -0
  50. package/dist/core/validateConfig.js +172 -0
  51. package/dist/core/workflow.js +72 -0
  52. package/dist/core/workspace.js +80 -0
  53. package/dist/core/yaml.js +126 -0
  54. package/dist/core/yamlDoc.js +367 -0
  55. package/dist/detector.js +95 -0
  56. package/dist/input/apiSpec.js +395 -0
  57. package/dist/input/curl.js +259 -0
  58. package/dist/input/endpoint.js +220 -0
  59. package/dist/input/har.js +120 -0
  60. package/dist/input/infer.js +174 -0
  61. package/dist/input/naming.js +145 -0
  62. package/dist/input/paste.js +130 -0
  63. package/dist/skills/androidSkeleton.js +292 -0
  64. package/dist/skills/androidTests.js +221 -0
  65. package/dist/skills/androidUi.js +561 -0
  66. package/dist/skills/androidViews.js +536 -0
  67. package/dist/skills/apiAdd.js +99 -0
  68. package/dist/skills/apiDiff.js +271 -0
  69. package/dist/skills/apiEdit.js +547 -0
  70. package/dist/skills/apiImport.js +127 -0
  71. package/dist/skills/apiList.js +35 -0
  72. package/dist/skills/apiSync.js +221 -0
  73. package/dist/skills/auth.js +1304 -0
  74. package/dist/skills/completion.js +142 -0
  75. package/dist/skills/config.js +93 -0
  76. package/dist/skills/create.js +638 -0
  77. package/dist/skills/createDemo.js +1026 -0
  78. package/dist/skills/doctor.js +304 -0
  79. package/dist/skills/doctorFix.js +214 -0
  80. package/dist/skills/explain.js +61 -0
  81. package/dist/skills/feature.js +418 -0
  82. package/dist/skills/featureEdit.js +225 -0
  83. package/dist/skills/featureLinks.js +179 -0
  84. package/dist/skills/init.js +66 -0
  85. package/dist/skills/iosUi.js +468 -0
  86. package/dist/skills/locale.js +335 -0
  87. package/dist/skills/mcp.js +175 -0
  88. package/dist/skills/mock.js +482 -0
  89. package/dist/skills/module.js +23 -0
  90. package/dist/skills/plans.js +66 -0
  91. package/dist/skills/prefill.js +84 -0
  92. package/dist/skills/reactNativeUi.js +388 -0
  93. package/dist/skills/reactUi.js +352 -0
  94. package/dist/skills/report.js +75 -0
  95. package/dist/skills/route.js +230 -0
  96. package/dist/skills/screen.js +597 -0
  97. package/dist/skills/screenForm.js +410 -0
  98. package/dist/skills/setup.js +28 -0
  99. package/dist/skills/setupDoctor.js +226 -0
  100. package/dist/skills/templatesCmd.js +32 -0
  101. package/dist/skills/testgen.js +331 -0
  102. package/dist/skills/theme.js +388 -0
  103. package/dist/starters/auth.js +144 -0
  104. package/dist/starters/commands.js +283 -0
  105. package/dist/starters/engine.js +315 -0
  106. package/dist/starters/home.js +42 -0
  107. package/dist/starters/http.js +93 -0
  108. package/dist/starters/manifest.js +285 -0
  109. package/dist/starters/paths.js +70 -0
  110. package/dist/starters/publish.js +150 -0
  111. package/dist/starters/registry.js +258 -0
  112. package/dist/starters/sign.js +72 -0
  113. package/dist/starters/source.js +98 -0
  114. package/dist/starters/strictJson.js +148 -0
  115. package/dist/starters/tar.js +180 -0
  116. package/docs/COMMANDS.md +527 -0
  117. package/examples/openapi.yaml +319 -0
  118. package/package.json +57 -4
package/README.md CHANGED
@@ -1,3 +1,526 @@
1
- # Temporary Holding Version
1
+ # codz
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ A project-aware CLI that learns how your project is built, then makes the same structural change the same way every time. It runs offline, never uploads code, shows a diff before writing anything, and can undo every change.
4
+
5
+ Adapters for **Next.js**, **React (Vite)**, **Flutter**, **React Native**, **Android (Kotlin)** and **iOS (SwiftUI)**: new projects (`codz create`, opening on a demo screen in the architecture you pick), API endpoints (add, import, update, rename, remove), screens and forms, routes, mocks, tests, locales, theme values and project health checks, all with a diff first, `--plan`/`apply`, `undo` and `--json`. MIT licensed.
6
+
7
+ ## Requirements
8
+
9
+ - Node.js **20 or newer** for the built package (`npm run build`), or **22.18 or newer** to run the TypeScript source directly from a checkout. There are no runtime dependencies.
10
+ - Git (optional, but recommended: codz refuses to apply changes over uncommitted work unless you pass `--allow-dirty`).
11
+
12
+ ## Install
13
+
14
+ ```bash
15
+ npm install -g codz-cli # the command is `codz`
16
+ codz --help
17
+ ```
18
+
19
+ From a checkout instead:
20
+
21
+ ```bash
22
+ cd codz
23
+ npm link # puts `codz` on your PATH
24
+ codz --help
25
+ ```
26
+
27
+ On Node 22.18+ this runs the TypeScript in `src/` directly. On Node 20 or 21, run `npm run build` first; `bin/codz.js` then uses the compiled `dist/` (set `CODZ_DIST=1` to force it).
28
+
29
+ **Publishing:** the package is `codz-cli` on npm (npm refused the plain name `codz` as too similar to existing packages); the command it installs is still `codz`. `npm publish` builds `dist/` and runs the tests first (`prepublishOnly`); the package ships `bin/`, `dist/`, the README, the license, docs/COMMANDS.md, the examples and assets, not the TypeScript source. Publishing needs two-factor authentication on the npm account. Raise the version first (`npm version patch`): a published version cannot be replaced.
30
+
31
+ ### Check your setup
32
+
33
+ ```bash
34
+ cd my-app
35
+ codz doctor --setup
36
+ ```
37
+
38
+ It checks Node, git (installed, a repository, a clean tree), the config file (found, valid, paths that exist), whether `.codz/` is git-ignored, the framework and any libraries codz does not write for yet, the formatter and analyzer, the scan cache and the change history. Each line is `pass`, `warn` or `fail` with a hint; the exit code is 1 when anything fails. It only reads.
39
+
40
+ ### Shell completion
41
+
42
+ ```bash
43
+ eval "$(codz completion bash)" # in ~/.bashrc
44
+ source <(codz completion zsh) # in ~/.zshrc, after compinit
45
+ codz completion fish > ~/.config/fish/completions/codz.fish # fish
46
+ ```
47
+
48
+ Completes commands, flags, endpoint names (`codz api show <TAB>`), plan ids, config keys and their allowed values.
49
+
50
+ ## Quick start
51
+
52
+ ```bash
53
+ cd my-app
54
+ codz init # detect the framework, scan, write codz.config.yaml
55
+ # (a fresh project is offered an architecture to set up)
56
+ codz explain # routes, endpoints, models, locales, conventions
57
+
58
+ # Paste a cURL command and (optionally) the response, then press Ctrl-D:
59
+ codz api add
60
+
61
+ # Or pass everything as flags:
62
+ codz api add --curl "curl https://api.example.com/users/42/orders" --sample orders.json
63
+ codz api add --url "POST https://api.example.com/users" --request-sample new-user.json --sample user.json
64
+
65
+ codz undo # revert the last change
66
+ ```
67
+
68
+ Every change shows a diff and asks before writing. Use `--dry-run` to preview only, `--yes` to apply without asking, or `--plan` to save the diff and apply exactly that later with `codz apply <id>`.
69
+
70
+ ### New projects: create
71
+
72
+ ```bash
73
+ codz create # asks: type, architecture, name, org, base URL, options
74
+ codz create shop-app --type android --architecture retrofit-hilt --org com.acme --base-url https://api.shop.dev
75
+ codz create shop-app --type react-native --flavor expo --architecture axios-react-query
76
+ codz create shop_app --type flutter --architecture riverpod --primary "#0F766E"
77
+ codz create shop-app --type nextjs --architecture fetch-helper --tailwind --dry-run
78
+ codz create shop-web --type react --architecture axios-react-query
79
+ codz create shop-app --type ios --architecture urlsession --org com.acme
80
+ ```
81
+
82
+ `create` asks for the project type (Flutter, Next.js, React (Vite), React Native, Android, iOS), then the architecture for that type, the project name, the organization id (for app ids and packages), the API base URL and the type's own options (Tailwind for Next.js, Expo or the React Native CLI). It runs the platform's own creator (`flutter create`, `create-next-app`, `create-expo-app`, the React Native CLI), applies the architecture with the same `setup` as below, writes `codz.config.yaml`, sets the theme color, installs dependencies and makes the first git commit. Without the platform tool, or with `--offline`, codz writes a minimal project of its own instead. Android has no command-line creator, so codz always writes Android Studio's Empty Activity project itself (Kotlin, Jetpack Compose, a version catalog, Navigation Compose with a Home screen) and adds the Gradle wrapper. React (Vite) and iOS also use built-in templates: Vite's react-ts project, and Xcode 16's SwiftUI App project (a synchronized source folder, so files codz adds are part of the app without editing the project file). Every project opens on a demo task list written in the chosen architecture (a Riverpod notifier, a GetX module, a Cubit, a Hilt or Koin ViewModel, a TanStack Query hook, an ObservableObject...), on sample data, so you start from a working example of the pattern; `codz feature add` and `codz api add` replace the sample data with your API. `--dry-run` lists the steps; `--no-install` and `--no-git` skip those steps.
83
+
84
+ | Type | Architectures |
85
+ | --- | --- |
86
+ | Flutter | `riverpod`, `getx`, `bloc`, `get_it`, `none` |
87
+ | Next.js | `fetch-helper`, `plain-fetch`, `none` |
88
+ | React Native | `fetch-helper`, `axios-react-query`, `axios`, `none` (each with `--flavor expo` or `bare`) |
89
+ | Android | `retrofit-hilt`, `retrofit-koin`, `retrofit`, `none` |
90
+
91
+ ### Ready-made starters: codz new (online)
92
+
93
+ ```bash
94
+ codz new shop_app --template ./starters/flutter-riverpod-dio --org com.acme # a template folder: no network, no account
95
+ codz starters list --framework flutter # the catalog (when it is online)
96
+ codz starters show flutter-riverpod-dio # what it adds beyond codz create, tested SDKs, license
97
+ codz login # only for paid starters: approve a code in the browser
98
+ codz new shop_app --template flutter-riverpod-dio@1.2.0
99
+ cd shop_app && codz init # then api add, screen add, ... as usual
100
+ ```
101
+
102
+ `create` is free and offline and builds an architecture. `new` installs a finished starter (screens, theming, tests, error handling) from the starter catalog or a template folder. `new`, `starters`, `login`, `logout` and `whoami` are the only commands with network code, and they load it only when they run. They contact only the starter catalog and send nothing about your projects.
103
+
104
+ - **Checked before use.** The catalog index is signed with Ed25519 and checked against keys built into codz. An index older than one this machine has seen is refused, and so is an expired one, so a mirror cannot hide a withdrawn version. A catalog can also name online keys that sign a short-lived `timestamp.json` confirming the index is still current; codz then checks that signature, that it points at this exact index, and that it has not expired or gone backwards, so the long-lived index can stay signed offline. Every archive must match the hash in the signed index, and every file must match the hash in its manifest. A withdrawn version is refused even from the cache.
105
+ - **Data only.** A starter is files plus a manifest. It never runs its own scripts; codz runs only `flutter create`, `flutter pub get`, `dart format` and `npm install --ignore-scripts`, with arguments it builds itself from typed answers.
106
+ - **Strict reading.** The archive reader accepts regular files and folders only. Links, devices, `..`, absolute paths, Windows reserved names, case or Unicode clashes, and oversized or bomb archives stop it before anything is written.
107
+ - **One step, and undoable.** The preview lists every file and step. The project is built in a temporary folder and moved into place in one rename. `codz undo` inside the new project removes it again while you have not changed it; files from `pub get`, `npm install` and `codz init` do not count as changes.
108
+ - **Plans and agents.** `--plan` (or `--json` without `--yes`) saves a plan, and `codz apply <id>` creates exactly that. From MCP, `new` only plans, `login` is not a tool, and a paid starter has to be downloaded once by a person first.
109
+ - **Offline.** `--cached` uses only what is already downloaded. In CI, set `CODZ_TOKEN` instead of logging in.
110
+
111
+ The catalog is served by the separate codz store project (accounts, purchases, `codz login`); until a release points at it, `new` works with template folders or `CODZ_REGISTRY`. Starter sources live in `starters/`, and `scripts/starters.ts` checks, packs and signs them (see starters/README.md).
112
+
113
+ ### Fresh projects: setup
114
+
115
+ When a project has no API layer yet, `codz init` asks which architecture to create and for the API base URL, then shows one diff with everything:
116
+
117
+ | Framework | Architecture | What it creates |
118
+ | --- | --- | --- |
119
+ | Flutter | `getx` | `createDio()` with your base URL, an `InitialBinding` that registers Dio, `GetMaterialApp(initialBinding: ...)` in `main.dart`, `dio` and `get` in `pubspec.yaml` |
120
+ | Flutter | `riverpod` | `createDio()` and `dioProvider`, `ProviderScope` around the app, `dio` and `flutter_riverpod` |
121
+ | Flutter | `get_it` | `createDio()`, `setupDependencies()` called from `main()`, `dio` and `get_it` |
122
+ | Flutter | `bloc` | `createDio()` and get_it registrations, `flutter_bloc` for Cubit screens |
123
+ | Next.js | `fetch-helper` | `lib/api/client.ts` with `apiFetch<T>()` and `ApiError`, `lib/api/index.ts`, `NEXT_PUBLIC_API_URL` in `.env.example` and `.env.local` |
124
+ | Next.js | `plain-fetch` | Only `NEXT_PUBLIC_API_URL`; each function calls `fetch` itself |
125
+ | React Native | `fetch-helper` | `src/config/env.ts` (`API_URL`, `USE_MOCKS`; `EXPO_PUBLIC_*` on Expo), `src/api/client.ts` with `apiFetch<T>()`, React Navigation (`RootNavigator`, a Home screen) and `App.tsx` |
126
+ | React Native | `axios` / `axios-react-query` | The same with an axios instance; `axios-react-query` adds a `QueryClientProvider` and a query hook per endpoint |
127
+ | Android | `retrofit-hilt` | `ApiConfig.BASE_URL`, a Hilt `NetworkModule` (Json, OkHttpClient with logging, Retrofit), `@HiltAndroidApp` application, `@AndroidEntryPoint` on `MainActivity`, INTERNET permission, plugins and libraries in `libs.versions.toml` (KSP, Hilt, kotlinx.serialization) |
128
+ | Android | `retrofit-koin` | The same with a Koin `networkModule` started from the application class |
129
+ | Android | `retrofit` | The same with a `ServiceLocator` object and no DI library |
130
+
131
+ Android dependencies go into `gradle/libs.versions.toml` and the module's `build.gradle.kts` when the project has a version catalog, otherwise straight into `build.gradle.kts` (Groovy build files get a list of what to add).
132
+
133
+ It also saves the folder conventions, so every later `api add` puts models and repositories in the right place and registers new repositories (`Get.lazyPut`, a Riverpod provider, or a get_it registration) with no manual step. After setup, codz runs `flutter pub get` when Flutter is installed.
134
+
135
+ Without a terminal (scripts, CI, agents), pass the choice as flags:
136
+
137
+ ```bash
138
+ codz setup --architecture getx --base-url https://api.example.com --yes
139
+ codz init --architecture riverpod --base-url https://api.example.com --yes
140
+ ```
141
+
142
+ ### GetX modules and wiring
143
+
144
+ For GetX projects (set up by codz or created with the GetX CLI), codz writes features in the GetX CLI layout:
145
+
146
+ ```bash
147
+ codz module add profile # binding, controller, view, route
148
+ codz api add --into profile < request.txt # new endpoint, called from ProfileController
149
+ codz api wire getProducts --into home # existing endpoint into HomeController
150
+ codz module add catalog --api getProducts # new module with an endpoint already wired
151
+ ```
152
+
153
+ - `module add` creates `lib/app/modules/<name>/{bindings,controllers,views}` and registers the page in `lib/app/routes/app_pages.dart` and `app_routes.dart`. If those files don't exist yet, it creates them and points `GetMaterialApp` at `AppPages.routes`. Route constants follow your file: `Routes.PROFILE` in a GetX CLI project, `Routes.profile` otherwise. `--initial` makes the module the first screen.
154
+ - `api wire` adds the repository with `Get.find`, Rx state (`user`, `isUserLoading`, `userError`), and a `loadUser()` method with try/catch. When the call needs no arguments, `onInit` calls it automatically (`--no-load` to skip). Running it twice changes nothing.
155
+
156
+ ### Importing a whole API
157
+
158
+ ```bash
159
+ codz api import openapi.yaml # OpenAPI 3 (YAML or JSON)
160
+ codz api import swagger.json --tag users # Swagger 2, only operations tagged "users"
161
+ codz api import shop.postman_collection.json --only getUser,listUsers
162
+ ```
163
+
164
+ Every operation becomes an endpoint exactly as `api add` would write it. Shared schemas become one model, endpoints of one resource land in one file, and endpoints the project already has are skipped. Postman examples are used as response samples; requests without one are typed `unknown`/`dynamic` with a warning.
165
+
166
+ **From the browser (HAR).** In Chrome DevTools → Network, use "Save all as HAR with content", then:
167
+
168
+ ```bash
169
+ codz api import app.har --list --base-url https://api.example.com # see what it found
170
+ codz api import app.har --base-url https://api.example.com
171
+ ```
172
+
173
+ JSON calls are grouped by method and path (`/users/42` and `/users/43` become `/users/{id}`, with both responses as samples). Analytics hosts, images, scripts and failed responses (`--include-errors` keeps those) are skipped. Headers and cookies are never read, secret query parameters are dropped, and response bodies are only used to work out types: no value from the file is written, cached or kept in history. A HAR file still holds your session cookies, so do not commit it.
174
+
175
+ **Filters** work with every format:
176
+
177
+ | Flag | Keeps |
178
+ | --- | --- |
179
+ | `--list` | nothing: prints what would be imported and stops |
180
+ | `--tag t` / `--only name` | operations with that tag (OpenAPI), folder (Postman) or host (HAR) / those names |
181
+ | `--path '/users/**'` | paths matching the glob: `*` is one segment, `**` any number; `{id}` and `:id` both match a parameter |
182
+ | `--method GET,POST` | those methods |
183
+ | `--max 20` | the first 20 that match |
184
+ | `--base-url <url>` | HAR: requests under that URL only |
185
+ | `--skip-conflicts` | imports what works when some endpoints cannot be added (by default codz lists them and stops) |
186
+
187
+ Imports of more than 50 operations need `--max` or `--yes`, so a whole spec is never added by accident.
188
+
189
+ The spec's server URL stands in for your app's own base URL (often another environment), so its host is never written into a call. When your client already has a base URL (Dio `BaseOptions(baseUrl: ...)`, Retrofit, a fetch helper, an axios instance), calls use the path only: `/v1/orders/$orderId`, or `/orders/$orderId` when the base URL already ends in `/v1`.
190
+
191
+ ### Changing endpoints
192
+
193
+ ```bash
194
+ codz api update getUser --sample new-user.json # rebuild the model from a new response
195
+ codz api rename listUsers fetchUsers # rename the function and every call site
196
+ codz api remove deleteUser # remove it; lists callers that will break
197
+ ```
198
+
199
+ `api update` rewrites the model in place and prints the fields that were added, removed or changed type, plus every line in your code that uses a removed or changed field. Code you added to a model is kept: in Dart, every member codz does not generate (`copyWith`, `==`/`hashCode`, `toString`, getters, other constructors and methods) comes back after the regenerated fields, with a warning if one of them still uses a field that was removed; in TypeScript, comments above interface fields stay.
200
+
201
+ `api rename` and `api remove` find uses with your project's own TypeScript compiler when `typescript` is installed in it (it is in almost every Next.js project), so a local variable or parameter that happens to share the name, an object key, or another file's own function with that name is never touched. Without it, codz falls back to its text scanner (`CODZ_NO_AST=1` forces the fallback).
202
+
203
+ ### Other stacks
204
+
205
+ codz writes in the style the project already uses:
206
+
207
+ - **axios (Next.js):** API functions call your `axios.create` instance (`const res = await api.get<User>(...)`), with query parameters as `{ params }`. Without an instance they call `axios` with the base URL from your environment. `mock add` adds a request interceptor to the instance.
208
+ - **TanStack Query (Next.js):** when the project already uses `@tanstack/react-query`, `api add` also writes a hook: `useQuery` for a GET (key `[resource, ...path params, query params]`), `useMutation` for the rest, invalidating the resource's queries on success. Hooks go into the hooks file that already imports from the same API file, otherwise `hooks/use-<resource>.ts`. Set `dataFetching: none` in `codz.config.yaml` to turn this off.
209
+ - **freezed (Flutter):** models are `@freezed` classes with a const factory constructor (`abstract class` for freezed 3, `class` for freezed 2, following your existing models). `api update` keeps your `@Default(...)` values and hand-written members. Run `dart run build_runner build` afterwards.
210
+ - **React Native:** the same TypeScript generation as Next.js (your `apiFetch` helper or axios instance, relative imports when the project has no `@/` alias), with the API URL from `src/config/env.ts`. Screens are React Navigation screens (an entry in `RootStackParamList` and a `<Stack.Screen>`) or Expo Router files under `app/` (`[id].tsx`, `useLocalSearchParams`); lists use `FlatList` with pull to refresh. Tests are Jest.
211
+ - **Android (Kotlin):** endpoints become `suspend` methods on a Retrofit interface per resource (`@GET("users/{id}") suspend fun getUser(@Path("id") id: Int): User`), with paths relative to the base URL. Models are data classes in the project's JSON library: kotlinx.serialization (`@Serializable`, `@SerialName`), Moshi (`@JsonClass`, `@Json`) or Gson (`@SerializedName`); optional fields default to `null`. A new interface is registered where Retrofit is created: a `@Provides` function in the Hilt module, a `single { }` in the Koin module, or a `by lazy` property on the service locator. `api update`, `rename` and `remove` work on Kotlin too. A `{"data": ...}` envelope needs `--no-unwrap`.
212
+ - **Retrofit (Flutter):** endpoints become annotated methods on your `@RestApi()` client (`@GET('/users/{id}') Future<User> getUser(@Path('id') int id);`), or on a new client registered like a repository. A `{"data": ...}` envelope needs `--no-unwrap`, because a Retrofit method returns the whole body.
213
+
214
+ ### Keeping up with the API: api sync
215
+
216
+ ```bash
217
+ codz api sync openapi.yaml # update endpoints whose spec changed
218
+ codz api sync openapi.yaml --add # ...and add the ones the project does not have yet
219
+ codz api sync openapi.yaml --remove # ...and delete endpoints the spec no longer has
220
+ codz api sync openapi.yaml --check # CI: exit 1 when the project is out of date with the spec
221
+ ```
222
+
223
+ Endpoints are matched by method and path (a base prefix like `/v1` that your base URL already holds is allowed). A matched endpoint is rewritten from the spec in place: its response and request models (keeping your own members and comments, and the field order you have), its parameters, keeping your path and parameter names. Unchanged endpoints are left alone, and a second sync finds nothing to do. Changes that break callers (a response field removed or changed type, a new required parameter, a new request body) are listed with the lines that use them. Endpoints only in your project are listed, not removed, unless you pass `--remove`; they may belong to another API.
224
+
225
+ ### Before you merge: api diff
226
+
227
+ ```bash
228
+ codz api diff openapi-main.yaml openapi-pr.yaml # what changed, what breaks, where it is used
229
+ codz api diff old.yaml new.yaml --format md --report api-diff.md # a pull request comment
230
+ codz api diff old.yaml new.yaml --format sarif --report api.sarif # GitHub code scanning
231
+ codz api diff old.yaml new.yaml --fail-on warning # exit 1 on warnings too (default: breaking)
232
+ ```
233
+
234
+ Breaking: an operation removed, a response field removed or retyped, a new path parameter, a new required request field. Warning: a response field that can now be null, a removed query parameter, a retyped request field. Added operations, response fields and optional request fields are listed as additions. Inside a project each change names the endpoint function and the files and lines that use it (its callers, the screens, the model); outside a project it compares the two files only. Nothing is written except the `--report` file.
235
+
236
+ ### Mock responses
237
+
238
+ ```bash
239
+ codz mock add --all # a mock for every endpoint
240
+ codz mock add getUser --sample user.json # use a real response as the mock
241
+ ```
242
+
243
+ - Flutter: `mocks/mock_responses.dart` and a `MockInterceptor` next to your Dio setup, added to Dio only when you run `flutter run --dart-define=USE_MOCKS=true`.
244
+ - Next.js: `mocks.ts` next to your request helper, checked first when `NEXT_PUBLIC_USE_MOCKS=true` (added to `.env.example` as `false`).
245
+
246
+ Mock data is generated from the models (`email` fields get emails, `id`s count up) and is yours to edit. With `--sample`, values that look like secrets or personal data (tokens, passwords, emails, phone numbers, names, addresses, long token-like strings) are replaced with examples before anything is written; `--keep-values` writes the sample exactly as given. Mocks are keyed by method and path, so renaming an endpoint keeps them. Running `mock add` again leaves mocks you edited by hand alone and says which ones it kept; `--sample` or `--force` replaces them.
247
+
248
+ ### Locales
249
+
250
+ ```bash
251
+ codz locale add hi # copy every key from the default language
252
+ codz locale key cart.empty "Your cart is empty" --value hi="आपकी कार्ट खाली है"
253
+ ```
254
+
255
+ Works with JSON message files (next-intl, i18next; `cart.empty` becomes a nested key), Flutter ARB files (keys become identifiers like `cartEmpty`, `{name}` placeholders get metadata) and GetX `Translations`. A GetX project without translations gets `lib/app/translations/app_translations.dart`, wired into `GetMaterialApp` with `translations:`, `locale:` and `fallbackLocale:`. Languages without a `--value` get the default text and are listed by `codz doctor` as untranslated. Only the changed keys are touched; the rest of each file keeps its formatting.
256
+
257
+ ### Theme
258
+
259
+ ```bash
260
+ codz theme set primary "#6750A4" radius 12 font Inter
261
+ ```
262
+
263
+ The kind comes from the value: `#hex` is a color, a number is a size, anything else is a font.
264
+
265
+ - Flutter: `AppColors`, `AppSizes` and `AppTheme` (light and dark, seeded from `AppColors.primary`) in `lib/app/theme` (GetX) or `lib/core/theme`, or wherever your project already keeps `AppColors`. `MaterialApp` / `GetMaterialApp` gets `theme: AppTheme.light`. The Flutter template theme is replaced; a theme you wrote yourself is left alone, with a note.
266
+ - Next.js: Tailwind v4 `@theme` variables (`bg-primary`), Tailwind v3 `theme.extend` in `tailwind.config`, or plain CSS variables in `:root` in `globals.css`.
267
+ - React Native: `colors`, `sizes` and `fonts` in `src/theme/index.ts`.
268
+ - Android: `val Primary = Color(0xFF...)` in `ui/theme/Color.kt` and sizes as `dp` in `ui/theme/Dimens.kt` (a project made by `codz create` already feeds `Primary` into its Material 3 color scheme). Fonts are not set on Android yet.
269
+
270
+ ### Whole features and sign-in
271
+
272
+ ```bash
273
+ codz feature add orders --spec openapi.yaml # endpoints, list, detail, create and edit screens, routes, tests
274
+ codz feature add users --spec openapi.yaml --tag users --no-tests
275
+ codz auth add # sign-in screen, secure token storage, token on every request
276
+ codz auth add --login-path /v1/session --refresh-path /v1/session/refresh --public /pricing
277
+ ```
278
+
279
+ `feature add` takes the operations whose path or tag names the feature (or `--tag` / `--path`), adds their endpoints, makes a list screen, a detail screen, a create form and an edit form where the API has them, links them (tapping a row opens the detail, a New button opens the form) and adds tests. Every step is planned in a private copy of the project and shown as one diff: one apply, one undo. A model clash stops the whole feature unless you pass `--skip-conflicts`.
280
+
281
+ A project with no API layer yet (fresh from `flutter create`, `create-next-app`, Vite, Expo, the React Native CLI, Android Studio or Xcode) is set up first, in the same change: the recommended architecture, or the one you pass with `--architecture` (Flutter: riverpod, getx, get_it, bloc; Next.js: fetch-helper, plain-fetch; React Native and React web: fetch-helper, axios, axios-react-query; Android: retrofit-hilt, retrofit-koin, retrofit; iOS: urlsession). The base URL comes from `--base-url` or the spec's server. Then the endpoints, screens and tests are written in that architecture, and new dependencies are installed after apply.
282
+
283
+ `auth add` adds sign-in to an existing project. Next.js: an HttpOnly cookie session, server actions, a login page and `middleware.ts` that sends signed-out visitors to `/login`. React Native: tokens in `expo-secure-store` or the Keychain, the token on every request and sign-out on 401, an `AuthProvider` and a login screen. Flutter: `flutter_secure_storage`, a Dio interceptor (with refresh when you pass `--refresh-path`) and a go_router redirect. Android (Hilt): encrypted token storage, an OkHttp interceptor, a login screen and ViewModel. When your network setup has a shape codz does not recognise, it says exactly what to add by hand.
284
+
285
+ ### Screens
286
+
287
+ ```bash
288
+ codz screen add catalog --api getProducts
289
+ codz screen add order-details --api getOrder --path /orders/:id
290
+ ```
291
+
292
+ One change with the route, the page, the call to the endpoint, and the loading, error (with retry) and data states. Path parameters feed the endpoint's arguments by name.
293
+
294
+ - GetX: a module with the endpoint wired into the controller and an `Obx` view.
295
+ - Flutter with Riverpod or get_it: the page loads the endpoint in a `FutureBuilder` (`ref.read(provider)` or `getIt<Repository>()`), with pull to refresh for lists.
296
+ - Flutter with Bloc (`flutter_bloc`): a Cubit next to the page with sealed loading / loaded / failure states, and a page that provides it (`BlocProvider`) and switches on its state (`BlocBuilder`). The API class comes from get_it when the project uses it, otherwise from `context.read` (a `RepositoryProvider` above the page).
297
+ - Next.js: an async server page that awaits the endpoint, plus `loading.tsx` and `error.tsx` next to it.
298
+ - React Native: a screen that loads the endpoint (through its TanStack Query hook when there is one) with `ActivityIndicator`, the error with Retry, and a `FlatList` or the fields; registered in the navigator, or a file under `app/` with Expo Router.
299
+ - Android: a Compose screen and a ViewModel next to it. The ViewModel gets the Retrofit interface from Hilt (`@HiltViewModel`, `hiltViewModel()`), Koin (`viewModelOf(::X)` added to the module, `koinViewModel()`) or the service locator (a `ViewModelProvider.Factory`), reads route parameters from `SavedStateHandle` (converted to `Int` when the method wants one), and exposes `StateFlow<UiState<T>>` (`UiState.kt` with Loading, Success and Error is written once). The screen shows a spinner, the error with Retry, then a `LazyColumn` or the model's fields, and gets a `composable("orders/{id}")` entry in your `NavHost`.
300
+
301
+ Only GET endpoints make a data screen. For POST, PUT and PATCH endpoints, `--form` makes a form instead:
302
+
303
+ ```bash
304
+ codz screen add new-user --api createUser --form
305
+ codz screen add edit-user --api updateUser --path /users/:id/edit --form
306
+ ```
307
+
308
+ One input per field of the request model (text, email, number, checkbox, date, comma-separated list), required fields marked, and submit calling the endpoint with saving, saved and error states. Next.js gets a client page (`'use client'`, path parameters from `useParams`); Flutter gets a `Form` with validators and a `SnackBar` (Riverpod, get_it, Bloc and GetX; in GetX the module's view is the form, with route parameters from `Get.parameters`). React Native gets `TextInput`s and `Switch`es with an `Alert` on the result. Android gets `OutlinedTextField`s (number keyboard for numbers), `Switch`es for booleans and a Save button that calls `viewModel.submit(...)`, with the error shown and an `onDone` callback on success. A required field a form cannot fill, such as a nested object, stops the command with the field named.
309
+
310
+ ### Tests for API functions
311
+
312
+ ```bash
313
+ codz test add getUser # one endpoint
314
+ codz test add --all # every endpoint without a test
315
+ ```
316
+
317
+ Tests that fake the network, so they run offline: Next.js tests (Vitest, or Jest when the project uses it) replace `fetch`, or the axios instance's method, with a spy that answers example data, then check the method, the URL and the result, and that a failed response throws. Flutter tests give Dio a fake `HttpClientAdapter`, check the method, the path and the typed result, and that a 500 throws a `DioException`. React Native tests are Jest. Android tests are JUnit tests on the JVM against OkHttp's `MockWebServer` (`app/src/test/java/.../UserApiTest.kt`): each one enqueues example JSON, calls the method, checks the method, the path and the parsed result, and one test per interface checks that a 500 throws `HttpException`; MockWebServer, kotlinx-coroutines-test and JUnit are added as `testImplementation` when missing. Run them with `./gradlew :app:testDebugUnitTest`. One test file per API file (`users.test.ts` next to it, or `test/.../user_repository_test.dart`); endpoints that already have a test are skipped.
318
+
319
+ ### Custom templates
320
+
321
+ ```bash
322
+ codz templates list # which templates the project customizes
323
+ codz templates init api-function.ts # start one from a file that reproduces codz's output
324
+ ```
325
+
326
+ Templates live in `codz/templates/` (`templatesFolder` in the config); commit them. A template is the text to write with `{{placeholders}}`; `{{default}}` is what codz would have written, so a template can wrap it or replace it.
327
+
328
+ | Template | Shapes | Placeholders |
329
+ | --- | --- | --- |
330
+ | `file-header.ts`, `file-header.dart` | the top of every new file | `{{file}}` |
331
+ | `api-function.ts` | a Next.js API function | `{{default}}`, `{{name}}`, `{{method}}`, `{{path}}`, `{{params}}`, `{{returnType}}` |
332
+ | `api-method.dart` | a Flutter repository or Retrofit method | `{{default}}`, `{{name}}`, `{{method}}`, `{{path}}`, `{{returnType}}` |
333
+ | `model.ts`, `model.dart` | a model | `{{default}}`, `{{name}}` |
334
+
335
+ Whatever a template writes must still be code codz can read back (an exported function, a class method), or later commands will not find it.
336
+
337
+ ### Routes
338
+
339
+ ```bash
340
+ codz route add settings
341
+ codz route add order-details --path /orders/:id
342
+ ```
343
+
344
+ - GetX: a module (same as `module add`).
345
+ - go_router: a page widget next to your other pages and a `GoRoute` (path parameters passed to the page).
346
+ - Navigator: a page and an entry in `MaterialApp(routes: {...})`.
347
+ - Next.js: `app/orders/[id]/page.tsx` (async `params` on Next 15+), or `pages/` for the Pages Router.
348
+ - React Native: a screen registered in the navigator with typed params, or an Expo Router file.
349
+ - Android: a `@Composable` screen taking the parameters as `String`s and a `composable("orders/{id}") { entry -> ... }` entry in the `NavHost`.
350
+
351
+ ### Doctor
352
+
353
+ ```bash
354
+ codz doctor # everything
355
+ codz doctor --only locales # locales, api, urls, models
356
+ codz doctor --strict --json # for CI: exit 1 on warnings too
357
+ ```
358
+
359
+ | Check | Reports |
360
+ | --- | --- |
361
+ | locales | missing keys (error), extra keys, texts identical to the default language, keys that look unused |
362
+ | api | calls with no try/catch, `.catch`, Riverpod `AsyncValue` or `snapshot.hasError`; endpoints without a typed response |
363
+ | urls | hardcoded `http(s)://` addresses outside your config and network setup |
364
+ | models | models nothing uses |
365
+
366
+ Each finding has a file and line and, where there is one, the command that fixes it. The exit code is 1 when there are errors.
367
+
368
+ ```bash
369
+ codz doctor --fix # repair what is safe, as one change: diff, confirm, undo
370
+ codz check # CI gate: config check + doctor; exit 1 on any error or warning
371
+ ```
372
+
373
+ `doctor --fix` adds missing locale keys (with the default language's text, so they still show as untranslated), rewrites hardcoded URLs that start with your base URL (Next.js: `` `${process.env.NEXT_PUBLIC_API_URL}/path` ``; Flutter: a relative path inside Dio calls), and removes models nothing uses (a file left empty is deleted, with its barrel export). Untyped responses and calls without error handling are listed with the fix, because they need a real response or a decision about the error screen.
374
+
375
+ ### Looking around: api list, api show, config, plans
376
+
377
+ ```bash
378
+ codz api list # every endpoint: method, path, function, response, file
379
+ codz api list users # filter by name, path or method
380
+ codz api show getUser # signature, models with fields, every place that uses it
381
+
382
+ codz config # the conventions in use, marking which were detected
383
+ codz config get quote
384
+ codz config set modelsFolder src/types # edits codz.config.yaml in place (diff, undo)
385
+ codz config set baseUrlEnv '' # '' = go back to detecting it
386
+ codz config check # tabs, unknown keys (with "did you mean"), bad values, paths
387
+
388
+ codz plans # saved --plan changes: ready, applied or stale
389
+ codz plans show <id> # the diff again
390
+ codz plans clean # remove applied and stale plans (--all for every plan)
391
+ ```
392
+
393
+ **History.** `codz history` lists applied changes; `codz history show <id>` shows one change's files (and whether each was edited since) with the diff it made; `codz undo --to <id>` undoes every change back to that one, newest first.
394
+
395
+ **Workflow flags** for every command that changes code: `--commit` commits exactly the changed files (`--commit-message "..."`, or a message built from the summary), `--open` opens the diff in `$EDITOR` before asking, and `api add --clipboard` reads the cURL command from the clipboard (pbpaste, wl-paste, xclip or xsel). Every preview starts with a line like `4 files: 2 created, 2 changed (+17 −0 lines)`.
396
+
397
+ `config set` refuses values codz does not understand (for example `quote: backtick`) and paths outside the project. A plan is stale when a file it touches changed since it was made; `codz apply` refuses those, so make the change again.
398
+
399
+ ### Pasting a cURL with its response
400
+
401
+ ```
402
+ curl -X POST 'https://api.example.com/users/42/orders?expand=items' \
403
+ -H 'Authorization: Bearer eyJ...' \
404
+ --data-raw '{"product_id": 7, "qty": 2}'
405
+ response:
406
+ {"data": {"id": 9001, "total_price": 20, "items": [{"sku": "A1", "qty": 2}]}}
407
+ ```
408
+
409
+ codz removes the `Authorization` header (and cookies, API keys, tokens in the query) and never writes them anywhere. It then generates:
410
+
411
+ - the models (`Order`, `OrderItem`, `CreateUserOrderRequest`) in your models folder, in your file naming;
412
+ - `createUserOrder(userId, body, params?)` in the existing `users` API file or repository, through your own request helper when you have one;
413
+ - the registration your project uses (barrel `index.ts` exports, a Riverpod provider, or a get_it registration).
414
+
415
+ ## What it supports
416
+
417
+ | Framework | Supported setup | Not yet |
418
+ | --- | --- | --- |
419
+ | Next.js | App Router, TypeScript, `fetch` directly or through a shared helper (e.g. `apiFetch<T>(path, init)`), axios (an `axios.create` instance, named or default export, or `axios` itself), TanStack Query hooks, path aliases, per-file or single-file models, barrel files | Pages Router, object-style clients (`api.get(...)` wrappers around fetch), SWR |
420
+ | Flutter | Dio from repository/service classes or Retrofit (`@RestApi`) clients; hand-written `fromJson`/`toJson` (factory or plain constructor), json_serializable or freezed (2 and 3); GetX bindings, Riverpod or get_it; Cubit screens in Bloc projects; go_router/auto_route routes; ARB locales or GetX Translations | `http` package, Chopper, full `Bloc` (events) screens |
421
+ | React Native | Expo and bare React Native CLI projects, TypeScript; `fetch` through a shared helper or an axios instance, TanStack Query hooks; React Navigation (native stack) or Expo Router; API URL in a config file | Redux Toolkit Query, plain JavaScript projects |
422
+ | React (web) | Vite or Create React App, TypeScript; `fetch` through a shared helper or an axios instance, TanStack Query hooks; React Router (`<Routes>` or `createBrowserRouter`); API URL from `VITE_API_URL` / `REACT_APP_API_URL` | `auth add`, Next.js-style server components (use the Next.js adapter) |
423
+ | Android | Kotlin app module; Retrofit with `suspend` functions; kotlinx.serialization, Moshi or Gson data classes; Hilt, Koin or a service locator object; screens in Jetpack Compose (Navigation Compose) or XML Views (an Activity, a layout and a ViewModel per screen, registered in the manifest); version catalog or direct Gradle Kotlin DSL dependencies | Ktor, Java sources, Fragments, `mock add` |
424
+ | iOS | Swift with SwiftUI: an `APIClient` over URLSession with async/await, `Codable` structs, SwiftUI views with `ObservableObject` view models, `NavigationLink` navigation; Xcode 16 synchronized folders (older projects: codz lists the files to add to the target) | UIKit screens, Alamofire, `test add`, `mock add`, `auth add` |
425
+ | Anything else | Generic adapter: structure, locale files and `.env` base URLs in `explain` | `api add`, `theme`, `route` |
426
+
427
+ When something is outside the supported setup, codz says so before doing anything rather than generating the wrong style.
428
+
429
+ ## How it decides what to write
430
+
431
+ - **Conventions** (folders, naming, quotes, semicolons, helper, DI, imports) are detected on `init` and saved to `codz.config.yaml`. Correct anything wrong once and commit the file; codz uses your values from then on.
432
+ - **The project map** is a cache in `.codz/` (git-ignored). It is rebuilt automatically when files change, so hand edits never leave it stale.
433
+ - **Model inference** follows fixed rules: several `--sample`s are merged; a field missing or null in any sample is nullable; money-like names (`price`, `amount`, `lat`, ...) become doubles; ISO strings become dates; enums are never guessed; a field that is only ever `null`, or a list that is only ever empty, is marked unknown with a warning instead of a guess; `{"data": ...}` envelopes are unwrapped (`--no-unwrap` to keep them).
434
+ - **Existing models** with the same name and fields are reused. A different model with the same name stops the run (`--model-name` to choose another name); nested clashes get a prefixed name.
435
+ - **Base URLs**: when the URL's host matches a configured base URL (`.env` for Next.js, Dio's `baseUrl` for Flutter), only the path is written, minus any prefix like `/v1`.
436
+
437
+ ## Safety
438
+
439
+ - A diff before every write; `--dry-run` and `--plan` never write.
440
+ - Refuses to apply over uncommitted git changes unless `--allow-dirty`.
441
+ - Checks that every target file is unchanged since the preview; otherwise nothing is applied.
442
+ - Writes all files to temporary names first and swaps them in together; any failure restores everything.
443
+ - Runs your formatter (Prettier, `dart format`) and analyzer (`tsc`, `dart analyze`) when installed. If the analyzer reports a new error in a changed file, the change is reverted (`--no-verify` to skip).
444
+ - `codz undo` restores from backups in `.codz/backups/`, and refuses (without `--force`) if you edited the files since.
445
+ - Never edits outside the project root or inside `.codz/`. No network access, no telemetry.
446
+
447
+ ## For scripts and AI agents
448
+
449
+ Every command accepts `--json` and prints one JSON object: `{"ok": true, ...}` or `{"ok": false, "error": {"code", "message", "hint"}}`. A typical agent flow:
450
+
451
+ ```bash
452
+ codz explain --json # learn the project
453
+ codz api add --curl "..." --plan --json # get the diff and a plan id
454
+ codz apply <plan-id> --json # apply exactly what was shown
455
+ ```
456
+
457
+ ### MCP server
458
+
459
+ ```bash
460
+ codz mcp # in the project folder (or: codz mcp --cwd /path/to/project)
461
+ ```
462
+
463
+ `codz mcp` serves codz over the Model Context Protocol on stdio, for AI agents and editors that support MCP. Every command becomes a tool (`api add` → `api_add`, `api sync` → `api_sync`, `doctor`, ...), with a JSON schema built from its options. Tools that edit code never write: they return the diff and a `planId`, and the `apply` tool applies that plan exactly as shown. Two resources: `codz://project` (what codz knows about the project) and `codz://commands` (every command and option).
464
+
465
+ To add it to an MCP client, register a stdio server whose command is `codz` with the arguments `["mcp", "--cwd", "/path/to/project"]`. Many clients take a JSON entry like:
466
+
467
+ ```json
468
+ { "mcpServers": { "codz": { "command": "codz", "args": ["mcp", "--cwd", "/path/to/project"] } } }
469
+ ```
470
+
471
+ ### VS Code extension
472
+
473
+ `extensions/vscode` runs codz from the command palette: add an endpoint from a cURL command or URL, sync with a spec, show an endpoint and jump to its uses, rename, mock and test every endpoint, doctor findings in the Problems panel, undo. Every change opens as a diff first and is applied only when you click Apply. Package it with `npx @vscode/vsce package` in that folder and install the `.vsix`; see its README.
474
+
475
+ ## Beta testers
476
+
477
+ See [BETA.md](BETA.md): install, the first 10 minutes, what is stable, and how to send feedback with `codz report`.
478
+
479
+ ## Development
480
+
481
+ ```bash
482
+ npm test # unit, golden and CLI integration tests (node:test)
483
+ npm run test:update-golden # accept intended changes to generated output
484
+ npm run typecheck # needs: npm i -D typescript @types/node
485
+ ./scripts/check-generated.sh # compile generated code with real SDKs (Flutter + tsc), pages (.tsx) included
486
+ node scripts/starters.ts check starters/*/ # starter publishing gates (manifest, hashes, secrets, determinism)
487
+ ./scripts/check-android.sh # create an Android project per architecture, run a session, then Gradle assembleDebug + unit tests (needs the Android SDK)
488
+ ./scripts/corpus.sh # run codz (read-only, --dry-run) on the public projects in scripts/corpus.txt
489
+ npm run docs # regenerate docs/COMMANDS.md from the command table
490
+ npm run check:all # beta build check: feature/auth/screen add on every platform, then real builds (tsc, vitest, dart analyze, Gradle, swiftc)
491
+ npm run beta:pack # tests + dist/ + release/codz-cli-<version>.tgz, checked by installing it in a clean folder
492
+ FUZZ_RUNS=5000 FUZZ_SEED=3 node --test test/fuzz.test.ts # fuzz the parsers harder
493
+ ```
494
+
495
+ Every command and option is defined once, in `src/core/commands.ts`: `--help`, `codz <command> --help`, shell completion, the option parser and [docs/COMMANDS.md](docs/COMMANDS.md) are generated from it, and a test fails if the CLI handles a command or reads an option the table does not list. A mistyped option (`--dryrun`) is an error with a suggestion, never silently ignored.
496
+
497
+ CI (`.github/workflows/ci.yml`) runs the tests and the typecheck on Linux, macOS and Windows, fuzzes the parsers, checks that docs/COMMANDS.md is current for every push and pull request, and runs `check-generated.sh` with Flutter installed, so the Dart output is analyzed too: on the fixtures and on a project made by `flutter create`. An `android` job runs `check-android.sh` with Java 17, Gradle and the runner's Android SDK, so the Kotlin that codz writes (setup, endpoints, screens, forms, routes, tests, theme) is compiled and its generated tests run. `.github/workflows/corpus.yml` runs the corpus check weekly; a crash or a timeout on any project fails it.
498
+
499
+ Layout:
500
+
501
+ ```
502
+ bin/codz.js entry point
503
+ src/cli.ts commands and flags
504
+ src/core/ types, cache, config and YAML reader, JSON editing, diff, change sets, git
505
+ src/input/ cURL, paste, OpenAPI/Swagger/Postman parsing, naming, model inference
506
+ src/core/commands.ts the command and option table (help, completion, parser, docs, MCP tools)
507
+ src/skills/mcp.ts codz mcp: the Model Context Protocol server
508
+ src/starters/ codz new and the starter catalog (the only network code; loaded on demand)
509
+ starters/ the internal starter templates; scripts/starters.ts publishes them
510
+ extensions/vscode/ the VS Code extension
511
+ dist/ compiled output for the npm package (npm run build; not committed)
512
+ src/adapters/ nextjs (+ Scan, Gen, Setup), flutter (+ Scan, Gen, Styles, Setup), reactNative (+ Setup),
513
+ android (+ Setup, kotlinGen), getx, dartGen, reactQuery, generic
514
+ src/skills/ init, setup, explain, api add/import/update/remove/rename, module add,
515
+ api wire, mock, locale, theme, route, screen, test, doctor, create
516
+ (+ androidSkeleton, androidUi, androidTests, reactNativeUi)
517
+ fixtures/ sample projects used by the tests (two of them fresh)
518
+ test/golden/ expected output for every fixture scenario
519
+ ```
520
+
521
+ ## Known limits
522
+
523
+ - Scanning uses careful text parsing (brace- and string-aware). `api rename`/`api remove` use the TypeScript compiler when the project has it; everything else, and all Dart code, uses the text scanner. It is checked against the fixtures and, weekly, against real public projects (`scripts/corpus.txt`); please report a scan that maps something wrong.
524
+ - Next.js output was compiled with `tsc --strict` during development. Flutter output was reviewed but not compiled, because the Dart SDK was not available in the build environment. Run `./scripts/check-generated.sh` on a machine with Flutter to check it. The same goes for Kotlin: neither the Android SDK nor the Maven repositories were reachable while it was built, so Android output is checked by the CI `android` job (`./scripts/check-android.sh`), not by the local test run.
525
+ - `doctor` uses the same text scanning, so its "unused" and "no error handling" findings are hints to check, not proof. Keys looked up dynamically (``t(`x.${y}`)``) cannot be traced.
526
+ - The VS Code extension has unit tests for its logic but has not been run in VS Code by these tests; try it with "Run Extension" from that folder before packaging it.
@@ -0,0 +1,2 @@
1
+ Gradle wrapper files (Apache License 2.0, from Gradle 8.11.1), copied into Android projects
2
+ codz creates when Gradle is not installed. The wrapper downloads Gradle itself on first run.