18 KiB
Logseq CLI Sync Command Implementation Plan
Goal: Add logseq sync subcommands to inspect and operate db-sync through existing db-worker-node APIs.
Architecture: The CLI parser and executor will gain a dedicated sync command module that maps subcommands to :thread-api/db-sync-* calls via /v1/invoke.
Architecture: A small worker API addition will expose runtime sync status, and sync config commands will support headless token setup through CLI-managed config values.
Architecture: The design will reuse existing graph lock and repo binding behavior in logseq.cli.server/ensure-server! and frontend.worker.db-worker-node/repo-error.
Tech Stack: ClojureScript, babashka.cli, promesa, db-worker-node HTTP API, frontend.worker.sync.
Related: Builds on docs/agent-guide/031-logseq-cli-doctor-command.md, docs/agent-guide/033-desktop-db-worker-node-backend.md, and docs/agent-guide/034-db-worker-node-owner-process-management.md.
Problem statement
The current CLI exposes graph, server, doctor, list, upsert, remove, query, and show commands, but it does not expose db-sync control or observability.
frontend.worker.db-core already exposes operational db-sync thread APIs such as :thread-api/db-sync-start, :thread-api/db-sync-stop, :thread-api/db-sync-upload-graph, and :thread-api/db-sync-grant-graph-access.
frontend.worker.db-worker-node already routes these methods over /v1/invoke with repo-lock safety checks, so the missing piece is a CLI command surface and one read API for status inspection.
This plan keeps scope tight by reusing current transport and server lifecycle code, and only adds new worker behavior where inspection data is currently unavailable.
I will use @planning-documents for naming, @writing-plans for task granularity, @logseq-cli for CLI integration expectations, and @test-driven-development for implementation sequence.
Testing Plan
I will add parser and action unit tests that fail first for new sync command help, option validation, and action shaping.
I will add command execution tests that fail first and verify logseq.cli.transport/invoke receives the exact method names and argument shapes for each sync subcommand.
I will add format tests that fail first and verify human output for sync status and action commands, while keeping JSON and EDN behavior unchanged.
I will add worker API tests that fail first for the new sync inspection API exposed through /v1/invoke.
I will add one CLI integration test that fails first and verifies an end-to-end sync status flow on a temp graph and a started db-worker-node process.
I will run targeted tests after each behavior slice and then run bb dev:lint-and-test before final review.
NOTE: I will write all tests before I add any implementation behavior.
Scope and CLI surface
| CLI command | Purpose | Worker method | Repo required |
|---|---|---|---|
sync status [--graph <name>] |
View current db-sync runtime state and counters. | :thread-api/db-sync-status (new). |
Yes. |
sync start [--graph <name>] |
Start db-sync websocket client for the graph. | :thread-api/db-sync-start. |
Yes. |
sync stop [--graph <name>] |
Stop db-sync client for the running daemon. | :thread-api/db-sync-stop. |
Yes, to target a graph daemon deterministically. |
sync upload [--graph <name>] |
Upload current graph snapshot and mark graph remote metadata. | :thread-api/db-sync-upload-graph. |
Yes. |
sync download [--graph <name>] |
Download remote graph data and apply it to local graph storage. | :thread-api/db-sync-download-graph (new). |
Yes. |
sync remote-graphs |
List remote graphs visible to current auth context. | :thread-api/db-sync-list-remote-graphs (new). |
No. |
sync ensure-keys |
Ensure user RSA keys required by e2ee are present. | :thread-api/db-sync-ensure-user-rsa-keys. |
No. |
sync grant-access --graph-id <uuid> --email <email> [--graph <name>] |
Grant encrypted graph key access to a target user email. | :thread-api/db-sync-grant-graph-access. |
Yes. |
sync config set <name> <value> |
Set one config value by key. | :thread-api/set-db-sync-config. |
No. |
sync config get <name> |
Read one config value by key. | :thread-api/get-db-sync-config (new). |
No. |
sync config unset <name> |
Remove one config value by key. | :thread-api/set-db-sync-config. |
No. |
The first release intentionally excludes asset download and raw kv import commands because they need more user-facing safety rails and payload tooling.
sync config set supports ws-url, http-base, and auth-token, and config set auth-token <token-value> is the headless authentication entrypoint.
sync config get and sync config unset reject unknown config keys.
sync status will return normalized fields even when sync is not configured, so scripts can branch deterministically.
sync remote-graphs and sync download require auth-token to be configured in headless mode.
Architecture and integration points
logseq sync <subcommand>
-> /Users/rcmerci/gh-repos/logseq/src/main/logseq/cli/commands.cljs (parse/build/execute)
-> /Users/rcmerci/gh-repos/logseq/src/main/logseq/cli/command/sync.cljs (new)
-> /Users/rcmerci/gh-repos/logseq/src/main/logseq/cli/server.cljs (ensure graph daemon)
-> /Users/rcmerci/gh-repos/logseq/src/main/logseq/cli/transport.cljs (POST /v1/invoke)
-> /Users/rcmerci/gh-repos/logseq/src/main/frontend/worker/db_worker_node.cljs (repo checks + invoke)
-> /Users/rcmerci/gh-repos/logseq/src/main/frontend/worker/db_core.cljs thread APIs
-> /Users/rcmerci/gh-repos/logseq/src/main/frontend/worker/sync.cljs and sync/crypt.cljs
Worker additions will be minimal, with no protocol changes to cloud endpoints.
CLI additions will follow existing graph and server command module patterns for spec, entries, build-action, and execute-* helpers.
Implementation plan
Phase 1. Add failing parser and help tests.
- Add a failing assertion in
/Users/rcmerci/gh-repos/logseq/src/test/logseq/cli/commands_test.cljsthat top-level help includessyncandsync status. - Add a failing assertion in
/Users/rcmerci/gh-repos/logseq/src/test/logseq/cli/commands_test.cljsthatlogseq syncshows subgroup help likeserverandgraph. - Add a failing assertion in
/Users/rcmerci/gh-repos/logseq/src/test/logseq/cli/commands_test.cljsthatsync config set|get|unsetandsync grant-accessshow in sync group help. - Run
bb dev:test -v logseq.cli.commands-test/test-help-outputand confirm failure references missingsynccommand rows.
Phase 2. Add failing action and execution tests for sync command module.
- Create
/Users/rcmerci/gh-repos/logseq/src/test/logseq/cli/command/sync_test.cljswith failing tests forbuild-actiongraph requirement onsync status. - Add a failing test for
build-actionrejection whensync config setis missing name or value. - Add a failing test for
build-actionrejection whensync grant-accessmisses--graph-idor--email. - Add a failing test for
build-actiongraph requirement onsync download. - Add a failing execution test that stubs
logseq.cli.server/ensure-server!andlogseq.cli.transport/invokeand expects:thread-api/db-sync-startwith[repo]. - Add a failing execution test that expects
:thread-api/db-sync-stopwith[]and still routes throughensure-server!using selected repo. - Add a failing execution test that expects
:thread-api/db-sync-upload-graphwith[repo]. - Add a failing execution test that expects
:thread-api/db-sync-download-graphwith[repo]. - Add a failing execution test that expects
:thread-api/db-sync-list-remote-graphsforsync remote-graphs. - Add a failing execution test that expects
:thread-api/db-sync-ensure-user-rsa-keyswithout repo. - Add a failing execution test that expects
:thread-api/db-sync-grant-graph-accesswith[repo graph-id email]. - Add a failing execution test that expects
:thread-api/get-db-sync-configforsync config get <name>. - Add a failing execution test that expects
:thread-api/set-db-sync-configforsync config set <name> <value>and payload merge behavior. - Add a failing execution test that expects
:thread-api/set-db-sync-configforsync config unset <name>and key removal behavior. - Add a failing execution test that verifies
sync config set auth-token <token-value>updates worker-consumable token config for headless mode. - Run
bb dev:test -v logseq.cli.command.sync-testand confirm failures are only from missing sync implementation.
Phase 3. Implement CLI sync command wiring.
- Add
/Users/rcmerci/gh-repos/logseq/src/main/logseq/cli/command/sync.cljswith sync option specs,entries,build-action, andexecute-*functions. - Register
sync-command/entriesin/Users/rcmerci/gh-repos/logseq/src/main/logseq/cli/commands.cljscommand table. - Extend
finalize-commandin/Users/rcmerci/gh-repos/logseq/src/main/logseq/cli/commands.cljswith sync-specific required-option checks. - Extend single-token group help routing in
/Users/rcmerci/gh-repos/logseq/src/main/logseq/cli/commands.cljsto includesync. - Extend
build-actiondispatch in/Users/rcmerci/gh-repos/logseq/src/main/logseq/cli/commands.cljsto callsync-command/build-action. - Extend
executedispatch in/Users/rcmerci/gh-repos/logseq/src/main/logseq/cli/commands.cljsto route sync action types. - Add
syncto top-level command grouping in/Users/rcmerci/gh-repos/logseq/src/main/logseq/cli/command/core.cljs. - Run
bb dev:test -v logseq.cli.commands-test/test-parse-args-helpandbb dev:test -v logseq.cli.command.sync-testuntil green.
Phase 4. Add read-only worker APIs for sync inspection.
- Add a failing worker test in
/Users/rcmerci/gh-repos/logseq/src/test/frontend/worker/db_worker_node_test.cljsthat/v1/invokeacceptsthread-api/get-db-sync-configwithout repo. - Add a failing worker test in
/Users/rcmerci/gh-repos/logseq/src/test/frontend/worker/db_worker_node_test.cljsthat/v1/invokeforthread-api/db-sync-statusenforces repo and returns structured status. - Add
:thread-api/get-db-sync-configin/Users/rcmerci/gh-repos/logseq/src/main/frontend/worker/db_core.cljsreturning current config map. - Add
:thread-api/db-sync-statusin/Users/rcmerci/gh-repos/logseq/src/main/frontend/worker/db_core.cljsreturning ws state, graph id, and sync counters for a repo. - Add or expose a small helper in
/Users/rcmerci/gh-repos/logseq/src/main/frontend/worker/sync.cljsto compute status without requiring websocket side effects. - Add
:thread-api/db-sync-list-remote-graphsin/Users/rcmerci/gh-repos/logseq/src/main/frontend/worker/db_core.cljsand implement cloud graph listing through worker sync HTTP helpers. - Add
:thread-api/db-sync-download-graphin/Users/rcmerci/gh-repos/logseq/src/main/frontend/worker/db_core.cljsand implement remote snapshot download plus local import flow. - Update worker sync auth token resolution so
sync config set auth-token <token-value>is used in headless mode when state token is missing. - Register
:thread-api/get-db-sync-configand:thread-api/db-sync-list-remote-graphsinnon-repo-methodsin/Users/rcmerci/gh-repos/logseq/src/main/frontend/worker/db_worker_node.cljs. - Run
bb dev:test -v frontend.worker.db-worker-node-testand fix only sync-related regressions.
Phase 5. Add output formatting tests and implementation.
- Add failing tests in
/Users/rcmerci/gh-repos/logseq/src/test/logseq/cli/format_test.cljsfor human output ofsync status. - Add failing tests in
/Users/rcmerci/gh-repos/logseq/src/test/logseq/cli/format_test.cljsfor human output ofsync remote-graphs. - Add failing tests in
/Users/rcmerci/gh-repos/logseq/src/test/logseq/cli/format_test.cljsfor human output of sync action commands such as start, upload, and download. - Add failing tests in
/Users/rcmerci/gh-repos/logseq/src/test/logseq/cli/format_test.cljsverifying token redaction forsync config get auth-tokenin human output. - Implement sync human formatters in
/Users/rcmerci/gh-repos/logseq/src/main/logseq/cli/format.cljswith stable keys and token redaction. - Confirm JSON and EDN output behavior by running
bb dev:test -v logseq.cli.format-test.
Phase 6. Add integration coverage and CLI docs.
- Add a failing integration test in
/Users/rcmerci/gh-repos/logseq/src/test/logseq/cli/integration_test.cljsthat creates a graph and runssync statuswith--output json. - Add a failing integration test in
/Users/rcmerci/gh-repos/logseq/src/test/logseq/cli/integration_test.cljsforsync config set auth-tokenthensync config get auth-tokenbehavior. - Add a failing integration test in
/Users/rcmerci/gh-repos/logseq/src/test/logseq/cli/integration_test.cljsforsync config unset auth-token. - Add a failing integration test in
/Users/rcmerci/gh-repos/logseq/src/test/logseq/cli/integration_test.cljsforsync remote-graphs --output json. - Add a failing integration test in
/Users/rcmerci/gh-repos/logseq/src/test/logseq/cli/integration_test.cljsforsync download --graph <name>flow with mocked remote snapshot response. - Implement any missing glue for integration stability in
/Users/rcmerci/gh-repos/logseq/src/main/logseq/cli/command/sync.cljs. - Update
/Users/rcmerci/gh-repos/logseq/docs/cli/logseq-cli.mdcommand docs with sync command examples and error behaviors. - Run
bb dev:test -v logseq.cli.integration-testto verify end-to-end behavior.
Phase 7. Final verification and cleanup.
- Run
bb dev:lint-and-testfrom/Users/rcmerci/gh-repos/logseqand confirm exit code0. - Run manual smoke commands with a temp graph and confirm both
--output humanand--output jsonare stable. - Review help text alignment and command ordering to match existing CLI aesthetics.
Edge cases and error handling
sync status must return a valid map even when :ws-url is missing, with an explicit inactive state rather than throwing.
sync start must keep current behavior where missing ws-url or missing graph uuid results in no crash and a deterministic status response.
sync grant-access must surface cloud errors with existing http-error path and preserve status code and body context.
sync config get auth-token must redact token values in human output while keeping full value available in JSON and EDN output for scripting.
sync config set auth-token <token-value> must write to the config file selected by --config (default ~/logseq/cli.edn) so headless auth survives daemon restarts.
sync remote-graphs must return a deterministic empty list when user has no remote graphs instead of returning nil.
sync download must fail fast when the target local graph is missing required auth or remote graph metadata, and must report a clear sync-specific error code.
Repo mismatch and lock ownership behavior must remain enforced by db-worker-node and must not be bypassed in CLI command code.
All new options must keep kebab-case keyword naming and avoid introducing _ forms.
Verification commands
| Command | Expected outcome |
|---|---|
bb dev:test -v logseq.cli.command.sync-test |
Sync command unit tests pass with no failures. |
bb dev:test -v logseq.cli.commands-test/test-help-output |
Help output includes sync group and subcommands. |
bb dev:test -v frontend.worker.db-worker-node-test |
Worker invoke tests pass including new sync read APIs. |
bb dev:test -v logseq.cli.format-test |
Human and structured output tests pass including sync formatters. |
bb dev:test -v logseq.cli.integration-test |
CLI integration tests pass for sync status and config flow. |
bb dev:lint-and-test |
Full lint and unit suite passes with exit code 0. |
node ./dist/logseq.js sync status --graph demo --output json |
Returns {"status":"ok","data":...} with sync status fields. |
node ./dist/logseq.js sync remote-graphs --output json |
Returns remote graph list in structured output. |
node ./dist/logseq.js sync download --graph demo |
Downloads remote graph snapshot and imports it into local graph data. |
node ./dist/logseq.js sync config set auth-token <token-value> |
Sets headless auth token for db-sync API calls. |
node ./dist/logseq.js sync config get auth-token --output json |
Returns configured token value in structured output. |
node ./dist/logseq.js sync config unset auth-token |
Removes configured token and returns success message. |
Testing Details
The new tests verify behavior at parser level, action-building level, transport payload level, worker invoke contract level, output formatting level, and end-to-end CLI invocation level.
The tests assert external behavior such as command availability, returned status payloads, and worker method invocations, instead of asserting internal helper implementation details.
Implementation Details
- Add new file
/Users/rcmerci/gh-repos/logseq/src/main/logseq/cli/command/sync.cljsfor sync command ownership. - Keep
synccommand wiring inside existing dispatch points incommands.cljsand do not introduce a second dispatcher. - Add core worker sync inspection APIs,
get-db-sync-configanddb-sync-status, and reuse existingset-db-sync-configfor config writes. - Add worker sync APIs for remote graph listing and graph download to support
sync remote-graphsandsync download. - Reuse
transport/invokewith existingdirect-pass?handling and default to transit mode. - Keep
sync statusoutput fields stable for scripting, includingrepo,graph-id,ws-state, and pending counters. - Keep human output terse and redact auth-token values.
- Update
command.core/top-level-summaryand group-help routing sosyncbehaves like existing command groups. - Keep all new keyword names kebab-case and avoid shadowed local names such as
bytes. - Update
docs/cli/logseq-cli.mdwith command list, examples, and expected error hints. - Run full lint and tests after targeted green passes.
Question
No open question.
This plan adopts option A and includes sync config set|get|unset with config set auth-token <token-value> as the token setup path.