12 KiB
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
clojure -M:cljs compile logseq-cli db-worker-node
yarn db-worker-node:release:bundle
yarn db-worker-node:release:bundle compiles and bundles db-worker-node with @vercel/ncc, 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-nodeand lock-file protocol for a graph. - Disk SQLite under
~/logseq/graphsis the source of truth; OPFS periodic export is not part of the desktop primary write path. - If a daemon already exists for the graph, CLI reuses it via lock-file discovery instead of starting a second writer.
- If lock ownership is invalid or stale, startup cleans stale lock state before retrying.
- Lock metadata includes an
owner-sourcevalue (cli,electron,unknown) and lifecycle actions enforce owner boundaries. server stopandserver restartare owner-aware: CLI can only stop/restart servers it owns (or legacyunknownownership).- If lock is missing but a matching orphan
db-worker-nodeprocess still exists for the same repo/data-dir, startup performs orphan cleanup before retrying.
Run the CLI
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:
logseq graph list
Configuration
Optional configuration file: ~/logseq/cli.edn
Default data dir: ~/logseq/graphs.
Graph directories on disk are stored as user-facing graph names (for example, demo/), not logseq_db_ prefixed repo identifiers.
Migration note: If you previously used ~/.logseq/cli-graphs or ~/.logseq/cli.edn, pass --data-dir or --config to continue using those locations.
Supported keys include:
:repo:data-dir:timeout-ms:output-format(use:jsonor:ednfor scripting)
CLI flags take precedence over environment variables, which take precedence over the config file.
Verbose logging:
--verboseenables structured debug logs to stderr for CLI option parsing and db-worker-node API calls.- stdout remains reserved for command output; large payloads are truncated in debug previews.
Commands
Graph commands:
graph list- list all db graphsgraph create --repo <name>- create a new db graph and switch to itgraph switch --repo <name>- switch current graphgraph remove --repo <name>- remove a graphgraph validate --repo <name>- validate graph datagraph info [--repo <name>]- show graph metadata (defaults to current graph)graph export --type edn|sqlite --output <path> [--repo <name>]- export a graph to EDN or SQLitegraph import --type edn|sqlite --input <path> --repo <name>- import a graph from EDN or SQLite (new graph only)
For any command that requires --repo, if the target graph does not exist, the CLI returns graph not exists (except for graph create). graph import fails if the target graph already exists.
Server commands:
server list- list running db-worker-node serversserver status --repo <name>- show server status for a graphserver start --repo <name>- start db-worker-node for a graphserver stop --repo <name>- stop db-worker-node for a graphserver restart --repo <name>- restart db-worker-node for a graphdoctor [--dev-script]- run runtime diagnostics fordb-worker-node.js,data-dirpermissions, and running server readiness (--dev-scriptchecksstatic/db-worker-node.jsexplicitly)
Server ownership behavior:
server stopandserver restartcan returnserver-owned-by-otherif the daemon was started by another owner source.server startcan returnserver-start-timeout-orphanwhen lock creation times out and orphan matching processes are detected.server listhuman output includes anOWNERcolumn, andserver status/server listinclude owner metadata in structured output (--output json|edn).
Inspect and edit commands:
list page [--expand] [--limit <n>] [--offset <n>] [--sort <field>] [--order asc|desc]- list pageslist tag [--expand] [--limit <n>] [--offset <n>] [--sort <field>] [--order asc|desc]- list tagslist property [--expand] [--limit <n>] [--offset <n>] [--sort <field>] [--order asc|desc]- list properties (TYPEis included by default even without--expand)upsert block --content <text> [--target-page <name>|--target-id <id>|--target-uuid <uuid>] [--pos first-child|last-child|sibling]- create blocks; defaults to today’s journal page if no target is givenupsert block --blocks <edn> [--target-page <name>|--target-id <id>|--target-uuid <uuid>] [--pos first-child|last-child|sibling]- insert blocks via EDN vectorupsert block --blocks-file <path> [--target-page <name>|--target-id <id>|--target-uuid <uuid>] [--pos first-child|last-child|sibling]- insert blocks from an EDN fileupsert block --id <id>|--uuid <uuid> [--target-id <id>|--target-uuid <uuid>|--target-page <name>] [--pos first-child|last-child|sibling] [--update-tags <edn-vector>] [--update-properties <edn-map>] [--remove-tags <edn-vector>] [--remove-properties <edn-vector>]- update and/or move a blockupsert page --page <name> [--update-tags <edn-vector>] [--update-properties <edn-map>] [--remove-tags <edn-vector>] [--remove-properties <edn-vector>]- create (or update by page name) a pageupsert page --id <id> [--update-tags <edn-vector>] [--update-properties <edn-map>] [--remove-tags <edn-vector>] [--remove-properties <edn-vector>]- update a page by id (cannot be combined with--page)upsert tag --name <name>- create or upsert a tag by nameupsert tag --id <id> [--name <name>]- validate a tag by id; when--nameis provided, rename that tag id (no-op if normalized name is unchanged)upsert tag --id <id> --name <name>conflicts: returnstag-name-conflictwhen target name is a non-tag page, andtag-rename-conflictwhen target name is another existing tagupsert property --name <name> [--type <type>] [--cardinality one|many] [--hide true|false] [--public true|false]- create or update a property by nameupsert property --id <id> [--type <type>] [--cardinality one|many] [--hide true|false] [--public true|false]- update a property by idmove --id <id>|--uuid <uuid> --target-id <id>|--target-uuid <uuid>|--target-page <name> [--pos first-child|last-child|sibling]- move a block and its children (defaults to first-child)remove --id <id>|--uuid <uuid>|--page <name>- remove blocks (by db/id or UUID) or pagessearch <query> [--type page|block|tag|property|all] [--tag <name>] [--case-sensitive] [--sort updated-at|created-at] [--order asc|desc]- search across pages, blocks, tags, and properties (query is positional)query --query <edn> [--inputs <edn-vector>]- run a Datascript query against the graphquery --name <query-name> [--inputs <edn-vector>]- run a named query (built-in or fromcli.edn)query list- list available named queriesshow --page <name> [--level <n>]- show page treeshow --uuid <uuid> [--level <n>]- show block treeshow --id <id> [--level <n>]- show block tree by db/id
Help output:
Subcommands:
list page [options] List pages
list tag [options] List tags
list property [options] List properties
upsert block [options] Upsert block
upsert page [options] Upsert page
upsert tag [options] Upsert tag
upsert property [options] Upsert property
move [options] Move block
remove [options] Remove block or page
search <query> [options] Search graph
show [options] Show tree
Options grouping:
- Help output separates Global options (apply to all commands) and Command options (command-specific flags).
Version output:
logseq --versionprints:
Build time: <timestamp>
Revision: <commit>
Output formats:
- Global
--output <human|json|edn>applies to all commands - For
graph export,--outputrefers to the destination file path. Output formatting is controlled via:output-formatin config orLOGSEQ_CLI_OUTPUT. - Human output is plain text. List/search commands render tables with a final
Count: Nline. For list and search subcommands, the ID column uses:db/id(not UUID). If:db/identexists, anIDENTcolumn is included.list propertyincludes a dedicatedTYPEcolumn. Search table columns areIDandTITLE. Block titles can include multiple lines; multi-line rows align additional lines under theTITLEcolumn. Times such as listUPDATED-AT/CREATED-ATandgraph infoCreated atare shown in human-friendly relative form. Errors include error codes and may include aHint:line. Use--output json|ednfor structured output. - For
list property,TYPEis returned in default output (without--expand) for human and structured (json/edn) formats. upsert pageandupsert blockreturn entity ids indata.resultfor JSON/EDN output, and include ids in human output.- Human example:
Upserted page: [123] - Human example:
Upserted blocks: [201 202] - JSON example:
{"status":"ok","data":{"result":[123]}} - EDN example:
{:status :ok, :data {:result [123]}}
- Human example:
doctoroutput includes overall status (ok,warning,error) and per-check rows fordb-worker-script,data-dir, andrunning-servers. For scripting,--output json|ednkeeps the structured check payload.- Common doctor failures:
doctor-script-missing:db-worker-node.jsruntime target is missing (default target:dist/db-worker-node.js; usedoctor --dev-scriptto checkstatic/db-worker-node.js).doctor-script-unreadable: script path exists but is not a readable file.data-dir-permission: configured data dir is not readable or writable.doctor-server-not-ready: one or more lock-discovered servers are still in:startingstate (warning).- If bundled runtime startup fails with missing-module or missing-file errors, rebuild with
yarn db-worker-node:release:bundleand confirmdist/db-worker-node.jsexists and every path listed indist/db-worker-node-assets.jsonis present next to it.
queryhuman output returns a plain string (the query result rendered viapr-str), which is convenient for pipelines likelogseq query ... | xargs logseq show --id.- Built-in named queries currently include
block-search,task-search,recent-updated,list-status, andlist-priority. Usequery listto see the full set for your config. - Show and search outputs resolve block reference UUIDs inside text, replacing
[[<uuid>]]with the referenced block content. Nested references are resolved recursively up to 10 levels to avoid excessive expansion. For example:[[<uuid1>]]→[[some text [[<uuid2>]]]]and then<uuid2>is also replaced. showhuman output prints the:db/idas the first column followed by a tree:
id1 block1
id2 ├── b2
id3 │ └── b3
id4 ├── b4
id5 │ ├── b5
id6 │ │ └── b6
id7 │ └── b7
id8 └── b8
Examples:
node ./dist/logseq.js graph create --repo demo
node ./dist/logseq.js graph export --type edn --output /tmp/demo.edn --repo demo
node ./dist/logseq.js graph import --type edn --input /tmp/demo.edn --repo demo-import
node ./dist/logseq.js upsert block --target-page TestPage --content "hello world"
node ./dist/logseq.js move --uuid <uuid> --target-page TargetPage
node ./dist/logseq.js search "hello"
node ./dist/logseq.js show --page TestPage --output json
node ./dist/logseq.js server list
node ./dist/logseq.js doctor
node ./dist/logseq.js doctor --dev-script
node ./dist/logseq.js doctor --output json