12 KiB
Logseq CLI debug Command Implementation Plan
Goal: Add a new debug command group with debug pull for low-level Datascript entity inspection via db-worker-node.
Goal: debug pull must support --graph <name> or default to current graph resolution already used by existing commands.
Goal: In global help (logseq --help), show debug under Utilities and do not show debug subcommands (same top-level-only behavior as example).
Architecture: Keep command parsing, validation, and output behavior in logseq-cli, and reuse existing db-worker-node invoke API :thread-api/pull with selector [*].
Architecture: Avoid adding new worker thread APIs unless we discover a hard blocker; current worker already exposes :thread-api/pull and supports lookup refs.
Tech Stack: ClojureScript, babashka.cli dispatch table, existing command pipeline in logseq.cli.commands (parse-args -> build-action -> execute), and existing CLI e2e spec harness.
Related:
/Users/rcmerci/gh-repos/logseq/src/main/logseq/cli/commands.cljs/Users/rcmerci/gh-repos/logseq/src/main/logseq/cli/command/core.cljs/Users/rcmerci/gh-repos/logseq/src/main/logseq/cli/command/show.cljs/Users/rcmerci/gh-repos/logseq/src/main/logseq/cli/command/id.cljs/Users/rcmerci/gh-repos/logseq/src/main/logseq/cli/transport.cljs/Users/rcmerci/gh-repos/logseq/src/main/frontend/worker/db_core.cljs/Users/rcmerci/gh-repos/logseq/src/test/logseq/cli/commands_test.cljs/Users/rcmerci/gh-repos/logseq/src/test/logseq/cli/completion_generator_test.cljs/Users/rcmerci/gh-repos/logseq/cli-e2e/spec/non_sync_inventory.edn/Users/rcmerci/gh-repos/logseq/cli-e2e/spec/non_sync_cases.edn
Problem statement
Today we have user-facing inspection commands (show, query), but no direct debug command that exposes a raw pull for a single entity selector path.
For debugging schema/data issues, we need a predictable command that can fetch one entity using either db id, uuid, or ident and return raw entity data.
The requested command is:
logseq debug pull --id <db-id>
logseq debug pull --uuid <uuid>
logseq debug pull --ident <db-ident>
with selector fixed to [*] and data source being the current graph DB served by db-worker-node.
Requested behavior contract
| Area | Requirement |
|---|---|
| Command shape | Add top-level debug group with subcommand pull. |
| Graph selection | Accept --graph globally; if omitted, use current graph resolution (same as existing commands using pick-graph). |
| Target selector | debug pull accepts exactly one of --id, --uuid, --ident. |
| Pull behavior | Execute :thread-api/pull with selector [*] and resolved lookup value. |
| Global help | logseq --help shows debug in Utilities and does not list debug pull there. |
| Group help | logseq debug and logseq debug --help show debug pull as subcommand. |
Current baseline
- Top-level help grouping is implemented in
/Users/rcmerci/gh-repos/logseq/src/main/logseq/cli/command/core.cljswithUtilitiescurrently configured as top-level-only and already hidingexamplesubcommands. - Graph fallback is implemented centrally via
logseq.cli.command.core/pick-graphand is already used inbuild-actionfor graph-scoped commands. db-worker-nodealready provides:thread-api/pullin/Users/rcmerci/gh-repos/logseq/src/main/frontend/worker/db_core.cljs:- accepts
(repo selector id) - supports integer ids and lookup refs (e.g.
[:db/ident kw],[:block/uuid uuid])
- accepts
- Existing command modules (
show,query) already demonstrate ensure-server + invoke flow and can be reused as implementation patterns.
Conclusion: this feature should be mostly CLI-side wiring; worker protocol changes are likely unnecessary.
CLI design proposal
1) New command namespace
Add /Users/rcmerci/gh-repos/logseq/src/main/logseq/cli/command/debug.cljs.
Planned entry:
debug pull(:debug-pull)
Planned command options:
--id(db id)--uuid(UUID string)--ident(strict EDN keyword string, e.g.:logseq.class/Tag)
Global options (--graph, --output, etc.) continue to come from command-entry merged global spec.
2) Selector normalization
debug pull resolves exactly one lookup target:
--id-> numeric entity id--uuid-> lookup ref[:block/uuid <uuid>]--ident-> lookup ref[:db/ident <keyword>]
Validation rules:
- exactly one of
--id,--uuid,--identis required - reject multiple selectors with clear invalid-options message
- reject invalid uuid / invalid id / invalid ident formats
--identaccepts only strict EDN keyword syntax with leading:
3) Action model
build-action output shape:
{:type :debug-pull
:repo <resolved repo>
:lookup <id-or-lookup-ref>
:selector '[*]}
repo resolution should reuse existing command pipeline behavior:
--graphfirst- then config current graph
- then repo fallback from config
4) Execute model
Execution pattern:
- ensure server for repo (
cli-server/ensure-server!) - invoke worker
:thread-api/pullwith[repo selector lookup] - return structured data payload (include selector metadata for traceability)
Suggested success payload:
{:entity <pulled-entity>
:lookup <normalized lookup>
:selector '[*]}
For missing entity, return a clear typed error (e.g. :entity-not-found) instead of silently returning nil.
Global help behavior plan
Update top-level-summary groups in /Users/rcmerci/gh-repos/logseq/src/main/logseq/cli/command/core.cljs:
- add
debugtoUtilitiescommand set - keep
:top-level-only? trueforUtilities - add
desc-overridesentry fordebugso top-level help renders stable one-line description (instead of inheriting fromdebug pulltext)
Expected top-level help effect:
- shows
debug - does not show
debug pull - remains consistent with current
examplevisibility behavior
Testing Plan (TDD)
I will follow @test-driven-development and write failing tests first.
Phase 1: Parser and help RED tests
- Extend
/Users/rcmerci/gh-repos/logseq/src/test/logseq/cli/commands_test.cljs:- top-level help includes
debug - top-level help does not include
debug pull Utilitiessection still listsexampleandcompletion
- top-level help includes
- Add group-help tests:
parse-args ["debug"]returns help summary containingdebug pull
- Add parse success tests:
debug pull --id 1debug pull --uuid <uuid>debug pull --ident :logseq.class/Tag
- Add parse failure tests:
- no selector
- multiple selectors
- malformed id / uuid / ident
Phase 2: Action and execute RED tests
- Add build-action tests in
commands_test.cljs:- uses
--graphwhen provided - falls back to current graph from config when
--graphomitted - returns missing-repo when neither explicit nor current graph exists
- uses
- Add execute tests (new file suggested:
/Users/rcmerci/gh-repos/logseq/src/test/logseq/cli/command/debug_test.cljs):- verifies invoke contract
:thread-api/pullwith selector[*] - verifies id/uuid/ident normalization to lookup argument
- verifies entity-not-found behavior
- verifies invoke contract
Phase 3: GREEN implementation
- Implement new namespace
command/debug.cljswith entries + build + execute. - Wire into
/Users/rcmerci/gh-repos/logseq/src/main/logseq/cli/commands.cljs:- include
debug-command/entriesin base table - finalize-command validation branch for selector constraints
- build-action case
:debug-pull - execute case
:debug-pull
- include
- Update
/Users/rcmerci/gh-repos/logseq/src/main/logseq/cli/command/core.cljstop-level group config forUtilitiesto includedebug(hidden subcommands at global help).
Phase 4: Completion and e2e coverage
- Update completion tests in
/Users/rcmerci/gh-repos/logseq/src/test/logseq/cli/completion_generator_test.cljs:- includes
debuggroup andpullsubcommand completion.
- includes
- Update inventory in
/Users/rcmerci/gh-repos/logseq/cli-e2e/spec/non_sync_inventory.edn:- add
:debugscope with commanddebug pull - add options
--id,--uuid,--ident
- add
- Add e2e cases in
/Users/rcmerci/gh-repos/logseq/cli-e2e/spec/non_sync_cases.edn:- id-based pull
- uuid-based pull
- ident-based pull
- one case proving current-graph fallback (no
--graphon debug call after config/graph setup)
Phase 5: Formatter and docs
- Add explicit human formatting branch in
/Users/rcmerci/gh-repos/logseq/src/main/logseq/cli/format.cljsfor:debug-pull:- pretty-print entity as EDN for readable debugging output
- include compact header context (selector and lookup)
- Update
/Users/rcmerci/gh-repos/logseq/docs/cli/logseq-cli.mdwithdebug pullusage and examples.
File-by-file change map
| File | Planned change |
|---|---|
/Users/rcmerci/gh-repos/logseq/src/main/logseq/cli/command/debug.cljs |
New command namespace (entries, validation helpers, build-action, execute-debug-pull). |
/Users/rcmerci/gh-repos/logseq/src/main/logseq/cli/commands.cljs |
Register debug entries; add parse/finalize validation, build-action route, and execute dispatch. |
/Users/rcmerci/gh-repos/logseq/src/main/logseq/cli/command/core.cljs |
Add debug under Utilities top-level-only group and description override to hide subcommands in global help. |
/Users/rcmerci/gh-repos/logseq/src/main/logseq/cli/format.cljs |
Add explicit human formatter for debug output with pretty-printed EDN entity payload. |
/Users/rcmerci/gh-repos/logseq/src/test/logseq/cli/commands_test.cljs |
Add parser/help/build coverage for debug command and utilities help visibility rules. |
/Users/rcmerci/gh-repos/logseq/src/test/logseq/cli/command/debug_test.cljs |
New execute/normalization tests for debug pull invoke contract. |
/Users/rcmerci/gh-repos/logseq/src/test/logseq/cli/completion_generator_test.cljs |
Add completion coverage for debug pull. |
/Users/rcmerci/gh-repos/logseq/cli-e2e/spec/non_sync_inventory.edn |
Add debug scope and option coverage metadata. |
/Users/rcmerci/gh-repos/logseq/cli-e2e/spec/non_sync_cases.edn |
Add non-sync end-to-end cases for id/uuid/ident and graph fallback behavior. |
/Users/rcmerci/gh-repos/logseq/docs/cli/logseq-cli.md |
Document debug pull usage and selector examples. |
db-worker-node impact
No new worker API is required for the requested scope.
Reason:
:thread-api/pullalready exists and already performs Datascriptd/pull.- selector
[*]is legal and directly maps to requested debug behavior. - lookup refs for
:db/identand:block/uuidare already supported by Datascript pull semantics.
Potential worker-side follow-up is only needed if we later want:
- multi-entity pull
- custom selectors from CLI input
- stricter nil/not-found error signaling at worker layer
Edge cases to explicitly cover
| Scenario | Expected behavior |
|---|---|
debug pull with no selector flags |
Error: exactly one selector required. |
debug pull --id 1 --uuid ... |
Error: only one of --id, --uuid, --ident allowed. |
debug pull --ident logseq.class/Tag (without leading :) |
Error with explicit invalid ident message (--ident requires strict EDN keyword). |
debug pull without --graph and no current graph configured |
Error: missing repo/graph. |
| entity not found | Return typed error (:entity-not-found) instead of ambiguous success with nil. |
logseq --help |
Shows debug under Utilities, not debug pull. |
Verification commands
bb dev:test -v logseq.cli.commands-test
bb dev:test -v logseq.cli.command.debug-test
bb dev:test -v logseq.cli.completion-generator-test
bb -f cli-e2e/bb.edn test --skip-build
bb dev:lint-and-test
Expected outcome: parser/help behavior, invoke contract, completion, and e2e coverage all green.
Resolved decisions
--identaccepts only strict EDN keyword input.- Not-found is a hard error (
:entity-not-found). - Human output for
debug pulluses pretty-printed EDN.