Deploy a prototype that runs in Docker to a PitchStation host. Get an HTTPS address, a private link for each person, and redeploys that keep the address and the links.
Apps is switched on per person by your PitchStation admin. Not on yet? Ask them for “Deploy hosted apps (containers)”. How access works ↓
5ways in: AI skill, client, MCP, REST, web page
0rebuilds to change the address or who can open it
2checks of your Compose file: at the dry run and on the host
3DNS views that must agree before your own domain goes live
~/projects/demo-crm
compose.yaml
web/
db/migrations/
.env.exampletemplate, kept
.envleft out
node_modules/left out
deploy succeeded
one operation
Compose file checked
images built
migration run
containers started
health check passed
address routed, with a certificate
Access link · Jordan (investor)
Jordan’s browser · opened with the access link
demo-crm.apps-ap.pitchstation.ai
Demo CRM · Pipeline overview
Lead
Proposal
Won
The route
Six stops from your laptop to their browser
This page follows one fictional prototype, demo-crm. Alex built it, and Jordan, an investor, needs to see it. Each stop says what Alex does and what PitchStation does along the way.
Each promise is printed next to its limit. The stops below show how they work.
Access is checked on the app’s host
A private app’s password, access links and end date are checked on its own host, from a policy file kept there. The check calls nothing outside the host, so it keeps working while PitchStation is unreachable.
LIMITNew “Sign in with PitchStation” sign-ins need PitchStation to be reachable.
Every deploy is a release
Roll back to an earlier release with the skill, the client or the API. Its Compose file starts again, and your domains, access rule, budget and last applied environment stay as they are.
LIMITA rollback restores code built on the host only when each release gives its images a new tag. It never undoes database migrations.
Your data can leave the host
Set up backups once. They run before each redeploy of a running app, daily if you ask, and whenever you choose. PitchStation keeps its own copies, which you can download.
LIMITBackups larger than 512 MB, the default limit, stay on the app’s host only.
Shared hosts enforce the rules
On a shared host each app runs inside its own memory, CPU and process budget. Compose settings that reach outside the app are refused before anything is built.
LIMITOn a server registered to your own account, the same checks only warn unless the server is set to enforce them.
Stop 01 · Built
It runs on your machine. That is the starting line.
Apps takes a project folder. If the folder has a Compose file, the host runs that file. A Vite and React app built with npm, or a Next.js app set to output: 'standalone' with npm or pnpm, needs no Compose file: the packager writes a Dockerfile and a Compose file into the upload for you. Your folder is not changed.
The packager runs on your machine. It leaves out .git, node_modules, .env files, key files, build caches and local databases, and it keeps templates such as .env.example. It refuses a symlink or any file that contains a private key. Add your own rules in a .pitchstationignore file.
The app contract
The web service listens on 0.0.0.0 inside its container, on the container port: 3000 unless you choose another when you create the app.
Only the web service publishes a port, and only as 127.0.0.1:${HOST_PORT}:<container port>.
The health path answers HTTP 200 within about 60 seconds of starting, with no redirect and no login.
Data lives in named volumes. They survive every release; files written inside the container’s own file system do not.
The slug names the address, and it cannot be changed later.
The packager runs on your machine. It leaves out .env files, keys and clutter, and it never rewrites your project folder.
Alex asks an AI assistant that has the PitchStation Apps skill. The skill checks which hosts Alex may use, makes the project deployable and creates the app. Then it runs a dry run and shows the plan before anything is applied.
A deploy’s dry run packs the folder, checks the Compose file and returns the plan: the files, the address, the access rule and any warnings. Nothing on the host changes until you apply with a key. Rollbacks, environment changes, budgets, restores and moves also start with a dry run, and domain and access changes start with a plan you review.
Say to your assistantUse the create-pitchstation-app skill. Make ~/projects/demo-crm deployable, then deploy it to PitchStation as a private app. Show me the dry-run plan before applying.
The skill never asks for your token or password in chat. For a private app it writes the password to a file that you read in your own terminal.
Or run the client yourself
# once: create the app, private from the start
ps-apps create --file app.json --private \
--password-file ~/.pitchstation/demo-crm.password
# dry run: the plan comes back, nothing changes
ps-apps deploy --app 41 --source ~/projects/demo-crm \
--marker"Demo CRM · Pipeline overview"# apply with a key you keep; a key never deploys twice
ps-apps deploy --app 41 --source ~/projects/demo-crm \
--marker"Demo CRM · Pipeline overview" \
--apply--key demo-crm-20261002-01 --watch
ps-apps stands for ~/.pitchstation/ps-apps, the launcher the skill’s Setup installs for the one-file Apps client. It is not on your PATH, so type the full path.
What the skill does after one sentence. Amber marks the two points where it comes back to you.
Five ways in, one API
The skill is one way in. The Apps client, the MCP tools, the REST API and the Apps page reach the same API, and every call checks the same Apps permission.
AI skill
create-pitchstation-app
Best for
Asking Claude Code, Codex or another agent with a shell to make a project deployable and ship it.
Does
Everything in the comparison below. It drives the Apps client for you, and uses the REST API to stop or delete an app.
Not here
Accepting publisher terms. You accept them yourself on the Apps page.
Apps client
pitchstation-apps.cjs
Best for
Terminals and CI. One Node file (Node 20 or later) with no dependencies; each result is one JSON line. It reads the token from the environment and refuses tokens or passwords on the command line.
Stopping or deleting an app (use the REST API). Accepting terms, which needs a signed-in browser session.
MCP tools
six pitchstation_app_* tools
Best for
Assistants that work through tools. The six are list, status, logs, deploy, operation and readiness.
Does
Deploys (with an image archive if you have one), follows, retries and cancels operations, reads status and logs, and runs readiness.
Not here
Creating apps. Also domains, access, environment, budgets and rollback: those are reviewed plans guarded by a version check, so they stay in the skill, the client and the REST API; the Apps page also does domains, access and budgets.
REST API
/api/apps
Best for
Your own tooling. It is the complete surface, described in OpenAPI at /api/openapi-apps.json.
Does
Every action, including stop and delete. Changes that run as operations take an Idempotency-Key: repeat a request with the same key and you get the same operation back. Send Prefer: respond-async to get 202 and an operation to follow at once.
Not here
Accepting publisher terms: that needs a signed-in browser session.
Apps page
/apps.html
Best for
Owners working by hand, signed in.
Does
Hosts and spend, terms, domains, access and end date, access links, backups and restore, moves, read-only services, deploy settings, image archives (list and remove), status, logs, budgets and operations.
Not here
Creating, deploying, environment changes, rollback, stop and delete. It lists image archives but does not upload them.
… stands for /api/apps/{id}, and {op} for an operation ID.
The Apps page cannot create or deploy an app. It is where you change addresses and access, share links, back up, move, and watch status, logs and operations.
Apply once. One operation takes it from upload to live.
When Alex applies, PitchStation answers at once with an operation ID and does the work on the app host. It re-checks DNS for every hostname, checks the Compose file, sets the app’s budget and builds the images, or loads images built elsewhere. If backups are set up and the app already has a release, it backs up the data. Then it runs the migration, starts the containers and waits for the health check. Last, it routes the address, with a certificate for each hostname.
Once PitchStation has accepted the deploy, you can close the laptop: the operation keeps running. If the connection drops, send the identical command again with the same key. You get the same operation back, not a second deploy.
If anything fails before the new containers start, the previous release keeps serving. If the new release fails its health check, the operation fails, and the address serves the failing release until you deploy a fix or roll back. The failed step keeps its last lines of output, with stored secrets masked. When PitchStation cannot tell what happened on the host, it stops the app’s queue and asks someone to check, instead of guessing.
Each apply is one operation with these steps, in this order. Send the same key again and you get the same operation back, never a second deploy.
Same key, same operation
Apply--key demo-crm-…-01first try
→
Operation Acreated
Same request again--key demo-crm-…-01after a dropped connection
→
Operation Areturned again, marked as a duplicate
Changed request--key demo-crm-…-01same key, new source
→
RefusedIDEMPOTENCY_KEY_REUSED
Your next deploy--key demo-crm-…-02a new key
→
Operation Bcreated
Keys are 8 to 128 letters, digits, dots, underscores or hyphens.
Follow it, or walk away
queued→running→succeededfailedcancelled
waiting_external: a hostname’s DNS is not ready. It retries by itself for up to about 75 to 90 minutes.
cancel_requested: stops at the next safe point.
Retry safe steps runs a failed operation again and skips the steps that already succeeded.
One at a time: while an operation runs, another change for the same app gets OPERATION_BUSY.
--watch follows an operation for up to five minutes. The operation does not stop when the watch does.
Uncertain? If only your containers were involved, you inspect the host, check your database and confirm. Routing and certificate cases go to an admin.
A page that loads proves little. It could be an old server, a default page or another app. Readiness tests every address of the app: DNS points at the right host, the certificate is valid, the access rule behaves as set, the home page carries the app’s identity text and headers, and its scripts and stylesheets load.
Every deploy runs readiness at the end, and so do rollbacks and domain or access changes. You can run it again from the Apps page or the client. A result holds for five minutes. It also says what it did not check: video playback, language switching and 3D still need a person with a browser.
Readiness is evidence that this address serves this app, with these access rules. Each deploy runs it at the end.
Public app? Declare that the app has no login or expiry of its own. Until you do, readiness will not certify it. Why
Hand over proof, not passwords
Copy redacted receipt gives the addresses, the access summary, the release and the latest readiness result. Passwords are never in it.
Identity text
Vite apps get an identity marker automatically. For Next.js and Compose apps, pass --marker with 12 or more characters the home page always shows, or set Expected page identity on the Apps page.
A private app asks for a password before a request reaches your containers. The check runs on the app’s own host, so the app stays private even while PitchStation itself is unreachable.
For a named person, create an access link. It lets that one person in without the password. It can expire, and you can revoke it on its own. Alex makes one for Jordan and copies it from the Apps page.
Colleagues with a PitchStation account can sign in with it instead. List the people, or a team, and the app’s sign-in page offers Sign in with PitchStation.
The Access links panel on the Apps page, with fictional data: one link per person, when it expires, and how often it was opened.
Passwords are 12 to 72 bytes, chosen and kept by you. A new password signs everyone out.
Sessions last 12 hours and never outlive the end date you set.
Up to 50 active links per app. Each can expire, up to a year ahead.
The Opened count appears where the app’s host runs the current host reporter, which an admin installs when onboarding the host.
After sign-in, your app gets the visitor’s own Authorization header. The gate’s credentials never reach it.
Webhooks and OAuth callbacks can skip the password on up to five callback paths. The end date still applies, and your app must verify each callback itself.
Set an end date, and after it every address answers 410.
The gate lives on the app’s own host. If PitchStation is down, your private app stays private, and its end date still holds.
If PitchStation is unreachable
Keeps working on the app’s host
Visitors reach your app.
Password and access-link sign-ins, and sessions already open.
The end date (410) and redirected or disabled addresses.
Takedowns (404).
Certificate renewal.
Waits until PitchStation is back
New Sign in with PitchStation sign-ins.
Deploys, rollbacks and every change, including new and revoked links.
Status, logs and readiness checks.
Use the password for a small group, a link for each named person, and PitchStation sign-in for colleagues and teams.
Account sign-in, callback paths and cache paths use a newer access check. PitchStation installs it on the app’s host with the app’s next deploy or access change.
Jordan opens the link and finds a bug on the deals page. Alex fixes it and deploys again with a new key. The domains, the password and the link Jordan already has all stay as they were, so Jordan reloads the page and sees the new release.
When a deploy fails, the operation shows the failed step’s last lines with stored secrets masked. In the example below, the new release failed its health check because a setting the new code needs is missing. Its container exits during startup, so nothing answers on the app’s port, and visitors get an error page (502) until the fix is deployed or the app is rolled back. The fix is to add the setting to the app’s environment and deploy again with a new key. If a step failed for a passing reason, Retry safe steps runs the operation again and skips the steps that already succeeded.
Every deploy is a release you can return to. Roll back with the skill, the client or the API: PitchStation starts that release’s Compose file again and keeps the domains, the access rule, the budget and the last environment you applied. A rollback does not build. An image built on the host keeps the same name from release to release, so a rollback runs its newest build, unless each release gives it a new tag, such as image: demo-crm-web:r34. A rollback never undoes database migrations, so write migrations that are safe to run forward.
A failed deploy on the Apps page, with fictional data: the health check failed, and the step’s last lines show why. The database address is masked.
After a failed health check, the failing release is what the address serves. Its containers replaced the old ones before the check ran, and they stay until you deploy a fix or roll back. If they do not start, as above, visitors get an error page. Deploying the fix with a new key is the surest way back. To roll back instead, name the release: the app still records the last good release as current, and ps-apps list shows its ID as currentRelease. A client updated by re-running the skill’s Setup also has ps-apps releases --app 41, which lists every kept release. A rollback without a release ID skips that release and goes one further back. Run ps-apps rollback --app 41 --release ID, then apply with a new key; it brings that release’s code back only if its images have their own tag.
After a failed health check the failing release stays at the address. Name the release you return to, and tag built images in every release so a rollback brings their code back.
Changed a NEXT_PUBLIC_ or VITE_ value? Those are baked in when the app is built. The Apps page tells you the running release still has the old value until you deploy again.
Apps run on shared hosts that PitchStation runs for teammates, or on a host of your own. On shared hosts each person can have three apps, unless an admin changes the limit. Leave the host out when you create an app and PitchStation places it on a host you may use. It prefers the region you ask for, if you name one, then the host with the most free budget memory. It says why it chose that host, and lists every host it passed over with the reason.
Want a machine nobody else uses? Reserve an isolated host on the Apps page or with the client, and an administrator launches it. It counts against the monthly spend cap on your account, which dev instances share. A reservation nobody launches within 24 hours lapses.
A shared host holds other people’s apps, so its rules refuse instead of warn. Each app gets its own budget: 512 MB of memory, one CPU and 256 processes by default, with no swap. The Compose file is checked at your dry run and again on the host before anything is built.
Check the architecture before you build. An ARM64 host needs ARM64 images. ps-apps targets lists each host you may use, with its architecture, region and free slots.
Leave the host out and PitchStation places the app, and says why. ps-apps targets lists each host you may use, with its architecture, region and free slots.
Shared host or isolated host
Compared
Shared host
Isolated host
Who else runs apps on it
Teammates
Nobody else
How you get it
Available once Apps is switched on for you
You reserve it on the Apps page or with the client; an administrator launches it
Compose rules
Risky settings refused
Strict allowlist: anything not on the list is refused
Budgets
Enforced, no memory overcommit
Warn only, unless the server is set to enforce them
Outbound traffic
Open, unless an admin restricts the host
Restricted: no outbound mail, no cloud metadata service, new connections rate-limited
Counts against
Your shared-host limit: 3 apps unless an admin changes it
Your monthly spend cap, shared with dev instances
Holds
—
3, 6, 12 or 20 apps, by size
Sizes and places
—
S, M, L or XL · arm64 or amd64 · Oregon or Singapore
Address
<slug>.<base domain>, for example demo-crm.apps-ap.pitchstation.ai
the host’s own label, for example demo-crm.h7.apps-ap.pitchstation.ai
A server registered to your own account can be a target too. There the same checks warn instead of refuse, unless the server is set to enforce them.
Other people’s apps share the machine, so the host refuses risky Compose settings and keeps every app inside its own budget.
Too heavy to build on the host? Build it elsewhere.
On hosts set up with the build ceiling, a build gets a capped share of the machine: by default 40% of its memory (at least 1 GB) and one CPU, one build at a time. A build that needs more stops with BUILD_LIMIT_EXCEEDED, and the running release keeps serving.
The way around it is to build on your own machine, in CI or on a PitchStation Devbox, and send the images. The host loads them and builds nothing.
Make the archive
From the project folder, ps-apps archive --source . --platform linux/arm64 --output ../demo-crm-r34.tar.gz builds with your own Docker and saves the images outside the project, so they are not packed into the upload. Use a new file name for each build: the client never overwrites a file. Every service with build: needs an image: name:tag.
Deploy with it
ps-apps deploy --app 41 --source . --image-archive ../demo-crm-r34.tar.gz uploads the archive once and shows the plan; add --apply--key … to deploy. If PitchStation already holds a file with the same SHA-256, it is not sent again.
The host loads it
The dry run checks each image’s CPU architecture against the host’s. PitchStation keeps your newest three archives, plus the one the running release came from.
On a Devbox, devbox.py app-deploy runs both steps for you. Match the host’s CPU: linux/arm64 for an ARM64 host, linux/amd64 for x86.
When a build is too heavy for the host, build it where you have room and send the result.
The Apps page in your PitchStation workspace is where an app lives after its first day. It lists only your own apps.
Status and logs
Each container’s state, health, restarts and memory against its budget. Up to 1,000 log lines a read, with stored secrets masked. Every log read is recorded.
Budget
Review a new memory, CPU or process limit, then apply it. On a shared host it applies without a restart.
Backups
Back up with a dump command or by copying named volumes, on demand or daily. Once backups are set up, each deploy of an app that already has a release backs up first. To restore, you review what is replaced and type the app’s slug.
Your own domain
Prove you own it with a TXT record, and PitchStation issues its certificate. The app is not rebuilt or restarted.
End date
Give a demo an end date. After it, every address answers 410, checked on the host for each request.
Move
Move the app to another host. Its data travels in a final backup, and the old copy stays stopped for 7 days by default.
Operations
Retry safe steps, cancel at a safe point, or settle an uncertain migration yourself after checking your database.
Read-only file system
Run chosen services with a read-only root file system and a writable /tmp, from the next deploy, rollback or environment change.
Your own domain
Bringing your own domain takes four steps, and the app keeps serving throughout.
A working URL is not proof of ownership; the TXT record is. The app keeps serving while its address changes.
Backups and restore
Backups run on the app’s host. PitchStation also keeps copies of the smaller ones, and a restore checks the file before it uses it.
Backups are taken and kept on the app’s host; PitchStation keeps copies of those up to 512 MB. A restore is reviewed, confirmed with the app’s slug, and checked before it is used.
Move to another host
A move uses the app’s backup settings. Review it first: the plan shows the destination and why it was chosen, whether the address changes, how the data travels, the downtime and every step. The app is down from the moment the source stops until the destination serves. If the move fails before the switch, the destination is cleaned up and the source starts again. The stopped source stays for 7 days by default. When the move changed the address, the old address redirects (308) to the new one.
A move is reviewed first. The app is down from the source stop until the destination serves; if anything fails before the switch, the source starts again.
Before a move can start
The app has a running release, and backup settings, or you tick “This app keeps no data”.
Its data is 512 MB or less, the default limit.
The destination is approved by an admin and has the same CPU architecture.
The destination has another base domain, as an isolated host does, so the platform address changes; a move between two hosts under one base domain needs per-app DNS. Custom domains stay yours: point their DNS at the new host as soon as the move stops the source, because the new host serves the app only once every name resolves to it.
A release deployed from an image archive is loaded on the new host, not rebuilt, so that archive must still be kept.
What stays private
Secrets encryptedEnvironment values are encrypted at rest. The API returns their names, never their values.
Values maskedStored values of six or more characters are masked in logs and failed-step output.
Reads recordedOnly you and PitchStation admins can read your logs, and every read is recorded.
Keys left outThe packager leaves .env and key files out of uploads and refuses a file that contains a private key.
Not on the Apps page: creating an app, deploying, rolling back, environment variables and uploading image archives (use the skill, the client or the API), and stopping or deleting an app (the skill or the API).
Running your own code on shared machines needs more trust than sharing a document, so Apps is never on by default. An admin switches it on for you. Then you make a token for your tools and set up your assistant.
Ask your admin
They open your account’s Feature access and tick “Deploy hosted apps (containers)”. Until then, the Apps page and the API answer CAPABILITY_REQUIRED.
Create an Apps token
On the API Tokens page, choose the Apps preset. The token starts with pst_ and is shown once. Keep it in a file, never in a chat or on a command line.
Set up your assistant
Say the sentence below to Claude Code, Codex or another agent with a shell. Its setup installs the Apps client, which needs Node 20 or later. It never asks you to paste the token into the chat.
Say to your assistantInstall the PitchStation Apps skill: save https://pitchstation.ai/downloads/create-pitchstation-app-SKILL.md as create-pitchstation-app/SKILL.md in your skills folder (~/.claude/skills for Claude Code, ~/.codex/skills for Codex). Then follow its Setup section and tell me which hosts I can deploy to.
Start a new session after installing. Prefer a terminal? The deploy guide shows the same setup by hand.
If your admin requires publisher terms, accept them once on the Apps page while you are signed in.
No PitchStation account yet? Apps is not part of self sign-up. Ask whoever runs PitchStation for your team, or write to hello@pitchstation.ai.
Questions
Can I sign up and start deploying?
Only once an admin has switched Apps on for your account; self sign-up does not include it. Sign in and open the Apps page. If it says CAPABILITY_REQUIRED, ask your admin.
What kinds of projects work?
A project with a Compose file whose settings pass the host’s Compose rules, with images built for the host’s CPU. A Vite and React app (npm), or a Next.js app set to output: 'standalone' (npm or pnpm), is packaged for you without a Compose file.
Do I need Docker on my machine?
Not for a normal deploy: the client uploads your source and the host builds it. You need Docker to build an image archive yourself. The skill also uses Docker for a local smoke test when it is there, and tells you when it is not.
Can I deploy from the Apps page?
No. The Apps page looks after apps that are already deployed: addresses, access, links, backups, moves, budgets, status, logs and operations. Create an app with the skill, the client or the REST API. Deploy with any of those, or with the MCP tools.
Does changing the domain or the password rebuild my app?
No. Address and access changes only re-apply the routing. They never rebuild or restart the app.
What happens to my app if PitchStation is down?
It keeps serving. Passwords, access links, end dates and certificate renewals are handled on the app’s own host. New Sign in with PitchStation sign-ins, deploys and other changes wait until PitchStation is back.
Is my data kept between releases?
Yes, if it lives in named volumes. Files written inside a container’s own file system are lost at the next deploy. Backups add copies on the host and, for backups up to 512 MB, on PitchStation.
Who can read my logs?
You and PitchStation admins. Stored environment values of six or more characters are masked, and every read is recorded in the app’s history.
Will my images run on every host?
Only on a host with the same CPU architecture. An ARM64 host needs ARM64 images. ps-apps targets shows each host’s architecture.
Can someone report an app?
Yes. Anyone can report an app at /abuse.html, without an account. An admin can take an app down; every address then answers 404 until the takedown is lifted.
Next step
Open Apps, or read the manual first
Sign in to see your apps. If the page says CAPABILITY_REQUIRED, your admin has not switched Apps on yet. The manual walks through every stop on this page.