Put an app online
Deploy a folder with cohostly deploy: every flag, what gets uploaded, how .env files are handled, the settings question, and what the output means.
cohostly deploy takes a folder on your computer and puts it online. Think of posting a parcel. The CLI packs the box, the platform opens it, builds the app inside and starts it, and you get back the address.
Every deploy makes a new version. Older versions are kept, so you can go back (see versions and rollback).
Three kinds of deploy
cohostly deploy does one of three things. It picks by looking at what you gave it.
cohostly deploy app.cohostlycohostly deploy [folder] and the folder has .cohostly/cohostly.json, and you did not pass --manifestAnything elseCareful The CLI works out "which folder is it" by taking the first word that does not start with
--and does not directly follow--project. A flag value such as the2048in--set compute.memory=2048or the3000in--port 3000, or the short flag-y, can be mistaken for the folder if you put it before the real folder. A folder with no snapshot in it makes the CLI quietly fall back to the plain-folder deploy, so your snapshot is not used. Always put the folder first, for examplecohostly deploy . --port 3000. This is current behaviour, read from the code. Also note that a snapshot deploy ignores--set,--yes,--draft,--manifestand--no-env-file. To change the machine size after a snapshot, editcomputein.cohostly/cohostly.json.
Usage
cohostly deploy [folder] [--project <name>] [--manifest <file>] [--set <path>=<value>] [--yes] [--verbose]
The folder defaults to the current folder. Nothing is required.
[folder]path.. If it does not exist: Error: directory not found: <path>. Put it first.--project <name>text--manifest <file>pathcohostly.json or manifest.json in the folder. A missing file stops with Error: manifest file not found: <path>. Passing it also stops the snapshot deploy.--set <path>=<value>text, repeatable--set compute.memory=1024. The value is read as JSON if it is JSON, otherwise as text. It wins over the file. A bad form stops with Error: --set needs a setting and a value, for example --set compute.memory=1024.--yes, -yon or off--drafton or off--show-settingson or offSettings used: with each setting, its value and where it came from. Default off.--no-env-fileon or off.env files. Default off.--skip-types-checkon or offplatform.gen.ts against the project's contract. Default off.--verbose, -von or offWithout --verbose, a terminal shows one live line ( 42s <newest build line>). A pipe or a log file gets one line per stage. PLATFORM_VERBOSE=1 does the same as --verbose.
Shortcuts for common settings
Each shortcut is the same as a --set. A missing value stops with, for example, Error: --port needs a value, for example --port 3000.
--language <name>text--set runtime.language=<name>.--node-version, --python-version, --go-version <v>textruntime.version, kept as text.--root <dir>pathruntime.root: the folder inside your project that holds the app.--install <command>textruntime.install_command.--build <command>textruntime.build.--start <command>textruntime.entrypoint: the command that starts the app.--port <n>texthealth.port: the port the app listens on.--package-manager <name>textruntime.package_manager.Who may run it: an editor or higher of an existing project, or anyone with an account for a new project name. Names are global across all accounts. If a name belongs to someone you cannot see, you get The name "<x>" is already taken. Pick another name, for example "<x>-2".
What deploy does, in order
- Works out the folder and the project name.
- Reads
--manifestif you gave one. - Checks
platform.gen.ts, if the folder has one. It asks the platform what the file should be and refuses to deploy if they differ. See the types check. - Packs the folder into a
.tar.gzwith the systemtar. - Checks the size (see upload size).
- Reads your
.envfiles and prepares their values (see .env files). - Prints
Deploying <project> ...and uploads. Progress streams back as labelled steps:Analysing,[1/4] Uploading,[2/4] Building,[3/4] Starting. The text after each label comes from the platform. - Prints the outcome.
What is left out of the upload
These are never packed, at any depth: node_modules, .git, .vercel, .next, __pycache__, .DS_Store and files that start with ._. The four root files .env, .env.local, .env.production and .env.production.local are also left out.
If nothing is left after that, you get Could not pack <dir>: ..., including there is nothing to deploy here except .env files, and those are never uploaded.
.env files are never uploaded
The CLI does not upload your root .env files. It reads them and sends their values as secrets instead, stored with your project's secrets and not with your code.
- The four files are read in this order, and later files win:
.env, then.env.local, then.env.production, then.env.production.local. - Files over 1 MB and symbolic links are skipped.
- A name is dropped if it is not capital letters, digits and underscores starting with a letter (up to 64 characters), if it is a common system name (
HOST,NODE_ENV,PATH,HOME,PWD,TZ,LANG,CI,DEBUG), if the platform sets it itself (AI_API_KEY,AI_BASE_URL,APPROVALS_URL,DATA_URL,CRON_URL,PORT, or anything starting withPLATFORM_orCONNECTION_), or if its value is empty. - The CLI prints the names, never the values:
Found 3 value(s) in your .env files (STRIPE_KEY, MAIL_KEY, DB_URL). They are sent securely and stored with your secrets, not with your code. - With
--no-env-fileit printsYour .env files were left out and no values were sent (--no-env-file). - More than 100 values stops the deploy:
Your .env files hold N values. A deploy can carry at most 100. ...(exit1).
Careful A
.env.localthat holds a throwaway test key will be sent as a secret too. Use--no-env-file, or move the file, if you do not want that. To manage values by hand instead, see secrets.
Upload size
Two limits apply, and they are different.
- The CLI checks the packed folder and refuses above 50 MB:
The folder is N MB after packing; the limit is 50 MB (a hosted platform may accept less). Remove build output and large files (node_modules and .git are already left out). - The hosted platform accepts about 30 MiB in one request. A folder between 30 and 50 MB passes the CLI check and is then refused by the server:
The server refused the upload because it is too large (about 30 MB is the most it accepts in one request). Leave out build output, large data files and dependency folders (node_modules and .git are already left out), then deploy again.
Treat 30 MB as the real limit. A plain folder deploy has no way around it. A sealed .cohostly file has one, described in pack and inspect.
The types check
If your folder contains platform.gen.ts (the typed code from cohostly types), deploy compares it with what the platform expects and stops when they differ (exit 1):
platform.gen.ts was edited by hand. Run "platform types --local" to restore it, or deploy with --skip-types-check.platform.gen.ts is older than your manifest or migrations, so the code was written against types that no longer match. Run "platform types --local", fix any errors it shows in your code, then deploy again (or deploy with --skip-types-check).
Run cohostly types --local, fix your code, and deploy again. Use --skip-types-check only when you know why the file differs.
The settings question
Your settings are what the app needs: language, start command, port. They live in cohostly.json. If you have no settings file, the platform works them out from your code (with its build planner) and may ask you to confirm. This is the only question the CLI ever asks.
The folder has cohostly.json (or our manifest.json), or you pass --manifest--draft.No settings file, in a terminal, no flagsNo settings file, in a terminal, --yesNo settings file, no terminal, no flagsNo settings file, no terminal, --draftNothing was deployed. Run again with --yes to accept these settings, or save them as cohostly.json in your folder. Exit code 2.No settings file, in a terminal, --draftDeploy with these settings? [Y]es / [e]dit / [n]o:. Yes deploys.A plan is "clean" when every setting came from the build planner, a default or your .env files, no model was needed to guess, nothing is risky against the live version, and every secret the app declares has a value.
The question:
There is no manifest, so here are the settings worked out from your code: runtime.language node [high] Railpack read package.json and planned this. runtime.entrypoint npm start [high] Railpack read package.json and planned this. health.port 3000 (standard) [high] Deploy with these settings? [Y]es / [e]dit / [n]o:
y,yesor Enter deploys. The confirmation is valid for 15 minutes.nornoprintsCancelled. Nothing was deployed.and exits0.eoreditopens the settings as JSON in$VISUALor$EDITOR. If it is not valid JSON,That is not valid JSON, so the edit was ignored.Then it asks again.
(standard) marks a value that is not in your settings file. The tag in brackets is how sure the planner is.
Good to know In a script, the reliable pattern is to save the settings once as
cohostly.json, then deploy. Then nothing ever asks. If you have no file yet, runcohostly deploy --draftwhere there is no terminal to read the plan, then deploy with--yesto accept it.
What it prints
Live
Deployed project: hello (version v3) URL: https://hello-4k2xq.cohostly.cloud
After that you may see Notice: ... lines, Since version v2: <summary> with up to 12 + added, - removed and ~ modified lines, a Build settings: table with where each value came from (set by you, seen when you ran it, detected by Railpack, worked out from the code, the standard setting), Settings used: (with --show-settings, or always for a snapshot deploy) and Warning: ... lines. Exit 0.
A new project starts private. The CLI does not say so. A deploy never changes who can open the app. A visibility line in a settings file is ignored with a warning. Use cohostly share to change it.
Held for approval
If the project holds new versions for an admin (ship):
Version v4 is built and waiting for an admin to approve it. Visitors keep seeing v3. - <what is risky about it> Approve it here: <request address> Or run: platform ship approve <project> <request>
A folder deploy exits 0 here. A snapshot deploy exits 1. A deploy request stays open for 7 days.
Careful The line
Or run: platform ship approve ...will not work for a version you deployed with the CLI, because a CLI key cannot approve a request another CLI key made. Approve it in the dashboard. See ship.
Failed
Deployment failed while building. Code: build_failed_dependency What went wrong: <cause> What to do: <fix>
You may also see the last lines of the build log, Try again in N seconds. and exit code 1.
unsupported_runtimenot_detectedpackage.json, requirements.txt, go.mod or index.html, or write a cohostly.json.unsupported_versionunsupported_buildnpm run <script>, pnpm run <script>, yarn <script> or npx next build.build_failed_dependencybuild_failed_command, build_failedbuild_out_of_memorymissing_secretport_mismatchPORT, or set health.port.binds_loopback127.0.0.1. Listen on 0.0.0.0, or read HOST.start_crashedupload_too_largeprovider_busysnapshot_invalid, snapshot_expired, snapshot_wrong_account, snapshot_tampered, snapshot_unavailable.cohostly file. See pack and inspect.A version must answer on its port before it goes live. If it does not, the deploy fails at the starting stage with a diagnosis. For more fixes see troubleshooting.
Other refusals you may meet: There is nothing in this upload: no files were found..., account limits in the form Your account has reached its limit of N <what> (you have M). <how to fix>, and The platform is busy right now .... For the numbers see limits.
Files read and written
Reads the folder, the settings file, the four root .env files, and platform.gen.ts if present. Reads the saved key (PLATFORM_API_KEY, or credentials.json in PLATFORM_CONFIG_DIR). Writes nothing to your folder.
Exit codes
0n.12--draft with no terminal and no settings file. Nothing was deployed.Examples
Deploy the current folder under its folder name:
cohostly deploy
Deploy another folder, set the port and the machine size, and accept the settings:
cohostly deploy ./api --project shop-api --port 3000 --set compute.memory=1024 --yes
Check the settings without deploying (see below), then deploy without sending .env files:
cohostly manifest check ./api cohostly deploy ./api --no-env-file
cohostly manifest check
Prints the effective settings and every error and warning a deploy would give, without deploying or storing anything. Use it after editing cohostly.json.
cohostly manifest check [folder] [--manifest <file>] [--set <path>=<value>] [--project <name>]
It accepts the same --set and shortcut flags as deploy. Anything other than check as the first word prints a usage line and exits 1.
[folder]path..--manifest <file>path--set <path>=<value>text, repeatable--project <name>textIt reads cohostly.json, or manifest.json if it is ours. If both exist it uses cohostly.json and says Both cohostly.json and manifest.json are here; cohostly.json was used. A manifest.json that is a web-app manifest is ignored.
Output, in order: Manifest: <path> (version N) or Manifest: none found in <dir>; Errors (a deploy would stop): (exit 1); Warnings:; Notices:; with --project, Who can ship in <project>: <label>; a table of each setting with its value and its source (flag, file or default); and Environment a bound app will see (set by the platform, never by you): with NAME=value lines. Those values are made by the platform. They are not your secrets.
Failures: Error: settings file not found: <path>, Check failed: <error>. For the settings themselves see the settings file.