Configure and run a cloned repository
Goal end state, all of it: the repo cloned, its dependencies installed, framework
setup done, /app/config.json holding a non-blocking run command and the
correct port, and the server verified up (a real curl got a response).
Do not stop at "dependencies installing" — drive it to a working server.
Work autonomously and KEEP GOING across the whole runbook; only stop to ask if a required secret (API key, DB password) is truly unavailable.
0. Inventory first (cheap; saves a failed-command round trip)
The VM baseline normally has git, python3/pip3, python3-venv, curl and a
build toolchain. Confirm what THIS task needs in one shot instead of discovering a
gap by letting a command fail:
command -v git python3 pip3 node npm docker; python3 --version
apt-install only what is missing (see step 2 for how to install correctly).
1. Clone
Clone into /app (your persistent workspace). If /app already has the seed
files only (readme.txt, config.json), clone into a subfolder:
git clone <url> /app/repo # project root is then /app/repo (maybe /app/repo/<subdir>)
Note the real project root — many repos keep the app in a subdir (src/,
backend/, app/). Everything below (pip install, manage.py, the run
command) runs from that root, but config.json and readme.txt must stay at
/app (a workspace reset wipes everything under /app except those two).
2. Detect the project type — and prefer docker-compose
If the repo ships a docker-compose.yml/docker-compose.yaml (and docker is
present), that IS its intended way to run — use it. docker compose up -d builds
the image, starts the DB and the app with the env the author already wired, and
skips the entire venv/pip/PEP668/dependency-resolution minefield. This is almost
always the fastest, most reliable path; reach for the manual venv route only when
there is no compose file. Map the published host port into config.json.port
(read the compose ports:), then verify with curl (step 6).
Otherwise, read the manifests at the project root to decide the toolchain — never assume:
- Python:
requirements.txt,pyproject.toml,Pipfile,manage.py(Django),app.py/wsgi.py/asgi.py(Flask/FastAPI),Dockerfile,docker-compose.yml. - Node:
package.json(look atscripts.start/dev/build), lockfile picks the manager (package-lock.json→npm,pnpm-lock.yaml→pnpm,yarn.lock→yarn). - Read the repo's
README*for the intended run command — copy it, don't invent.
3. Install dependencies (this is where runs usually go wrong)
Installs are long: start them, then WAIT — do not babysit them. bash
auto-promotes apt-get install / pip install / npm install to a BACKGROUND
job and gives you a job_id. Call process(job_id, action="wait") ONCE — it
blocks until the install finishes and returns the result. Do NOT poll
action="status" in a tight loop (it wastes tokens and time); wait is the tool
for "let it finish". When it returns, read the log to confirm success.
Things that look like failures but are NOT — keep waiting, do not intervene:
- pip backtracking: lines like
Using cached X-0.6.2 → 0.6.1 → 0.5.1 …mean pip is resolving a version conflict by trying older releases. This is normal; it finishes on its own. It is NOT a reason to kill the install. python3 -m venvtaking a few seconds: pip appears in.venv/binonly after it finishes bootstrapping. Don'tlsfor it mid-creation and panic.
Hard rules learned the hard way:
- NEVER
rm -rfa venv (or any dir) while an install is running into it — you will corrupt your own work. If you must recreate it,process(..., action="stop")first. - NEVER "fix" a missing Python dependency with
apt-get install python3-<lib>when you have a venv — packages likepython3-matplotlib/python3-wordclouddrag in ~1GB of TeX/Java/GUI deps. Install Python libs with pip into the venv. - One
apt-getat a time: a second fails on the dpkg lock. If the lock is "held by process … (apt-get)", that is your own earlier install — wait for it.
Pick ONE Python strategy and install + run with the SAME interpreter (Debian 12 is
PEP 668 / externally-managed, so a bare pip install errors):
- venv (default for
requirements.txt):python3 -m venv /app/.venvthen/app/.venv/bin/pip install -r requirements.txt. Afterwards ALWAYS run via/app/.venv/bin/python(never barepython3), andconfig.json.runmust use it. - apt (system Python):
DEBIAN_FRONTEND=noninteractive apt-get install -y python3-<name> …, then run with the systempython3.
Node: npm install (or the lockfile's manager). Verify the import/binary with the
exact interpreter before declaring success: /app/.venv/bin/python -c "import django".
4. Framework bring-up
Django (manage.py present):
- Make it bootable without external services: if it requires Postgres but no
POSTGRES_*/DATABASE_URLenv is set, fall back to SQLite, and add the VM's host toALLOWED_HOSTS(localhost,127.0.0.1,0.0.0.0) and a matchingCSRF_TRUSTED_ORIGINS. Prefer env-driven settings over hardcoding; keep changes minimal and reversible. python manage.py migratethenpython manage.py collectstatic --no-input(both via your chosen interpreter).- Run: dev →
python manage.py runserver 0.0.0.0:8000; orgunicorn <project>.wsgi:application --bind 0.0.0.0:8000.
Flask/FastAPI: flask run --host 0.0.0.0 --port 8000 /
uvicorn app:app --host 0.0.0.0 --port 8000.
Node: run scripts.start/dev; for Vite/CRA bind host 0.0.0.0 and use the
dev port (5173/3000). For a build step run npm run build first.
docker-compose: docker compose up -d (after command -v docker).
Always bind to 0.0.0.0 (not 127.0.0.1) on a high, unprivileged port so the
preview proxy can reach it.
5. Write /app/config.json
{"run": "<non-blocking start command>", "port": <the port the app listens on>}
CRITICAL: run is pasted into the user's interactive terminal — it must be
non-blocking or it freezes that terminal. Background the server inside the
command: setsid -f, nohup … &, … &, or docker compose up -d. cd into the
project root and use the right interpreter. Examples:
{"run": "cd repo/src && nohup /app/.venv/bin/gunicorn expenses_tracker.wsgi:application --bind 0.0.0.0:8000 >/app/run.log 2>&1 &", "port": 8000}
{"run": "cd repo && nohup npm run dev -- --host 0.0.0.0 >/app/run.log 2>&1 &", "port": 5173}
port must equal the port the app actually listens on. No port → no preview.
6. Verify it is actually up (do not skip)
Your bash/process tools are SEPARATE from the IDE Run button — start and check
the server yourself:
- Start it:
bash(command="<the run command>", background=true)(or it auto-backgrounds), get thejob_id. process(job_id, action="status")— confirm it didn't crash; read the log.- Confirm the port:
ss -ltn | grep :<port>thencurl -sS -m 5 http://localhost:<port>/— you want a real HTTP response. - If it failed, read the log/error, fix, and retry until
curlsucceeds.
Only then summarize: what you cloned, how it installs, how it runs, the port, and
that curl confirmed it. Update /app/readme.txt with the run command if helpful.
Source: HectorPulido/pequeroku — distributed by TomeVault.