feat(e2e): start a project from an example app with e2e init --example
Merged
KA
6d ago+788+788+012345678901234567890123456789-24-24-01234567890123456789
e2e init my-app --example with-expo copies one of the apps under examples/ into a new or empty directory. It then runs the usual skill, MCP, and install steps in the example's e2e project.
npx e2e init my-app --example with-flutter # "flutter" works too
flowchart LR
A[--example] --> B{dir empty?}
B -- no --> X[exit 2, nothing downloaded]
B -- yes --> C[codeload tarball at e2e@version]
C -- 404 --> D[fall back to main, warn]
C --> E[stream, extract examples/name, stop past it]
D --> E
E --> F[package.json: dir name + this CLI's e2e/@e2e-dev ranges]
F --> G[wizard in root or e2e/: skill, MCP, .gitignore, install]
G -- cancel / Ctrl-C --> R[remove the copy]
packages/e2e/src/cli/init/examples.ts: the example list, a streaming download fromcodeload.github.com/tester-army/e2e, and a small tar reader. The tar reader handles ustar prefixes, paxpath, and GNU long names. It refuses..paths, never writes links, and keeps the executable bit, sogradlewstill runs.- The tag matches the running CLI, so the example code matches the runner. Example pins are bumped by hand and trail releases:
with-viteate2e@0.21.2pinse2e ^0.15.2. The copy rewritese2eand the recorded@e2e-dev/*ranges to whatinitwrites for a new project. - The example's config, tests, and scripts stay as they are. No
tests/example.e2e.tsand notest:e2escript get added. For native apps (SwiftUI, Compose, KMP, Flutter, MAUI) the wizard runs ine2e/, so the skill and MCP files land there. The docs say to open the agent in that folder. - The download has a 30 s idle limit, not a total one, because the tarball is the whole repo (about 28 MB gzipped before
examples/). Ctrl-C during the download goes through the clack spinner'sonCancel, removes the partial copy, and exits 130. --examplewith--engine,--gateway, or--endpointis a usage error (exit 2).with-limrunisn't offered, since it reuses the SwiftUI and Compose apps.tests/unit/init-examples.test.tsfails if the list andexamples/drift apart, or if a listed script is missing.- Telemetry:
e2e_init_completedgetsexample(the folder name ornull) and a newexample-failedresult. Both are documented indocs/telemetry.mdx. - Docs: a "Starting from an example" section and flag row in
docs/reference/cli.mdx, plusskills/e2e/references/setup.mdandexamples/README.md.
Verified
Ran it locally: yes. Scratch directory, built CLI (packages/e2e/dist/cli/bin.js), real GitHub.
init vite-app --example vite --yes --install, thennpm run test:e2ein the copy:
The agent tests skip without✓ target "web" command ready 659ms ↓ |web| tests/agentic.e2e.ts (2 tests | 2 skipped) ✓ |web| tests/deterministic.e2e.ts (3 tests) 940msAI_GATEWAY_API_KEY. Before the range rewrite, the same run installede2e@0.15.2and failed withCONFIG_LOAD_FAILED.init flutter-app --example flutter --yes: about 2.4 s end to end. The skill and MCP files land influtter-app/e2e/, and the run ends withNext: cd flutter-app/e2e, then npm install, then build and install the app as ../README.md describes, then npm run test:e2e:android.init compose --example with-compose, diffed againstgit archive e2e@0.21.2 examples/with-compose: identical excepte2e/package.jsonname.gradlewis-rwxr-xr-x.init expo-app --example expo:package.jsondiff against the tag is the name pluse2e ^0.16.0 → ^0.21.2,@e2e-dev/web ^0.11.1 → ^0.15.2,@e2e-dev/mobile ^0.9.0 → ^0.12.3.kill -INT0.6 s into a download:■ Canceled,Cancelled; no changes were made, exit 130, and no directory left.- Each of these exits 2 before downloading anything:
--example svelte: the error lists the valid names.--example expo --engine web:drop --engine.- A non-empty directory:
is not empty; --example needs a new or empty directory.
Not verified: building and running a native example (Flutter, SwiftUI, and the others) on a device after copying. The copy is byte-identical to the tag apart from package.json, and the nightly examples workflow already covers those apps.