The postship command
The official CLI — check a URL, read your projects, wait for a ship, block a merge — and the GitHub action titilyonnais/postship-check@v1.
Updated on 17 September 2026
On this page
A binary that talks to https://postship.fr/api/v1 the way you would talk to the Overview. Node 18 or newer, no dependency. The npm package is postship, published by PostShip; the GitHub action is titilyonnais/postship-check@v1, public repository github.com/titilyonnais/postship-check. Nothing else comes from us.
npm i -g postship
postship check --url https://your-site.example --min-score 80The token
Account → API → “Create a key” (psk_…, shown once). It never goes on the command line: postship reads POSTSHIP_TOKEN from the environment, otherwise ~/.config/postship/config.json ({"token":"psk_…"}, mode 0600). The --token flag does not exist, and any token that would leak to the output is masked.
What PostShip does
The commands
| Command | What it does | Quota |
|---|---|---|
postship check --url U | Checks the URL as after a deploy: table, score, quota. --url repeatable, --project ID for the project's production URL, --min-score N, --json, --quiet, --junit file. | 1 per URL |
postship projects | Your projects, their state, their last run. --fail-if-red. | no |
postship incidents -p ID | What is down, since when. --fail-if-open. | no |
postship ship -p ID | The last production deploy and its score. --require, --min-score N. | no |
postship ships -p ID | The last production deploys (--limit 20). | no |
postship urls -p ID | The project's monitored URLs. | no |
postship wait -p ID | Waits until the last ship is concluded — --sha abcdef for yours — then returns its verdict. --timeout 600. | no |
postship gate -p ID --min-score N | Open incidents + last ship: is production shippable? One line in the workflow. | no |
postship watch -p ID | Open incidents, refreshed every 30 s. Terminal only. | no |
postship whoami | Plan, month's quota, token. | no |
postship doctor | Node, network, PostShip reachable, token accepted. | no |
postship init | Writes ./.postship.json (project, threshold) — committable, never the token. | no |
The project is looked up in order: --project, then ./.postship.json, then POSTSHIP_PROJECT. --json writes the raw response, nothing else. Help and errors are in French when LANG starts with fr, English otherwise; colors are only written to a terminal (NO_COLOR and CI=true respected).
Exit codes
| Code | Meaning |
|---|---|
| 0 | The site (or the read) is good, the threshold is met |
| 1 | The site has a problem: fail, score below threshold, open incidents with --fail-if-open |
| 2 | The tool could not tell: token, quota, network, usage, project not found |
1 and 2 are not the same thing: a workflow that blocks a merge on the site's state must not block on a PostShip outage.
In GitHub Actions
On GitHub Actions, check writes one ::error annotation per failing check: they show up on the pull request, without any GitHub API. The composite action does the same without installing anything:
- uses: titilyonnais/postship-check@v1
with:
url: ${{ steps.preview.outputs.url }}
token: ${{ secrets.POSTSHIP_TOKEN }}
min-score: 80The token is an input of the action, passed from a repository secret: GitHub masks it in the logs, and it never lands in the runner's process list.
A well-built CI checks the preview URL once, then on production:
postship wait --project "$POSTSHIP_PROJECT" --sha "$GITHUB_SHA" --timeout 600
postship gate --project "$POSTSHIP_PROJECT" --min-score 80wait and gate use no quota: they are reads. For GitLab, check --junit report.xml writes a report the Tests tab displays.
Limits and plans
| Free | Pro | Team | Agency | |
|---|---|---|---|---|
check per month | 30 | 300 | 1000 | 3000 |
Reads (projects, incidents, ship, wait, gate…) | unlimited | unlimited | unlimited | unlimited |
Beyond that, check is refused (429, exit 2) with the exact count — never a degraded result.
Troubleshooting
“Set POSTSHIP_TOKEN.”
The variable is not in the process environment. In a workflow, env: POSTSHIP_TOKEN: ${{ secrets.POSTSHIP_TOKEN }} on the step; locally, export POSTSHIP_TOKEN=psk_… or ~/.config/postship/config.json.
“Project not found.”
The token has no access to this project, or the id is wrong — the answer is the same in both cases, on purpose. postship projects lists what the token can see.
watch refuses to start
CI=true: a watch in a workflow runs for nothing. Use incidents --fail-if-open or gate.