create-mobile 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/README.md +76 -0
- package/bin/create-mobile.mjs +111 -0
- package/package.json +51 -0
package/README.md
ADDED
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
# create-mobile
|
|
2
|
+
|
|
3
|
+
> **The honest front door to a new mobile app.** `npm create mobile` doesn't silently
|
|
4
|
+
> pick a framework for you — it opens with Kotlin/Compose Multiplatform as the modern
|
|
5
|
+
> default, states the real trade-offs vs React Native and Flutter, and lets you choose.
|
|
6
|
+
> Continue, and it scaffolds a green-building Android + iOS app via
|
|
7
|
+
> [`create-cmp-cli`](https://www.npmjs.com/package/create-cmp-cli).
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npm create mobile@latest my-app
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Why this package exists — a fit check, not a redirect
|
|
14
|
+
|
|
15
|
+
"mobile" is framework-neutral, so a package under that name that quietly stamped one
|
|
16
|
+
stack would be a bait-and-switch. This one is built to earn the generic name. Launch it
|
|
17
|
+
and it opens with an honest positioning:
|
|
18
|
+
|
|
19
|
+
> Here's Compose Multiplatform as the modern default — one statically-typed codebase,
|
|
20
|
+
> real native Android + iOS UI, Google-backed, iOS stable since May 2025 — and here are
|
|
21
|
+
> the real trade-offs vs React Native/Flutter (bigger RN/Flutter ecosystems and hiring
|
|
22
|
+
> pools; a JS bridge or Dart's non-native render layer; CMP is the youngest of the three).
|
|
23
|
+
> **You choose.**
|
|
24
|
+
|
|
25
|
+
That's the same step-0 fit check the create-cmp Claude Code plugin's `cmp-new` skill runs,
|
|
26
|
+
brought to the command line. The generic name raises the honesty bar; this is how it's
|
|
27
|
+
cleared — you become the honest front door to mobile, not a redirect. The full sourced case
|
|
28
|
+
for choosing CMP (with its weaknesses named, not just its strengths) is
|
|
29
|
+
[docs/WHY-CMP.md](https://github.com/kvdm-co-pilot/create-cmp/blob/main/docs/WHY-CMP.md).
|
|
30
|
+
|
|
31
|
+
- **Interactive run:** you get the positioning **and a real prompt** —
|
|
32
|
+
`Continue with Compose Multiplatform? [Y/n]`. Decline and nothing is written; it points
|
|
33
|
+
you at `npm create expo` (React Native) or `flutter create` and exits cleanly.
|
|
34
|
+
- **Scripts / CI / agents (`--yes` or piped):** you've already chosen by how you invoked
|
|
35
|
+
it, so it prints the honest note and proceeds — no blocking prompt.
|
|
36
|
+
- **`--help` / `--version`:** pass straight through to the real CLI.
|
|
37
|
+
|
|
38
|
+
## What you get if you continue
|
|
39
|
+
|
|
40
|
+
One command stamps a **frozen, CI-verified template** — deterministic output, never
|
|
41
|
+
LLM-freehanded project code:
|
|
42
|
+
|
|
43
|
+
- Android + iOS shells (XcodeGen + CocoaPods pre-wired), Clean Architecture with a worked
|
|
44
|
+
example feature, Koin DI, bottom navigation with insets solved.
|
|
45
|
+
- A **proven-green version set** (Kotlin/KSP/Compose/Room/AGP pinned to a combination that
|
|
46
|
+
actually builds together — including the iOS/KSP2 path).
|
|
47
|
+
- Optional features by flag: Firebase (GitLive) with auth, Room, Maestro on-device E2E, a
|
|
48
|
+
live UI inspector, a desktop hot-reload dev client. `--verify` builds the app before
|
|
49
|
+
reporting success; the CLI exits non-zero on failure.
|
|
50
|
+
- The **delivery harness** in every generated project: specs with stable clause ids, an
|
|
51
|
+
8-gate verify lane (`node qa/verify.mjs`), evidence receipts bound to a content hash, a
|
|
52
|
+
device-free preview loop so coding agents see what they build, and CI that refuses "done"
|
|
53
|
+
without proof. See it working in the
|
|
54
|
+
[public showcase repo](https://github.com/kvdm-co-pilot/create-cmp-showcase) — including
|
|
55
|
+
[a PR the harness refuses](https://github.com/kvdm-co-pilot/create-cmp-showcase/pull/1).
|
|
56
|
+
|
|
57
|
+
## About this package
|
|
58
|
+
|
|
59
|
+
An **official alias** for `create-cmp-cli`, published by the same maintainer so the
|
|
60
|
+
conventional `npm create mobile` invocation works. It adds exactly one thing of its own —
|
|
61
|
+
the honest fit check above — then delegates to the installed `create-cmp-cli`, forwarding
|
|
62
|
+
all arguments, stdio, and the exit code. After the choice, either name runs the same tool
|
|
63
|
+
with the same flags.
|
|
64
|
+
|
|
65
|
+
Fully non-interactive (scripts and AI agents):
|
|
66
|
+
|
|
67
|
+
```bash
|
|
68
|
+
npx create-mobile my-app --name Acme --package com.acme.app --yes --verify
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
## Docs
|
|
72
|
+
|
|
73
|
+
- Repository, full README and issues: <https://github.com/kvdm-co-pilot/create-cmp>
|
|
74
|
+
- Why Compose Multiplatform (sourced, honest): [docs/WHY-CMP.md](https://github.com/kvdm-co-pilot/create-cmp/blob/main/docs/WHY-CMP.md)
|
|
75
|
+
- Every flag: [options.schema.json](https://github.com/kvdm-co-pilot/create-cmp/blob/main/options.schema.json) or `npx create-mobile --help`
|
|
76
|
+
- Usage guide (commands, skills, workflows): [docs/USAGE.md](https://github.com/kvdm-co-pilot/create-cmp/blob/main/docs/USAGE.md)
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// create-mobile — the honest front door to a new mobile app.
|
|
3
|
+
//
|
|
4
|
+
// The other create-cmp aliases (create-kmp, create-compose-multiplatform) are pure
|
|
5
|
+
// pass-throughs: their name already names the framework, so they just re-exec
|
|
6
|
+
// create-cmp-cli. This one is deliberately NOT a silent pass-through. "mobile" is
|
|
7
|
+
// framework-neutral, so a package that quietly scaffolds Compose Multiplatform under
|
|
8
|
+
// that name would be a bait-and-switch. Instead it opens with an HONEST fit check —
|
|
9
|
+
// CMP as the modern default, the real trade-offs vs React Native / Flutter, and a
|
|
10
|
+
// genuine choice — and only then delegates to create-cmp-cli. The generic name
|
|
11
|
+
// raises the honesty bar; this is how it's earned (the CLI analogue of the cmp-new
|
|
12
|
+
// skill's step-0 fit check). Everything after the choice is create-cmp-cli, verbatim.
|
|
13
|
+
|
|
14
|
+
import { createRequire } from "node:module";
|
|
15
|
+
import { dirname, join } from "node:path";
|
|
16
|
+
import { spawnSync } from "node:child_process";
|
|
17
|
+
import { stdin, stdout } from "node:process";
|
|
18
|
+
|
|
19
|
+
const require = createRequire(import.meta.url);
|
|
20
|
+
const argv = process.argv.slice(2);
|
|
21
|
+
|
|
22
|
+
// --help / --version: pure info passthrough — no banner, no prompt.
|
|
23
|
+
const INFO = new Set(["--help", "-h", "--version", "-v"]);
|
|
24
|
+
const infoOnly = argv.some((a) => INFO.has(a));
|
|
25
|
+
|
|
26
|
+
function resolveCliPath() {
|
|
27
|
+
let pkgJsonPath;
|
|
28
|
+
try {
|
|
29
|
+
// package.json is always resolvable, even behind an "exports" map.
|
|
30
|
+
pkgJsonPath = require.resolve("create-cmp-cli/package.json");
|
|
31
|
+
} catch {
|
|
32
|
+
process.stderr.write(
|
|
33
|
+
"create-mobile: could not find its dependency create-cmp-cli.\n" +
|
|
34
|
+
"Your install may be broken — reinstall, or run the real CLI directly:\n\n" +
|
|
35
|
+
" npx create-cmp-cli@latest\n",
|
|
36
|
+
);
|
|
37
|
+
process.exit(1);
|
|
38
|
+
}
|
|
39
|
+
const pkg = require(pkgJsonPath);
|
|
40
|
+
const bin = pkg.bin;
|
|
41
|
+
const relBinPath = typeof bin === "string" ? bin : (bin["create-cmp"] ?? Object.values(bin)[0]);
|
|
42
|
+
if (!relBinPath) {
|
|
43
|
+
process.stderr.write(
|
|
44
|
+
"create-mobile: create-cmp-cli declares no bin entry.\n" +
|
|
45
|
+
"Run the real CLI directly instead: npx create-cmp-cli@latest\n",
|
|
46
|
+
);
|
|
47
|
+
process.exit(1);
|
|
48
|
+
}
|
|
49
|
+
return join(dirname(pkgJsonPath), relBinPath);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// Re-exec create-cmp-cli: block until it finishes, inherit stdio so interactive
|
|
53
|
+
// prompts keep working, propagate the exit code. Never returns (calls process.exit).
|
|
54
|
+
function delegate() {
|
|
55
|
+
const cliPath = resolveCliPath();
|
|
56
|
+
const result = spawnSync(process.execPath, [cliPath, ...argv], { stdio: "inherit" });
|
|
57
|
+
if (result.error) {
|
|
58
|
+
process.stderr.write(`create-mobile: failed to launch create-cmp-cli: ${result.error.message}\n`);
|
|
59
|
+
process.exit(1);
|
|
60
|
+
}
|
|
61
|
+
if (result.signal) process.kill(process.pid, result.signal);
|
|
62
|
+
process.exit(result.status ?? 1);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
if (infoOnly) delegate(); // exits
|
|
66
|
+
|
|
67
|
+
// The honest positioning. To stderr so a piped stdout stays clean; both stream to
|
|
68
|
+
// the terminal in an interactive run, so the user always sees it.
|
|
69
|
+
const banner = [
|
|
70
|
+
"",
|
|
71
|
+
" create-mobile — the honest front door to a new mobile app.",
|
|
72
|
+
"",
|
|
73
|
+
" Recommended default: Kotlin / Compose Multiplatform (KMP)",
|
|
74
|
+
" - one statically-typed codebase, REAL native Android + iOS UI, no JS bridge",
|
|
75
|
+
" - Google-backed; Compose for iOS stable since May 2025",
|
|
76
|
+
"",
|
|
77
|
+
" The real trade-offs — know these before you choose:",
|
|
78
|
+
" - React Native / Expo: bigger ecosystem, more libraries and hiring pool,",
|
|
79
|
+
" but a JS<->native bridge and two languages at the edges",
|
|
80
|
+
" - Flutter: mature tooling and widgets, but Dart and a non-native render layer",
|
|
81
|
+
" - CMP is the youngest of the three: smaller community, newer iOS story",
|
|
82
|
+
"",
|
|
83
|
+
" Full sourced case: https://github.com/kvdm-co-pilot/create-cmp/blob/main/docs/WHY-CMP.md",
|
|
84
|
+
"",
|
|
85
|
+
].join("\n");
|
|
86
|
+
|
|
87
|
+
process.stderr.write(banner + "\n");
|
|
88
|
+
|
|
89
|
+
// Flags-driven / --yes / no TTY => the caller already chose by how they invoked it
|
|
90
|
+
// (scripts, CI, an agent passing flags). Print the banner and proceed. A real
|
|
91
|
+
// interactive run gets a real choice.
|
|
92
|
+
const nonInteractive = argv.includes("--yes") || argv.includes("-y") || !stdin.isTTY || !stdout.isTTY;
|
|
93
|
+
|
|
94
|
+
if (nonInteractive) {
|
|
95
|
+
delegate(); // exits
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
const { createInterface } = await import("node:readline/promises");
|
|
99
|
+
const rl = createInterface({ input: stdin, output: stdout });
|
|
100
|
+
const answer = (await rl.question(" Continue with Compose Multiplatform? [Y/n] ")).trim().toLowerCase();
|
|
101
|
+
rl.close();
|
|
102
|
+
|
|
103
|
+
if (answer === "" || answer === "y" || answer === "yes") {
|
|
104
|
+
delegate(); // exits
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
process.stdout.write(
|
|
108
|
+
"\n No problem — nothing was written.\n" +
|
|
109
|
+
" Prefer another stack? React Native: npm create expo@latest · Flutter: flutter create my_app\n\n",
|
|
110
|
+
);
|
|
111
|
+
process.exit(0);
|
package/package.json
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "create-mobile",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "The honest front door to a new mobile app. `npm create mobile` recommends Kotlin/Compose Multiplatform as the modern default, states the real trade-offs vs React Native/Flutter, and lets you choose — then, if you continue, scaffolds a green-building Android + iOS app (one Kotlin codebase) with a machine-enforced verify lane and evidence receipts. Official alias for create-cmp-cli; not a redirect — a fit check first.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"bin": {
|
|
7
|
+
"create-mobile": "bin/create-mobile.mjs"
|
|
8
|
+
},
|
|
9
|
+
"engines": {
|
|
10
|
+
"node": ">=18"
|
|
11
|
+
},
|
|
12
|
+
"files": [
|
|
13
|
+
"bin"
|
|
14
|
+
],
|
|
15
|
+
"keywords": [
|
|
16
|
+
"mobile app",
|
|
17
|
+
"create mobile app",
|
|
18
|
+
"new mobile app",
|
|
19
|
+
"cross-platform",
|
|
20
|
+
"app generator",
|
|
21
|
+
"react native alternative",
|
|
22
|
+
"flutter alternative",
|
|
23
|
+
"android",
|
|
24
|
+
"ios",
|
|
25
|
+
"compose-multiplatform",
|
|
26
|
+
"kotlin-multiplatform",
|
|
27
|
+
"kmp",
|
|
28
|
+
"cmp",
|
|
29
|
+
"scaffold",
|
|
30
|
+
"project-generator",
|
|
31
|
+
"claude-code",
|
|
32
|
+
"ai-agent"
|
|
33
|
+
],
|
|
34
|
+
"license": "MIT",
|
|
35
|
+
"author": "Karel van der Merwe",
|
|
36
|
+
"homepage": "https://github.com/kvdm-co-pilot/create-cmp#readme",
|
|
37
|
+
"repository": {
|
|
38
|
+
"type": "git",
|
|
39
|
+
"url": "git+https://github.com/kvdm-co-pilot/create-cmp.git",
|
|
40
|
+
"directory": "packages/aliases/create-mobile"
|
|
41
|
+
},
|
|
42
|
+
"bugs": {
|
|
43
|
+
"url": "https://github.com/kvdm-co-pilot/create-cmp/issues"
|
|
44
|
+
},
|
|
45
|
+
"publishConfig": {
|
|
46
|
+
"access": "public"
|
|
47
|
+
},
|
|
48
|
+
"dependencies": {
|
|
49
|
+
"create-cmp-cli": ">=0.7.1"
|
|
50
|
+
}
|
|
51
|
+
}
|