The kwisple CLI ships with @kwisple/sdk. It creates new site projects, signs you in to the
dashboard, links a project to a site, keeps the content model in sync while you work, pushes
it (also from CI) and moves content in and out as site kits. Its own messages are in Dutch.
Running it
The binary is kwisple, installed with @kwisple/sdk. Run it from the root of the site
project (the folder with cms.config.ts and .env):
npx kwisple <command> # npm, or any project with the SDK installed
pnpm kwisple <command> # pnpm: the starters (and RANSON.N) have a "kwisple" scriptThe entry registers tsx, so cms.config.ts runs as TypeScript without a build step. Inside
the platform monorepo the CLI runs straight from the SDK's TypeScript sources; an installed
package runs its compiled dist/. kwisple, kwisple help, --help and -h print the
overview. An unknown command prints it too, after an error.
All commands that fail print ✖ <reason> and exit with code 1. The one exception is
kwisple push, which exits with 2 when destructive changes were blocked.
Commands
| Command | What it does | Needs |
|---|---|---|
kwisple create [dir] | New site from a starter (Astro or Next.js). Alias: kwisple init. | Nothing. |
kwisple login | Signs this machine in to a dashboard (device flow in the browser). | An account. |
kwisple logout | Revokes the CLI token on the platform and forgets it here. | — |
kwisple whoami | Who you are signed in as, on which dashboard. | — |
kwisple link | Picks agency → client → site and writes .env. | Login. |
kwisple dev | Syncs cms.config.ts to the development model and runs the dev server. | .env |
kwisple push | Applies cms.config.ts to the live content model. | .env or CI variables |
kwisple status | Compares the local model with the platform's. | .env or CI variables |
kwisple seed [file] | Writes a site kit into the linked site. | .env |
kwisple export [file] | Saves the linked site's live content as a site kit. | .env |
kwisple ci-token | Creates a site token for CI. | Login + a linked project or --site |
".env" means KWISPLE_URL and KWISPLE_TOKEN, from .env.local, .env or the process
environment (see Environment variables). Without them these commands
stop with KWISPLE_URL en KWISPLE_TOKEN ontbreken.
Options
| Option | Used by | Meaning |
|---|---|---|
--dashboard <url> | login, logout, whoami, link, ci-token | The dashboard to talk to. A bare host gets https://. |
--no-browser | login | Print the approval link instead of opening a browser. |
--site <id|slug> | link, ci-token | The site, without questions. |
--client <slug> --name <name> | link | Create a custom-code site for that client first, then link it. |
--preview-url <url> | link | The preview URL to set on the site when it has none yet. |
--no-server | dev | Only follow the content model; do not start the dev server. |
--live | dev | Push every change to the live model instead of the development model. |
--force | push, seed | push: apply destructive changes. seed: write into a site that already has content. |
--dry-run | push | Show what would change; apply nothing. |
--config <path> | dev, push, status | Another config file than ./cms.config.ts. |
Which dashboard
login, logout, whoami, link and ci-token talk to a dashboard. The CLI picks it in this
order:
--dashboard <url>;- the environment variable
KWISPLE_DASHBOARD_URL; KWISPLE_DASHBOARD_ORIGINfrom the project's.env.localor.env;- the dashboard of your last login;
https://app.kwisple.com.
For the platform running locally, pass --dashboard http://localhost:4100 once at login; later
commands follow the last login. Agencies with their own dashboard host log in there: the
approval page then shows the agency's identity.
kwisple create
The same program as npm create kwisple-site. It asks what it needs, or takes it from flags:
| Flag | Meaning |
|---|---|
--framework astro|next (-f, also --template/-t, or --astro / --next) | The starter. |
--pm pnpm|npm|yarn|bun (--package-manager) | Package manager; default: the one you started it with. |
--install / --no-install | Install dependencies right away or not. |
--kit dienstverlener|horeca|geen | Starting content (a site kit you later put online with kwisple seed). |
--git / --no-git | Create a git repository or not. |
-y, --yes | No questions; defaults for whatever is missing. |
See Quick start for the whole path from create to live content.
kwisple login
Signs this machine in with the device authorization flow: no token to copy, and the token is never printed.
- The CLI asks the dashboard for a code (
POST /api/cli/device) and prints it:Je code: WDJB-MJHT. Codes are eight letters without vowels or look-alikes. - It opens
<dashboard>/cli?code=WDJB-MJHTin your browser. It does not open a browser with--no-browser, whenCIorSSH_CONNECTIONis set, or when the output is not a terminal; it prints the link instead. - On that page (Terminal koppelen), signed in, you see Geef de CLI toegang? with the Code, the Toestel (device, for example MacBook-Robbe · macOS), Aangemeld als and Geldig tot. Check that the code matches your terminal, then click Toegang geven (give access) or Weigeren (refuse).
- The CLI polls every 5 seconds (5 seconds more after each
slow_down) and, once approved, saves the token and prints✔ Aangemeld als <name> (<email>) op <dashboard>.
A code is valid for 10 minutes; after that the page shows Code verlopen and the CLI
stops with De code is verlopen. Voer kwisple login opnieuw uit. A refused code ends with
Toegang geweigerd in de browser. The token is minted at the first poll after approval and can
be collected only once. Starting logins is rate limited per address and globally.
The CLI token (kwicli_…) works with your rights: link sites, push content models and
create tokens for the sites you may manage, never more. It shows under Koppelingen →
Terminal in the dashboard, where you can revoke it. Requests are limited to 120 per minute
per token.
Where credentials are stored
One token per dashboard, in credentials.json in the CLI's config folder, readable by you only
(file mode 0600, folder 0700):
| Platform | Folder |
|---|---|
| macOS, Linux | $XDG_CONFIG_HOME/kwisple, else ~/.config/kwisple |
| Windows | %APPDATA%\kwisple |
| Any | KWISPLE_CONFIG_DIR overrides the folder |
The file remembers which dashboard you used last (current); that is the default for later
commands.
kwisple logout and kwisple whoami
logout revokes the token on the platform and removes it locally: Afgemeld op
whoami prints your name, email, the dashboard and the token's name. It exits with 1 when
you are not signed in, and also when the token was revoked in the dashboard (it then forgets
it locally).
kwisple link
Connects the project in the current folder to a custom-code site and writes .env.
Interactively (arrow keys) it asks:
- Bureau (agency), only when you belong to more than one;
- Klant (client), listing only clients where you may link a site;
- Website: the client's custom-code sites, staging environments marked
(staging), plus + Nieuwe website when you may create sites. A new site asks Naam van de nieuwe website, with a name derived frompackage.json.
Without questions: kwisple link --site <id|slug>, or kwisple link --client <slug> --name <name> to create the site first. Not in a terminal and no --site? It lists the clients and
sites with the flags to use, and stops.
What linking does:
- creates a site API token with the scopes
read + preview + schema, namedkwisple link · <machine> · <project>; linking the same project from the same machine again replaces it, other projects keep theirs; - creates the site's webhook secret if it has none yet;
- sets the site's Preview-URL only when it has none, to
--preview-urlorhttp://localhost:<port>/api/preview(the port from yourdevscript, else 4321 for Astro and 3000 otherwise); - merges these keys into
.env(other lines and comments stay; the file gets mode0600):
| Key | Value |
|---|---|
KWISPLE_URL | The platform's delivery API. |
KWISPLE_TOKEN | The new site token. |
KWISPLE_WEBHOOK_SECRET | The site's webhook secret. |
KWISPLE_DASHBOARD_ORIGIN | The dashboard you linked through (your agency's host when you used it). |
KWISPLE_ASSET_ORIGIN | Where uploaded files are served from. |
KWISPLE_SITE | The site's id (used by kwisple ci-token). |
- adds
.envto.gitignore(creating it if needed) unless it is already ignored; - warns when
.env.localsets one of the same keys, because.env.localwins.
Linking needs the developer-settings right on that client and only works for custom-code sites (Deze website is niet op maat gebouwd. Enkel websites met eigen code kan je koppelen.). The variables are explained in Environment variables and tokens.
kwisple dev
Follows the content model while you work:
- pushes
cms.config.tsto the site's development model on start and on every change (✔ Ontwikkelmodel bijgewerkt … — live blijft op versie N); editors and clients keep the live model until youkwisple push; - watches the config's folder recursively for
.ts,.mts,.jsand.mjsfiles (so split configs undercms/count), ignoringnode_modules,.next,.astro,distand anything undersrc/, with a 250 ms debounce; - starts the framework's dev server as
<pm> run dev, the package manager detected from the lockfile (pnpm-lock.yaml,yarn.lock,bun.lock/bun.lockb, else npm), withKWISPLE_SCHEMA=devso the SDK reads with the development model. Nodevscript, or--no-server: only the model is followed. A failing dev server endskwisple dev.
A broken model prints the problems and keeps watching. --live pushes to the live model
directly, as kwisple push would (without --force). Stop with Ctrl+C. The workflow is in
Workflow: dev, push and changes.
kwisple push
Validates cms.config.ts locally (the same checks as the platform, apps and forms included),
then sends it to the live model.
| Outcome | Output | Exit code |
|---|---|---|
| Applied | ✔ Versie N toegepast and the list of changes | 0 |
| Nothing changed | ✔ Geen wijzigingen — platform staat op versie N. | 0 |
--dry-run | ℹ Deze wijzigingen zouden worden toegepast: and the changes | 0, or 2 when a change is destructive |
Destructive changes, no --force | ! Niet toegepast: deze push bevat destructieve wijzigingen., the changes (destructive ones marked (destructief)) and Bevestig met kwisple push --force. | 2 |
| Invalid model, wrong token, network error | ✖ <reason> | 1 |
Changes are listed as + added, − removed, ~ changed. A destructive change hides existing
content (a removed field or section); content is never deleted and comes back when the field
does. --force applies them anyway.
--dry-run exits 2 when a change would be destructive (! Destructieve wijzigingen: op main is kwisple push --force nodig.), so a pull request fails on what the push on main would
refuse. --dry-run --force exits 0. Pushing needs a token with the schema scope, and only
works for custom-code sites.
kwisple status
Prints the platform's model version and where it came from, then runs a dry-run push quietly:
Lokaal model is gelijk aan het platform. or the changes a push would make. It needs the
schema scope too, because the comparison is a dry run on the platform.
kwisple seed and kwisple export
npx kwisple export # live content → cms/seed.json
npx kwisple seed # cms/seed.json → the linked site, published
npx kwisple seed kits/demo.json --forceexport saves the linked site's live content as a site kit. Images, files and links between
pages are left out of a kit. seed writes a kit into the linked site, published; it refuses a
site that already has content of its own unless --force, and lists what it could not place.
Both default to cms/seed.json and need the schema scope. See
Site kits: seed and export.
kwisple ci-token
Creates a site API token for CI with the scopes read + schema and prints it once, with the
API address:
npx kwisple ci-token # print KWISPLE_URL and KWISPLE_TOKEN
npx kwisple ci-token --gh # store them as GitHub Actions secrets with the gh CLI
npx kwisple ci-token --site acme-site # another site than the linked oneThe site comes from --site, else KWISPLE_SITE (written by kwisple link). --gh runs
gh secret set KWISPLE_URL and gh secret set KWISPLE_TOKEN for the current repository,
passing values over stdin; if that fails it prints the values instead. The token is named
CI (GitHub Actions); creating a new one revokes the previous CI token you made for that
site. Details in CI and automation.
Environment variables
| Variable | Read by | Meaning |
|---|---|---|
KWISPLE_URL, KWISPLE_TOKEN | dev, push, status, seed, export | Delivery API and site token. Read from .env.local, then .env, in the current folder; variables already set in the environment win (CI). |
KWISPLE_DASHBOARD_URL | dashboard commands | Dashboard to use (step 2 above). |
KWISPLE_DASHBOARD_ORIGIN | dashboard commands | Read from the project's .env.local / .env only (step 3 above). |
KWISPLE_SITE | ci-token | The linked site, from .env.local / .env or the environment. |
KWISPLE_CONFIG_DIR, XDG_CONFIG_HOME, APPDATA | credentials | Where credentials.json lives. |
CI, SSH_CONNECTION | login | When set, no browser is opened. |
kwisple dev sets KWISPLE_SCHEMA=dev for the dev server it starts. Never set it in
production. All variables of a site project are listed in
Environment variables and tokens.