# Logseq CLI (Node) The Logseq CLI is a Node.js program compiled from ClojureScript that connects to a db-worker-node server managed by the CLI. When installed, the CLI binary name is `logseq`. ## Build the CLI ```bash clojure -M:cljs compile logseq-cli pnpm db-worker-node:release:bundle ``` `pnpm db-worker-node:release:bundle` compiles and bundles `db-worker-node` with Vite, and writes a standalone runtime to `dist/db-worker-node.js` plus an asset manifest at `dist/db-worker-node-assets.json` (which may contain an empty `assets` array when no extra files are required). ## db-worker-node lifecycle `logseq` manages `db-worker-node` automatically. You should not start the server manually. The server binds to localhost on a random port and records that port in the repo lock file. Desktop + CLI shared semantics: - Electron desktop and CLI are expected to use the same `db-worker-node` and lock-file protocol for a graph. - Disk SQLite under `~/logseq/graphs` is the source of truth; OPFS periodic export is not part of the desktop primary write path. - If a daemon already exists for the graph and reports the same revision as the requester, CLI reuses it via lock-file discovery instead of starting a second writer. - If the discovered daemon reports a different revision, startup stops that exact server, starts a replacement from the requester's bundled runtime, and only returns a usable endpoint after the replacement reports the expected revision. - A proven revision mismatch may be stopped across owner sources for the same repo/root-dir. Matching-revision servers keep the normal owner boundary. - If lock ownership is invalid or stale, startup cleans stale lock state before retrying. - Lock metadata includes an `owner-source` value (`cli`, `electron`, `unknown`) and lifecycle actions enforce owner boundaries. - `server stop` and `server restart` are owner-aware: CLI can only stop/restart servers it owns (or legacy `unknown` ownership). - If lock is missing but a matching orphan `db-worker-node` process still exists for the same repo/root-dir, startup performs orphan cleanup before retrying. ## Run the CLI ```bash node ./dist/logseq.js graph list ``` You can also use npm link to make ./dist/logseq.js globally available, run: ``` npm link ``` If installed(or linked) globally, run: ```bash logseq graph list ``` ## Configuration The CLI config file defaults to `/cli.edn`, where `root-dir` defaults to `~/logseq`. Supported keys include: - `:graph` - The current active graph. Set this with `graph switch`. - `:root-dir` - CLI root directory. Default is `~/logseq`. - Graph data directory is derived as `/graphs`. - Config file default is derived as `/cli.edn`. - Server list file default is derived as `/server-list`. - Graph directories under `/graphs` are user-facing graph names e.g. `demo` and do not start with `logseq_db_`. - `:output-format` - Format for output. Default is `:human`. Use `:json` or `:edn` for scripting. - `:list-title-max-display-width` - For `:human` output, the max display width for TITLE column, defaulting to `40`. - `:http-base` - Http base domain for sync service. Interact with this via `sync config`. - `:ws-url` - Websocket url for sync service. Interact with this via `sync config`. - `:timeout-ms` - Request timeout in milliseconds. - `:login-timeout-ms` - Login callback timeout. Defaults to 5 minutes. - `:logout-timeout-ms` - Logout callback timeout. Defaults to 2 minutes. - `:custom-queries` - Map of custom queries which are run with `query --name`. See [below for more](#custom-queries). CLI global flags take precedence over environment variables, which take precedence over the config file. Here is a mapping of these three: | Config key | Environment variable | Global flag | | --- | --- | --- | | :graph | $LOGSEQ_CLI_GRAPH | --graph | | :root-dir | $LOGSEQ_CLI_ROOT_DIR | --root-dir | | :output-format | $LOGSEQ_CLI_OUTPUT | --output | | :timeout-ms | $LOGSEQ_CLI_TIMEOUT_MS | --timeout-ms | | :login-timeout-ms | $LOGSEQ_CLI_LOGIN_TIMEOUT_MS | n/a | | :logout-timeout-ms | $LOGSEQ_CLI_LOGOUT_TIMEOUT_MS | n/a | Legacy notes: * Migration note: If you previously used `~/.logseq/cli-graphs` or `~/.logseq/cli.edn`, pass `--root-dir` and/or `--config` to continue using equivalent custom locations. * `:e2ee-password` in `cli.edn` is ignored and removed silently during config read/update. Use `sync start --e2ee-password` or `sync download --e2ee-password` instead. * `cli.edn` no longer persists cloud auth tokens. CLI login state is stored separately in `~/logseq/auth.json`. ### Custom Queries Custom queries are defined in `:custom-queries` of a config file. This config is a map with the key as a query name and the value as a map with the following keys: * `:query` - Required datalog query as a vector. Queries can use built-in rules from `logseq.db.frontend.rules` by appending `%` to the `:in` part of a query. See `logseq.cli.command.query` for example queries. * `:doc` - Optional doc string describing the query. * `:inputs` - Optional vector of inputs where each input is a map. Valid keys for the map are `:name` and `:default`. This defines positional arguments to a query e.g. the arguments a user passes map to these inputs and the `:in` bindings in a `:query`. ## Authentication Use `logseq login` to authenticate the current machine with Logseq cloud. - `logseq login` starts a temporary callback server at `http://localhost:8765/auth/callback`, opens a browser to the Logseq Cognito Hosted UI, exchanges the returned authorization code, and writes `~/logseq/auth.json`. - `logseq logout` removes `~/logseq/auth.json`, opens a browser to the Cognito Hosted UI logout endpoint, and completes the browser logout flow at `http://localhost:8765/logout-complete`. - Sync commands still pass an in-memory runtime `:auth-token` to db-sync, but that token is now resolved from `auth.json` instead of `cli.edn`. Default auth file: `~/logseq/auth.json` Auth file contents include the persisted Cognito `id-token`, `access-token`, `refresh-token`, `expires-at`, `sub`, `email`, and `updated-at` values needed for headless refresh. Verbose logging: - `--verbose` enables structured debug logs to stderr for CLI option parsing and db-worker-node API calls. - `sync download` can stream realtime progress lines to stdout when progress is enabled; debug previews remain truncated. Timeouts: - `--timeout-ms` continues to control request timeout behavior for CLI transport. - Login callback timeout is controlled separately by `:login-timeout-ms` / `LOGSEQ_CLI_LOGIN_TIMEOUT_MS` and defaults to 5 minutes. - Logout callback timeout is controlled separately by `:logout-timeout-ms` / `LOGSEQ_CLI_LOGOUT_TIMEOUT_MS` and defaults to 2 minutes. ## Commands Graph commands: - `graph list` - list all db graphs - `graph create --graph ` - create a new db graph and switch to it - Fails with `graph-exists` if a local graph with the same name already exists - `--enable-sync` creates the graph, switches to it, uploads it to Logseq Sync, and starts sync in one command - `--e2ee-password ` is accepted only with `--enable-sync` and uses the same password verification path as `sync upload` and `sync start` - `graph switch --graph ` - switch current graph - `graph remove --graph ` - remove a graph - `graph validate --graph ` - validate graph data - `graph info [--graph ]` - show graph metadata (defaults to current graph) - `graph export --type edn|sqlite --file [--graph ]` - export a graph to EDN or SQLite - EDN export also accepts `--include-timestamps`, `--exclude-built-in-pages`, and `--exclude-namespaces ` - `--exclude-namespaces` trims CSV tokens, ignores empty tokens, removes duplicates, and can reduce backend export validation strictness - SQLite export writes the snapshot directly to the destination path through `db-worker-node` instead of round-tripping a base64 payload through the CLI - EDN-only export flags are rejected when `--type sqlite` is selected - `graph import --type edn|sqlite --input --graph ` - import a graph from EDN or SQLite (new graph only) - `graph backup list` - list backup snapshots under `/graphs//backup` - `graph backup create [--graph ] [--name