@runly-sh/cli
v0.0.1
Published
Self-hosted software. Made simple.
Downloads
13
Maintainers
Readme
runly
Self-hosted software. Made simple.
runly sets up a self-hosted Runly product on your own machine or server. You
run one command, answer a couple of questions, and end up with a folder
containing a docker-compose.yml, a .env, and a running application.
npx @runly-sh/cli create statusOr install it once and use the short name:
npm install -g @runly-sh/cli
runly create statusThe package is @runly-sh/cli; the command it installs is runly.
That folder is yours from then on. It does not depend on this CLI, or on
Node.js, or on npm. docker compose up -d is the whole interface once the
project exists.
Requirements
- Docker with the Compose plugin
- Node.js 20.11 or newer, but only to run the CLI — the generated project does not need it
Products
| Product | Command | Status |
| --- | --- | --- |
| Runly Status — status page with uptime monitoring and incident history | runly create status | available |
| Runly Forms — form builder with submissions and notifications | — | not built yet |
| Runly Links — short links with click analytics | — | not built yet |
The products marked "not built yet" are listed so the CLI can say "that exists, just not yet" instead of "no such thing". They carry no repository and no image, so there is nothing for the CLI to accidentally try to install.
Usage
runly create [product] [options]Run it with no arguments and it asks. Every question can be answered up front with a flag instead.
This page writes the installed command as runly. If you would rather not
install anything, npx @runly-sh/cli works everywhere runly appears below.
| Flag | What it does |
| --- | --- |
| --dir <path> | Where to create the project. Default: my-<product> |
| --database <postgres\|sqlite> | Which database to use |
| --postgres-mode <docker\|external> | Run PostgreSQL in Compose, or connect to your own |
| --database-url <url> | Your PostgreSQL connection URL. Implies --postgres-mode external |
| --port <number> | Port to publish on. Default: the product's own, usually 3000 |
| --release <version> | Install an exact product release, e.g. 1.2.3 |
| --image [ref] | Use a specific published image instead of the latest release |
| --source <path> | Build from a local product checkout — see Local development |
| --yes, -y | Take the defaults, ask nothing |
| --no-start | Write the files but do not run Docker |
--version prints the version of the CLI. To pick a version of a
product, use --release. The two are deliberately unrelated.
Examples
# The normal thing
runly create status
# Unattended, SQLite, do not start it
runly create status --yes --database sqlite --no-start
# Against a PostgreSQL server you already run
runly create status --database-url postgres://user:[email protected]:5432/runly
# An exact release rather than the newest one
runly create status --release 1.2.3What you get
my-status/
├── docker-compose.yml pinned to an exact image version
├── .env generated secrets — never commit this
├── .env.example the same keys with the values removed
├── .gitignore excludes .env
└── README.md how to run, upgrade and back up this deployment.env is written with owner-only permissions and holds a freshly generated
SESSION_SECRET and, for a Compose-managed database, a generated
POSTGRES_PASSWORD. It is created on your machine and never leaves it.
To upgrade, edit the image tag in docker-compose.yml and run
docker compose pull && docker compose up -d. The CLI is not involved.
How the CLI finds a product
Two separate questions, answered in two different ways.
"Is status a real product?" — answered from a list compiled into the CLI.
No network call. Typing runly create stauts fails instantly and offline, with
the list of names that do exist.
"Which version of it should I install?" — answered at run time by asking GitHub for the product repository's latest release. This is why shipping a new version of Runly Status needs no new version of the CLI.
If GitHub cannot be reached, the CLI falls back to a pinned version — an immutable release tag, so the install is still reproducible, just possibly older — and says so. If there is no pinned version to fall back to, it stops with:
Couldn't resolve a stable release of Runly Status.
Try again, or use --source for local development.It never resolves to latest, main, or any other moving target. A generated
project always names an exact version.
Local development
If you are working on a product itself, you do not want the CLI downloading a release over the top of your changes.
runly create status --source ../statusWith --source, the CLI reads runly.product.json from that checkout, skips
the release lookup entirely, and generates a project whose Compose file
builds the checkout rather than pulling an image. Everything else — the
.env, the secrets, the README, the database choice — is identical, so you are
testing the real deployment, not a special development mode.
--source cannot be combined with --release or --image: a checkout brings
its own version, and quietly ignoring one of the two flags would be worse than
refusing.
Documentation
docs/architecture.md— how the CLI, the product registry, and the product repositories fit together, and how releases flowdocs/products.md— therunly.product.jsonmanifest, and how to publish a new product release
Repositories
| | | | --- | --- | | CLI (this repository) | https://github.com/runly-sh/cli | | Runly Status | https://github.com/runly-sh/status | | Website | https://github.com/runly-sh/website |
Each releases on its own schedule. Nothing here builds or bundles a product.
Working on the CLI
pnpm install
pnpm test # vitest
pnpm lint
pnpm typecheck
pnpm build # tsup -> dist/index.js
node dist/index.js create status --yes --no-start --dir /tmp/exampleEverything is bundled into a single file by tsup, so the published package has
no runtime dependencies and all dependencies live in devDependencies.
The test suite never touches the network. Release lookups are stubbed and the
create tests pin a release; if you add a test that would make a real request,
stub it instead.
Licence
MIT
