Develop applications¶
shinyhub dev is the front door for app development:
Your directory chooses the scope. Local execution is always the default; adding
--remote <host> is the only way to move the loop to a ShinyHub server.
One app · Remote
Attach the current app to an existing target on the named host.
Use --app <slug> to narrow a fleet. Use --create or --ephemeral --ttl 8h
only when you deliberately want remote mode to create an app.
The safe local loop¶
From a bundle containing app.py, app.R, or a shinyhub.toml command:
doctor reports bundle, manifest, entrypoint, and runtime blockers
together without starting a process or contacting a server. dev then:
- mirrors the source into an isolated generated workspace;
- installs Python or R dependencies when needed;
- starts the app behind ShinyHub's real local proxy;
- waits for the declared readiness contract; and
- watches for the next edit.
The source directory is treated as read-only. Generated pyproject.toml,
uv.lock, .venv, renv files, bytecode, and the data link stay outside the
checkout and can never leak into a deployment bundle. App data persists across
restarts in a separate directory.
Each edit starts as a candidate. The proxy switches only after that candidate becomes healthy, so a syntax error, missing dependency, crash, or failed readiness check leaves the last healthy version serving. Fix the file and the next save retries automatically.
Requests use the production-shaped /app/<slug>/ route with prefix stripping,
forwarding headers, WebSocket support, and cookie handling. The root URL
redirects to the app route.
Common options¶
shinyhub dev . --open # open after the app is healthy
shinyhub dev . --fresh # rebuild generated state; keep app data
shinyhub dev . --no-sync # skip explicit uv/renv preparation
shinyhub dev . --port 8000 # choose the public proxy port
shinyhub dev . --slug sales # serve at /app/sales/
shinyhub dev . --data-dir ../dev-data # choose durable app-data storage
shinyhub dev . --state-dir /tmp/sales # choose generated workspace state
Environment values come from .env by default and may be overridden with
repeatable --env KEY=VALUE flags. Values are never printed; diagnostics list
keys only. PORT, SHINYHUB_APP_DATA, and SHINYHUB_APP_SLUG are managed by
ShinyHub and cannot be overridden.
Use [app] readiness_path when / is not a meaningful health endpoint. By
default, any 2xx or 3xx response is healthy; add readiness_status to require
one exact status:
Only one runner uses a cached workspace at a time. Give concurrent copies of
the same source distinct --state-dir values.
Choose the scope¶
- Fleet development explains automatic manifest discovery, shared inputs, multi-app output, and selection.
- Remote development explains connection, creation, safety, deployment history, logs, and traces.
shinyhub run remains the lower-level standalone command for one-shot checks
and specialist controls:
shinyhub run . --check # boot smoke test, then exit
shinyhub run . --no-reload # run once without watching files
--check also fails, before booting, on a uv.lock that no longer records
what pyproject.toml declares, which a deploy would refuse (see
shipped uv.lock files).
New interactive workflows should use shinyhub dev so every app shares one
mental model. To work on the ShinyHub platform rather than an application, use
the separate contributor development setup.