Apps
Ask Amp to build and deploy a production server as a workspace app.
An app is a named deployment target owned by a workspace. Each deploy uploads a new bundle and publishes it at the app’s URL. The app keeps a history of past deployments, including the thread each deployment came from.
Deploy From a Thread
Open a thread and ask Amp to prepare and deploy the server. Tell Amp how to build the server if the repository does not make that clear. You can use a prompt like this:
Amp builds the application in the thread’s Orb, prepares a directory with the production output,
and runs amp apps deploy. The deployment environment does not install packages or run a build.
The directory must already contain the server and its production dependencies. Native dependencies
must support Linux on x86-64.
Your server must:
- listen on the port in the
PORTenvironment variable - listen on
0.0.0.0, not onlylocalhost - provide an HTTP health endpoint
Runtime Environment
Amp sets these environment variables when it starts the server:
PORTis the port passed toamp apps deploy. The server must listen on this port.AMP_DEPLOYMENT_URLis the public URL for the app and includes a trailing slash. It is the selected custom URL when you pass--domain. Otherwise, it is the Amp URL at<app>--<workspace>.onamp.dev. Use it when the server needs its public origin for an absolute URL, redirect, or callback.NODE_ENVis set toproduction.
Amp does not set HOST. Configure the server to listen on 0.0.0.0 in its code or start command.
Do not use the local health check address as the public origin.
Secrets and Environment Variables
Use amp secrets with --app workspace/app. Pass values through a file, or use --data-file - to read from standard input.
amp secrets set NAME --app workspace/app --secret --data-file ./secret.txt
amp secrets set NAME --app workspace/app --env --data-file ./value.txt
amp secrets list --app workspace/app
amp secrets history --app workspace/app
amp secrets delete NAME --app workspace/app --yes App values override workspace values with the same name. Redeploy the app after changing a value.
Deploy From the CLI
You can also run amp apps deploy yourself. Pass the app as workspace/app, the directory to
upload, and the executable that starts the server. Deploying to an app name that does not exist yet
creates the app. App names contain only letters, numbers, and hyphens, and can be up to 29
characters. The executable can be a command included in the deployment runtime, such as node, or an executable file in the uploaded directory. An uploaded executable file must have
execute permission. For a directory whose entry point is server.js:
amp apps deploy workspace/app ./dist \
--command node \
--arg server.js \
--port 3000 \
--health-path / Repeat --arg for each argument passed to the executable. Amp creates a compressed archive that
contains every file and directory inside ./dist, then uploads it. Deployment bundles can be up to
250 MiB. Amp starts the executable and checks the health endpoint. A failed deployment does not
replace the active deployment. Pass --size d1.small or --size d1.large to choose the sandbox
size for a deployment; without --size, the app’s default size is used.
List a workspace’s apps with amp apps list <workspace>, show an app’s deployment history with amp apps deployments <workspace>/<app>, and delete an app and its deployments with amp apps delete --yes <workspace>/<app>.
Obelisks
An obelisk is an app’s single long-lived sandbox. Instead of uploading a bundle into a new sandbox
on every deploy, the obelisk keeps one sandbox with the app’s Git repository checked out, so
processes, databases, and files on disk survive deploys. Deploying pulls the newest commit into that
checkout. Obelisks are experimental and live alongside bundle deploys; the amp apps obelisk-* commands and the Obelisk section in workspace settings appear only for accounts they are enabled
for.
Deploy the current repository’s origin remote, or pass --repo:
amp apps obelisk-deploy <workspace>/<app>
amp apps obelisk-deploy <workspace>/<app> --repo https://github.com/<owner>/<repo> --branch main --port 3000 The first deploy creates the sandbox and clones the repository into /home/user/workspace/app,
using your connected GitHub account for GitHub repositories or your Amp account for Amp-hosted
repositories such as https://ampcode.com/@<workspace>/<repository>. Later deploys fast-forward
that checkout; a diverged or dirty checkout fails the deploy instead of being reset. The CLI drives
the deploy and streams its output, so you can stop it with Ctrl-C.
Define how the app builds and runs in .amp/obelisk.yaml in the repository:
build: pnpm install --frozen-lockfile && pnpm build
services:
web:
command: node start.js After the Git sync, a deploy runs build in the checkout and fails if it exits non-zero. Each entry
under services becomes a systemd unit named amp-obelisk-svc-<name> that runs the command in a
login shell as the user account with the app’s environment variables (including PORT and AMP_DEPLOYMENT_URL), restarts when it exits, and starts again when the sandbox restarts. A deploy
installs and restarts every service, removes units for services the file no longer defines, and
then waits for the app to accept connections on its port. A service may set cwd (relative to the
checkout) and extra env variables. Without .amp/obelisk.yaml, a deploy only syncs the
repository and leaves the app’s processes alone.
Run short commands (up to 60 seconds) in the checkout with the app’s environment variables loaded, for example to restart a service or read its logs:
amp apps obelisk-exec <workspace>/<app> 'git log -1 --oneline'
amp apps obelisk-exec <workspace>/<app> 'sudo systemctl restart amp-obelisk-svc-web'
amp apps obelisk-exec <workspace>/<app> 'sudo journalctl -u amp-obelisk-svc-web -n 50 --no-pager' Each obelisk runs an Amp runner named <app>-obelisk in the checkout, so threads can be started
on the production app itself with the list_runners and create_thread tools. Show the obelisk’s
status, sandbox, commit, and runner with amp apps obelisk <workspace>/<app>; the workspace Apps
page shows the same information.
An app has one backend. Once an obelisk deploy succeeds, the app’s URL routes to the obelisk, its
bundle deployments are retired and their sandboxes killed (they stay in the deployment history),
and amp apps deploy refuses the app until the obelisk is deleted. Delete an obelisk and everything
stored on its sandbox with amp apps obelisk-delete --yes <workspace>/<app>; the app’s URL stops
resolving until it is deployed again. Deleting the app also kills the obelisk sandbox.
Build an App With the Skill
The quickest way to a running obelisk app is the building-amp-apps skill. It gives Amp a starter
app with Sign in with Amp, the Jellyware widget, and a SQLite database already wired up, plus the
exact commands to create, deploy, and change the app. In a thread with no project, use a prompt
like this:
Amp then:
- Copies the skill’s template into a new Git repository and runs its checks. The template is a
SvelteKit app with no runtime dependencies; the database comes from
node:sqlite. - Runs
amp projects create --pushso the code lives in an Amp-hosted repository, andamp apps create <workspace>/<app>to reserve the app and its URL. - Registers a Sign in with Amp client for
https://<app>--<workspace>.onamp.dev/auth/callbackand storesAMP_OAUTH_CLIENT_ID,AMP_OAUTH_CLIENT_SECRET, and a generatedAPP_SESSION_SECRETas app variables withamp secrets set --data-file. The secrets are never shown. - Sets
AMP_APPin.amp/obelisk.yaml, pushes, and runsamp apps obelisk-deployonce. - Checks
/health, the anonymous redirect to/login, and the service log, then asks you to sign in at the app URL and confirm the Jellyware button appears.
The whole flow takes about five minutes. Afterwards you change the app either by asking Amp to edit, push, and redeploy, or from the running app through the Jellyware widget. The widget’s Production destination runs the agent on the app’s own obelisk and is offered only to the user who ran the last deploy.
The skill needs an account with apps and obelisks enabled and, to register the OAuth client
itself, the create-oauth-client-apps flag with workspace admin access. When that last part is
missing, the skill explains how to create the client in workspace settings and store the
credentials by hand. It currently ships as a workspace skill in the amp workspace; amp skills list shows whether it is available to you.
Jellyware Widget
An obelisk app can include the Jellyware widget so its creator and workspace admins can select page elements and send requests to Amp from the deployed app. The app must use Sign in with Amp. An app login does not grant permission to run agents or change production data.
From your app’s server, use the signed-in user’s OAuth access token to check widget access:
GET https://ampcode.com/api/jellyware/context?app=workspace/app
Authorization: Bearer <OAuth access token> The token must be issued for the https://ampcode.com/api/v2 resource. Keep it on your server.
Do not put it in HTML, browser storage, or script attributes. This endpoint checks the current
app creator and workspace membership. Repository write access is not app ownership.
The response is { "widget": null } when the user cannot use the widget. Otherwise, widget contains scriptURL and appID. Render the following only for an allowed user, using those values:
<script
src="https://ampcode.com/jellyware/widget.js"
data-jellyware-app="APP_ID_FROM_CONTEXT"
async
></script> If the access check fails or is unavailable, leave the widget hidden and keep the app usable.
Single-page apps must call window.__ampJellyware?.setEnabled(false) when removing the integration
or when access is lost. Remove any pending script element too, and disable the widget if that
script finishes loading after cleanup. Loading the script again restores an existing widget
without adding a second copy. The user’s choice to hide the review button is preserved.
Send opens an Amp confirmation page. Your comment and selected element are shown before any agent starts. Choose either:
- Orb. Create a thread in a project matching the app’s repository. Ask for deployment in your comment if you want Amp to deploy the resulting code.
- Production. Create a thread on the live app runner, with access to its database and files. This is available only to the user who deployed and owns that runner, while the matching runner is online. Workspace admin access alone does not grant production access.
Amp checks these permissions again when you confirm. Follow the created thread for progress or questions. After a requested deployment finishes, return to the app and reload it. The widget keeps unsent comments if the confirmation window is blocked or closed. Do not resend a request whose outcome is uncertain without checking your Amp threads first. Dictation and portal diagnostic uploads are not available in the production widget.
Inline confirmation
Apps can show the destination picker and confirmation inside the widget instead of a separate
page. Set data-jellyware-inline="true" on the widget script:
<script
src="https://ampcode.com/jellyware/widget.js"
data-jellyware-app="APP_ID_FROM_CONTEXT"
data-jellyware-inline="true"
async
></script> If your app sends a Content Security Policy, allow frame-src https://ampcode.com. Nothing else
changes on the app side: keep the context check, and do not add an app endpoint that talks to
Amp for the user. The app’s OAuth token is never used to start work.
On Send, the widget embeds an Amp page from https://ampcode.com in its tray. The first time,
the user connects it to their Amp account in a small Amp window; this is a normal Amp sign-in on
the Amp origin and stays connected for 12 hours in that browser. The embedded page then shows
the comments, the destination choice, and a Start in Orb or Send to Production button.
Amp checks app access, the project, and the runner when the page loads and again on send.
Nothing starts until the user clicks that button in the Amp page. Every send is confirmed
separately; there is no standing permission to grant or revoke.
The tray keeps an Open in Amp link to the full confirmation page. Use it if the embedded page does not load or a browser blocks it. A failed inline request keeps comments queued in the widget.
Custom Domains
First add a domain in workspace settings under Domains. Create the DNS records shown there and wait until the domain is Active. The app’s workspace and the custom domain must have the same owner.
To use only direct subdomains (for example, app.example.com), omit the routing record for the root
domain and only add the other records shown. You can leave example.com pointed at its current
service.
Use the configured domain itself or one direct subdomain:
amp apps deploy workspace/app ./dist \
--command node \
--arg server.js \
--domain app.example.com Amp checks ownership and domain status when publishing and again when the deployment becomes
active. The custom hostname changes only after the new deployment passes its health check. Later
deployments keep the current custom hostname when you omit the domain options. Pass --default-domain to remove the custom route after the next deployment becomes active.
The Amp URL at <app>--<workspace>.onamp.dev stays available when a custom domain is active.
Access and Pausing
Apps are public. Anyone with the URL can use an app without signing in to Amp. The deployed server must enforce any authentication, CORS, or CSRF rules that it needs.
Workspace members can create, update, deploy, and delete apps and view their deployment history.
Apps pause when inactive and resume when they receive a request. The first request after a pause can take longer while the app resumes. Any HTTP request can wake it, and continued requests can keep it running longer.
Link Back to Amp
When a person opens an app inside Amp, a link with target="_amp" can open an Amp page in the
containing Amp app:
<a href="https://ampcode.com/threads/T-..." target="_amp">Open the thread in Amp</a>