Skip to content
LazyFrog

Working from a checkout

How to work on a LazyFrog project from your own computer with Claude Code: clone it, change it locally, and git push to update the preview.

When the user works on a copy of the code with Claude Code or Codex (on their own machine or in their AI's cloud session), the preview stays the source of truth: it is what runs, what other people's AIs work on and what a publish takes. Work in the checkout; push to update the preview; use the LazyFrog tools to look (logs, database, screenshots) and to publish. The preview and the repository are one history.

  • The code and the tools. git clone https://git.lazyfrog.dev/<project>.git: git asks for a user name (anything) and a password, a personal token the user makes in the portal (Account › Access tokens, "Read and write" to push; you can't make one, and only the project's owner and editors can push). New projects carry .mcp.json, which Claude Code reads (it asks once, then connects LazyFrog's tools), and CLAUDE.md and AGENTS.md with these rules in short. Codex: codex mcp add lazyfrog --url https://mcp.lazyfrog.dev/mcp, then codex mcp login lazyfrog. An older project may not have the files: offer to add them (.mcp.json is {"mcpServers": {"lazyfrog": {"type": "http", "url": "https://mcp.lazyfrog.dev/mcp"}}}).
  • The remote. In a clone from git.lazyfrog.dev it is origin; in an export, origin or lazyfrog (when origin is GitHub). A checkout of the GitHub repository adds it once: git remote add lazyfrog https://git.lazyfrog.dev/<project>.git. Below, lazyfrog means whichever names it.
  • Code that isn't on LazyFrog yet (a repository only on the user's machine; one on GitHub is project import with its address instead): project create from the template nearest its stack (blank for most), then in the checkout git remote add lazyfrog https://git.lazyfrog.dev/<project>.git, git fetch lazyfrog and git merge lazyfrog/main --allow-unrelated-histories. The project's starter files (services.json, Dockerfile, compose.yml, migrations/0001_init.sql, CLAUDE.md, .mcp.json…) join the user's history. Where both have a file, keep the user's (public/index.html, README.md) and add LazyFrog's .gitignore lines to theirs. Then make it run here before pushing: point services.json at the app (dev, build, start, listening on $PORT, healthcheck_path), rewrite Dockerfile and compose.yml for its stack, and move its schema into migrations/, numbered after 0001_init.sql; an app with its own migration tool sets it as "migrate" instead (one or the other, never both). Commit, and push.
  • Push to update the preview. Edit and try it in the checkout as anywhere else (compose.yml runs the app with a PostgreSQL of its own and the same DATABASE_URL; .env.example names the variables), commit, then git push lazyfrog main (the preview's branch). The push answers on git's progress lines (remote: LazyFrog: …): "preview updated: https://p-….lazyfrog.app · build 41 s · 2 migrations applied to preview", or the step that failed with its last lines and what to do. Read them; don't push again unchanged. When the start takes longer than about a minute and a half, the push ends with "still …; the outcome goes on the project's activity": follow with service_status.
  • When the push is refused, it says why in its last line (! [remote rejected] main -> main (…)), and nothing in the preview changed:
    • "the preview has N commits you don't have": someone (or an AI over the tools) changed the preview; uncommitted work there was committed first, as "Changes made in the LazyFrog workspace". git pull lazyfrog main, resolve any conflicts, push again. Never force: a forced or non-fast-forward push is always refused.
    • "contains what looks like a secret": the file and line are above it. Take the value out of those commits (amend or rebase), put it in a secret (secrets request), and push again.
    • "another AI is working in this project": its lease (one AI at a time) is held; try again in a minute.
    • "over the plan's disk", or a read-only token: say so to the user (the plan, or a "Read and write" token).
  • Other branches are stored ("stored; the preview follows main"); only the preview's branch changes the preview.
  • Schema changes: add migrations/000N_name.sql in the checkout and push: pending migrations run on the preview's database as part of the push (a snapshot first), unless services.json says "migrate_on_push": false (then db migrate through the tools). A publish applies them to the live database after its rehearsal.
  • Without the push (or to change only a file or two), the tools still work: fs_write files (paths workspace/…), git commit, then git pull in the checkout.
  • Look through the tools: logs_tail, service_status, http_get, preview_screenshot, and db_read and db_schema for the preview's database (it isn't reachable from the machine).
  • Never commit secrets (.env, keys, tokens: ask the owner with secrets request, and keep local values in an ignored .env), .lazyfrog/, dependencies or build output.
  • Publishing goes through the tools: deploy preflight, then deploy publish when the user says so (see Publishing). A push publishes by itself only when the user turned auto_publish on.

For your AI: this page as Markdown · llms.txt