npm install
npm run openloop -- initRegister projects you want OpenLoop to track:
npm run openloop -- project:add --path . --name LarryLoopStart the local website:
npm run devThe dashboard opens at the printed local URL, usually http://127.0.0.1:5173.
It lists registered projects, campaign runs, workflow type, asset status, preview links, and captions when a workflow has them.
Run the full default pipeline:
openloop slides --project /path/to/project --name first-campaignThe run is written to .openloop/campaign/first-campaign/. If that folder already exists,
OpenLoop appends a timestamp to avoid overwriting it.
slides creates the social carousel workflow and exports 9:16 PNGs by default.
The default planner is codex, which reads the scanned product evidence and creates product-specific module files.
Use a direct command when the output is not a social slide set:
openloop app-store --project /path/to/app --name app-store-set --screenshots /path/to/real-screenshots
openloop app-ads --project /path/to/app --name launch-ad --screenshots /path/to/real-screenshotsWorkflow defaults:
social-carousel: six 9:16 assets, local text overlay, shared caption.app-store-screenshot: five App Store assets generated from real app screenshots, local text overlay, no caption required. It also tries to fetch before.click references for style inspiration without adding a CLI flag. It exports iPhone 6.9", iPhone 6.5", iPad 13", and iPad 12.9" target folders.app-ads: twelve portrait 2:3 single-shot scratch references with chroma-green phone screen cards, no local overlay, no caption required. Seedance prompts attach one clean video reference at a time; exact app screenshots are composited after generation to avoid hallucinated UI text/language drift.
Landing image generation is disabled for now.
Before asking Codex to capture screenshots for a target app, prepare that app with the repo skill:
Use $develop-screenshot-mode to inspect QuickShift and add screenshot mode only if it is missing.
The skill lives at:
.agents/skills/develop-screenshot-mode/
Expected app-side contract:
SCREENSHOT_MODE=1
SCREENSHOT_SCENE=store-hook|main-use-case|key-feature|user-outcome|install-cta
Expected readiness markers:
screenshot-ready-store-hook
screenshot-ready-main-use-case
screenshot-ready-key-feature
screenshot-ready-user-outcome
screenshot-ready-install-cta
Use this flow when automating source capture:
OpenLoop decides screenshot set
-> Codex receives capture prompt
-> Codex uses XcodeBuildMCP on the target iOS app
-> Codex writes slide-01.png ... slide-05.png
-> OpenLoop consumes that folder with app-store workflow
Use the old deterministic template only for offline/debug runs:
openloop slides --project /path/to/project --name first-campaign --planner localIf image generation fails midway, resume the same run. Existing raw images are skipped by default:
openloop run:resume --run .openloop/campaign/<generated-run>Force image regeneration when needed:
openloop generate:images --run .openloop/campaign/<generated-run> --forceOpenLoop still keeps each step as a separate command for debugging or manual edits:
npm run openloop -- scan --project /path/to/project --name first-campaign
npm run openloop -- generate:ideas --run .openloop/campaign/<generated-run> --planner codexReview and edit these files before image generation if needed:
shared/meta/brief.jsonmodules/<module>/meta/ideas.jsonmodules/<module>/meta/slides.json
shared/meta/brief.json includes safe source snippets from product docs, landing copy, App Store copy, and code signals. Sensitive names such as env, secret, token, and credential files are skipped.
Fresh login:
npm run openloop -- auth:login codexImport existing Codex CLI credentials into OpenLoop's own auth store:
npm run openloop -- auth:login codex --import-codexOpenLoop stores credentials at ~/.openloop/auth.json.
To switch accounts:
openloop auth:logout
openloop auth:login codexTo copy the currently logged-in Codex CLI account into OpenLoop:
openloop auth:login codex --import-codexnpm run openloop -- generate:images --run .openloop/campaign/<generated-run>This creates raw images for the run workflow:
modules/<module>/raw/images/slide-01.png
...
modules/<module>/raw/images/slide-XX.png
For App Store runs, add real screenshots before image generation:
shared/source/app-screenshots/slide-01.png
shared/source/app-screenshots/slide-02.png
...
shared/source/app-screenshots/slide-05.png
You can also set sourceImagePath per asset in slides.json. The backend uses those real images as source truth and will not invent app UI.
For App Store runs, OpenLoop also attempts a before.click inspiration pass before planning. If available, it writes:
modules/app-store-screenshots/references/before-click/manifest.json
modules/app-store-screenshots/meta/style-brief.json
These references are style-only. The planner and image model may use them for composition, background, device treatment, color rhythm, and hierarchy, but final exports must preserve the real source screenshot as the only app UI.
For App Ads runs, pass the same real screenshots folder:
openloop app-ads --project /path/to/app --name launch-ad --screenshots /path/to/real-screenshotsOpenLoop copies up to five screenshots into shared/source/app-screenshots/ and writes shared/source/app-screenshots/contact-sheet.png. App-ad generation keeps those screenshots for post-production only, then creates twelve single-shot video references with a chroma-green phone screen plane. During render, OpenLoop writes model-ready prompts beside each video reference.
For Seedance 2.0, attach one file from modules/app-ads/export/video-references/images/ at a time and paste its matching prompt from modules/app-ads/export/video-references/prompts/. Do not attach all twelve references in one run, and do not attach shared/source/app-screenshots/contact-sheet.png. Generate 2-4 second green-screen phone plates, then overlay exact source app screenshots in post-production. This avoids hallucinated labels, translated text, and changed UI.
If you run openloop app-store without --screenshots, OpenLoop stops after writing the plan and prints the run path. Add real screenshots to that run, then resume:
openloop run:resume --run .openloop/campaign/<generated-run>npm run openloop -- render --run .openloop/campaign/<generated-run>
npm run openloop -- validate --run .openloop/campaign/<generated-run>Final upload assets:
modules/<module>/export/slides/slide-01.png
...
modules/<module>/export/slides/slide-XX.png
modules/social-slides/export/caption.txt # social-carousel only
modules/<module>/review/preview.html
App Store screenshot workflow also writes target-specific folders:
modules/app-store-screenshots/export/app-store/iphone-6-9/slide-01.png # 1320x2868
modules/app-store-screenshots/export/app-store/iphone-6-5/slide-01.png # 1284x2778
modules/app-store-screenshots/export/app-store/ipad-13/slide-01.png # 2064x2752
modules/app-store-screenshots/export/app-store/ipad-12-9/slide-01.png # 2048x2732
Use the same exported social carousel slides and caption for TikTok or Instagram first.
App Ads workflow also writes:
modules/app-ads/export/video-prompts/kling.md
modules/app-ads/export/video-prompts/seedance.md
modules/app-ads/export/video-prompts/model-agent.md
modules/app-ads/export/video-references/images/slide-01.png
modules/app-ads/export/video-references/prompts/slide-01-seedance.md
modules/app-ads/export/video-references/prompts/slide-01-kling.md
modules/app-ads/export/video-references/prompts/slide-01-agent.md
modules/app-ads/export/video-references/images/slide-02.png
modules/app-ads/export/video-references/prompts/slide-02-seedance.md
modules/app-ads/export/video-references/prompts/slide-02-kling.md
modules/app-ads/export/video-references/prompts/slide-02-agent.md
shared/source/app-screenshots/contact-sheet.png