@pageloop/cli
v0.6.1
Published
The `pageloop` command — the operator + agent CLI for PageLoop. Same dispatch path the web admin uses, but runs without a long-lived server process: one-shot tasks (login, create a project, read a page's tasks), self-host server management, and CI scripts
Readme
@pageloop/cli
The pageloop command — the operator + agent CLI for PageLoop. Same
dispatch path the web admin uses, but runs without a long-lived server
process: one-shot tasks (login, create a project, read a page's tasks),
self-host server management, and CI scripts.
pageloop --help
pageloop <command> --helpThe CLI is concise by design: every required value is an optional flag. Anything you don't pass is taken from your config file (below), an env var, or — when you're at a terminal — an interactive prompt. So
pageloop loginwith no flags just asks you what it needs.
Configuration & defaults
How a value is resolved
For every argument, in order (first match wins):
- the flag you passed (
--endpoint …) - the matching env var (
PAGELOOP_ENDPOINT,PAGELOOP_TOKEN) - the merged config file (see below)
- a built-in default (e.g. endpoint →
https://pageloop.dev) - an interactive prompt (only at a TTY; shows the default in
[brackets])
Non-interactive runs (CI, pipes) never prompt — they use the default or exit with a clear "pass it as a flag" error.
The config file
Optional JSON holding your default arguments so you don't repeat them. Layers merge, later overriding earlier:
| Layer | Path | Scope |
|---|---|---|
| global | ~/.config/pageloop.json (or $XDG_CONFIG_HOME/pageloop.json) | all projects, this machine |
| local | ./pageloop.json | the current project directory |
| explicit | --config <path> | one invocation |
// ~/.config/pageloop.json
{
"endpoint": "https://pageloop.dev", // default server (the global service)
"projectId": "my-docs", // default --project for project-scoped commands
"email": "[email protected]" // sign-in convenience
}Anything still missing for the command you run is prompted for, leaning on these as the prompt defaults.
Endpoint
The endpoint defaults to https://pageloop.dev (the hosted service).
Override per-command with --endpoint, per-machine with the config file,
or pin one with pageloop server default --endpoint <url>. Self-hosters
set their own URL during pageloop setup.
Session / login
pageloop login validates and caches a bearer token at
~/.config/pageloop/token (mode 0600), keyed to the endpoint it was
issued for. Subsequent commands pick it up automatically. If a token has
expired, commands fail with a clear hint to re-run pageloop login
--endpoint <url> (your endpoint is retained).
Getting started
pageloop setup # wire the current directory to a project (interactive)
pageloop login # sign in (prompts for endpoint → defaults to pageloop.dev)
pageloop project create # create a project (prompts for slug / name / owner)
pageloop go # self-host: run setup if needed, then start the serverpageloop setup asks for your default endpoint (offering
https://pageloop.dev) and writes it, plus your project details, into a
pageloop.json so later commands need no flags.
Server management (self-host)
| Command | Purpose |
|---|---|
| pageloop server start [-D] | Run the HTTP transport (RPC + WS + SSE). -D/--daemon for background. |
| pageloop server init | First-boot bootstrap — DB + default org/project. Idempotent. |
| pageloop server default --endpoint <url> | Pin the default endpoint (--clear to forget). |
| pageloop server status / stop | Daemon liveness / shutdown. |
| pageloop server update | On a server install: git pull → install → build → migrate → restart. |
Projects + organizations
pageloop projects # list projects you can see on the server
pageloop project create # prompts for slug / name / owner-email
pageloop project create --slug my-docs --name "My Docs" --owner-email [email protected]
pageloop project [--slug my-docs] # info for one project (defaults to ./pageloop.json)project create goes over HTTP (auth + policy + audit) by default. Pass
--db <url> instead for an operator-direct local write (first-boot
bootstrap only) — it never mixes with --endpoint.
Pages + page groups
| Command | Purpose |
|---|---|
| pageloop page list [--project <slug>] | List a project's pages (remote by default; --db for local). |
| pageloop page comments --id <pageId> | Print a page's comments as JSON — see below. |
| pageloop page rename --project <s> --page <id-or-key> --to <key> | Rekey a page. |
| pageloop page migrate --project <s> --root <dir> --strategy <s> | Bulk rekey. |
| pageloop page move-to-group --project <s> --page <id> [--group <n>] [--create] | Re-parent a page. |
| pageloop group list / create / rename / move / trash --project <s> … | Page folders. |
Reading comments + tasks (for agents)
Pull a page's comments as raw JSON. The short way is just the page id — the server resolves the project and checks your read access:
# Every unresolved task on a page (an agent's open to-do list):
pageloop page comments --id <pageId> --unresolved--unresolved is shorthand for --task --task-status unresolved. Drop
it to get all comments; use --task for all tasks regardless of state,
or --task-status resolved for completed ones. Output is a JSON array,
ready to pipe into jq or an agent.
| Flag | Effect |
|---|---|
| --id <pageId> | The tracked page id (prompted if omitted). |
| --unresolved | Only open tasks. Shorthand for --task --task-status unresolved. |
| --task | Only comments promoted to tasks (resolved or not). |
| --task-status <unresolved\|resolved> | Narrow tasks to a completion state. |
| --endpoint <url> / --token <jwt> / --config <path> | Standard resolution (defaults to your session). |
Under the hood this hits the convenience REST endpoint, which also
accepts the pageId form directly:
curl -s -G "https://pageloop.dev/api/v1/comments" \
-H "Authorization: Bearer $PAGELOOP_TOKEN" \
--data-urlencode "pageId=<pageId>" \
--data-urlencode "taskStatus=unresolved"The older projectId=<slug>&pageKey=<key> form still works. Response is
{ "comments": Comment[] }. Mutate a task via the RPC
comments.setTask({ commentId, isTask?, resolved? }).
Authentication
pageloop login # interactive: prompts for endpoint, opens a browser (loopback OAuth)
pageloop login --github # force a provider
pageloop login --no-browser # copy-paste fallback (headless / SSH)
pageloop login --token <jwt> # accept a token directly (CI)
pageloop whoami # endpoint + user (never prints the token)
pageloop logoutRepositories
# Connect an existing repository to a project.
pageloop repo add --project my-docs --remote-url https://github.com/me/docs
pageloop repo list --project my-docs
pageloop repo sync --repo-id <repo-id>
# Scout paths, then import files as tracked pages (folders → page groups).
pageloop repo browse my-docs docs/api --branch develop
pageloop repo import my-docs docs/ --include md,html
pageloop repo import my-docs docs/ --include md --flatten # everything at root
pageloop repo import my-docs docs/ --include md --dry-run # preview onlyImport flags:
| Flag | Meaning |
|---|---|
| --branch <name> | Read from this branch instead of the repo's default. |
| --flatten | All files at project root; clashes auto-rename name (2).ext. |
| --include <ext,…> / --exclude <ext,…> | Whitelist / blacklist extensions (no dot). Exclude wins. |
| --exclude-path <frag,…> | Skip paths containing any substring. |
| --conflict <skip\|overwrite\|rename> | Already-tracked path behaviour (default skip). A trashed match is always restored. |
| --dry-run | Preview bucket counts; write nothing. |
repo import writes directly via the persistence adapter as a synthetic
superadmin — anyone with shell access to the DB can run it.
Static-site injection
# From your site root — patches every .html, no snippet to paste.
pageloop inject --project my-docs --endpoint https://pageloop.dev
pageloop inject "blog/**/*.html" --project my-docs --channel 0.3 # scope + pin a track
pageloop uninject --root . "**/*.html" # byte-clean removalinject appends one self-contained loader <script> that pulls the
current widget bundle + CSS and auto-updates (rolling back on a bad
release). Re-running is idempotent. pageloop setup --inject does
register-then-inject for a new project in one step. SPAs skip this —
import the widget once at the app root.
Other
| Command | Purpose |
|---|---|
| pageloop admin --email <e> | Promote a user to platform-superadmin (direct DB; first-boot). |
| pageloop token --email <e> | Issue a long-lived JWT for testing / CI (direct DB). |
| pageloop project list / page list --db <url> | Operator-direct local-DB reads (bypass the server). |
| pageloop migrate-data --from <url> --to <url> | Bulk-copy rows between backends (SQLite ⇄ Postgres). Idempotent. |
| pageloop publish [--root <p>] [--version <v>] [--channels <list>] [--dry-run] | Publish a widget bundle to a CDN root + channels. |
Operator-direct commands accept --db <url> (default
sqlite:./.pageloop/pageloop.db) and --secret <jwt-secret>
($PAGELOOP_JWT_SECRET). They share the running server's handlers + DB
locking, so a concurrent server + CLI mutation is safe.
