Skip to content

vadim0x60/flamp

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

35 Commits
 
 
 
 

Repository files navigation

flamp

UPD: looks like amp has now built a version of this into their product

agentic engineering with wings

flamp runs an Amp prompt on a disposable Fly Machine, commits the result, and pushes it back to your GitHub branch. Launch your agent, close your laptop, get a push notification to your phone when it's done.

Requirements

  • A Git repository with an origin remote, preferably on GitHub.
  • The Fly CLI installed and authenticated.
  • The Amp CLI installed locally. flamp uses it to generate Dockerfile.amp (the project's base image + dependency-install steps, plus flamp's scaffolding) when one does not already exist.
  • An Amp API key in AMP_API_KEY.
  • An SSH private key with push access to the repo in CLOUD_SSH_KEY_PATH.

Usage

export AMP_API_KEY=...
export CLOUD_SSH_KEY_PATH=~/.ssh/id_ed25519

./flamp <branch> "your prompt here" [path-or-glob ...]
./flamp <branch> @prompt.md [path-or-glob ...]
./flamp <branch> - [path-or-glob ...]
cat prompt.md | ./flamp <branch>

Examples:

./flamp fix/readme "Add a README for this project"
./flamp debug-run @prompt.md logs/latest.log .env.local
cat prompt.md | ./flamp feature/new-api

Pass HEAD as the branch to use your currently checked-out branch:

./flamp HEAD @prompt.md

On the first run, flamp generates Dockerfile.amp — the complete build recipe (base image + dependency installs, authored by Amp from your repo, plus flamp's scaffolding) — and persists it. On later runs any existing Dockerfile.amp, whether flamp-generated or hand-written, is built verbatim and never overwritten. The generated file carries a # Generated by flamp header purely as a human-facing note that it's safe to delete and regenerate; flamp itself doesn't read it back.

The Docker image is built from a clean checkout of a sticky pinned commit (not your local worktree, and not origin's default-branch tip). The pin is recorded in flamp-deps.commit and deliberately does not move every time you commit — so ordinary local commits no longer change the build context and therefore no longer bust Docker's dependency-layer cache. The pin only moves when the recipe is (re)generated or when you reset it (see below). The baked checkout only seeds the image's dependency layers; at runtime the Fly Machine fetches and checks out the requested branch, so the branch (including HEAD) must already be pushed with the commits you want Amp to work from — uncommitted local changes are not picked up.

Refreshing the cache:

  • Delete Dockerfile.amp to regenerate the whole recipe (new dependency steps + current flamp scaffolding) and re-pin to your current HEAD.
  • Delete flamp-deps.commit to rebuild the dependencies against your current HEAD without changing the recipe.

Otherwise the dependency layers are reused indefinitely, which is what you want for a dev container whose dependencies rarely change.

Extra path or glob arguments are copied into the checked-out repository on the Fly Machine at the same relative path. They are added to .git/info/exclude there, so they are available to Amp but are not committed.

Configuration

Environment variable Default Description
AMP_API_KEY required Amp API key from ampcode.com/settings.
CLOUD_SSH_KEY_PATH required SSH private key with push access to the repository.
FLY_APP amp-runner Fly app used to launch the Machine.
FLY_REGION ord Fly region for the Machine.
FLY_VM_SIZE shared-cpu-2x Fly Machine CPU size.
FLY_VM_MEMORY 2048 Fly Machine memory in MB.
FLAMP_SIMPLEPUSH_KEY unset Optional Simplepush key for Amp's final output.

(ord is the closest fly region to ampcode.com)

How it works

  1. Reads the prompt from an argument, @file, -, or stdin.
  2. Builds a Docker context from a clean checkout of the sticky pinned commit recorded in flamp-deps.commit (not your local worktree and not origin's latest default-branch tip), excluding local worktree files. The pin stays put across ordinary local commits so the dependency-layer cache survives; it is re-pinned to HEAD only when the recipe is (re)generated or when you delete flamp-deps.commit.
  3. If Dockerfile.amp is absent, generates it: Amp authors a single-stage fragment (base image + system/dependency steps, reusing the repo's existing Dockerfile where possible) as a transient intermediate, and flamp assembles it into Dockerfile.amp — injecting the repo worktree (WORKDIR /tmp/home/work + COPY . /tmp/home/work, without .git) right after the fragment's FROM, then appending git/ssh/ripgrep and the Amp CLI install. The assembled file is persisted and built verbatim on subsequent runs. .git is deliberately excluded: a fresh clone's .git is not byte-stable, so baking it in would bust the Docker layer cache on every build (the runtime fetch recreates .git on the Machine).
  4. Starts a disposable Fly Machine with the baked-in repo, prompt, SSH key, and optional extra files.
  5. Fetches and checks out or creates the requested branch in the baked-in repo, then runs Amp in deep mode.
  6. Commits any changes, pulls the latest branch state, asks Amp to resolve merge conflicts if needed, and pushes back to origin.

Notes

  • The Fly Machine receives the SSH key as a mounted file and uses it only for Git operations.
  • The generated Dockerfile.amp is assembled from a single-stage fragment Amp authors (its FROM plus system/dependency RUN/ENV lines, ideally lifted from the repo's own Dockerfile) with flamp's scaffolding injected: the repo checkout right after FROM, and the tooling/Amp install appended. The fragment is transient — only the assembled result is stored. It must contain exactly one FROM; if Amp's fragment has more (or you need a multi-stage / fully custom build), write Dockerfile.amp by hand instead.
  • For full control over the image, commit your own Dockerfile.amp. When present, any Dockerfile.amp — generated or hand-written — is built verbatim and flamp will not overwrite it (flamp never inspects its contents to decide this; it only checks whether the file exists). A hand-written one must copy the build context into /tmp/home/work, install dependencies, and install the Amp CLI itself. The build context no longer contains .git; the runner initializes git at runtime, so you don't need to bake it in (if you do, the runner reuses it).
  • Extra local files are intentionally excluded from commits on the remote Machine.

About

agentic engineering with wings

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages