Files
logseq/docs/agent-guide/042-logseq-cli-add-tag-command.md
2026-03-12 15:12:33 +08:00

9.7 KiB

Logseq CLI Add Tag Subcommand Implementation Plan

Goal: Add logseq add tag so CLI users can create a tag entity before using that tag in add block, add page, and update.

Architecture: Reuse the existing CLI to db-worker-node write path by sending :create-page with {:class? true} through :thread-api/apply-outliner-ops. Architecture: Keep db-worker-node protocol and HTTP endpoints unchanged because the feature composes existing worker operations. Architecture: Validate the result after write by pulling the page entity and asserting the page has :logseq.class/Tag semantics.

Tech Stack: ClojureScript, babashka.cli, Promesa, Datascript, db-worker-node, outliner ops.

Related: Builds on docs/agent-guide/018-logseq-cli-add-tags-builtin-properties.md and docs/agent-guide/041-logseq-cli-add-block-json-identifiers.md.

Problem statement

Current CLI behavior can attach only existing tags because resolve-tag-entity in /Users/rcmerci/gh-repos/logseq/src/main/logseq/cli/command/add.cljs fails with :tag-not-found when a tag is missing.

Current CLI behavior has no add tag command entry in /Users/rcmerci/gh-repos/logseq/src/main/logseq/cli/command/add.cljs, so users cannot create custom tags from CLI.

Current db-worker-node flow already supports page and class creation through :thread-api/apply-outliner-ops and :create-page, so the missing capability is command orchestration in CLI instead of worker transport.

list tag in /Users/rcmerci/gh-repos/logseq/src/main/logseq/cli/common/mcp/tools.cljs returns entities tagged with :logseq.class/Tag, so add tag must create that exact class shape instead of a plain page.

Testing Plan

I will follow @test-driven-development and write parsing tests before changing command implementation code.

I will add failing action-building tests that verify required options, normalized action payload, and explicit errors for invalid input.

I will add failing execution tests that stub transport calls and verify emitted outliner ops include :create-page with {:class? true}.

I will add failing format tests for human output so :add-tag has a stable success message contract.

I will add one integration test that creates a new tag and then uses that tag in add block to prove end to end behavior through db-worker-node.

I will add one integration test that confirms failure when the same title already exists as a non-tag page, so the command does not report false success.

NOTE: I will write all tests before I add any implementation behavior.

Scope and non-goals

This plan adds only add tag under the existing add command group.

This plan does not add new db-worker-node endpoints or thread-api methods.

This plan does not add editing features such as setting class extends, class properties, or tag description during creation.

This plan does not change existing add block, add page, or update option syntax.

add tag accepts --name only, and does not support --tag alias.

Integration overview

logseq add tag --name "Quote"
  -> /Users/rcmerci/gh-repos/logseq/src/main/logseq/cli/command/add.cljs
  -> /Users/rcmerci/gh-repos/logseq/src/main/logseq/cli/transport.cljs
  -> db-worker-node /v1/invoke
  -> :thread-api/apply-outliner-ops
  -> :create-page [title {:class? true}]
  -> Datascript entity tagged as :logseq.class/Tag

Detailed implementation plan

  1. Add a failing parser help test in /Users/rcmerci/gh-repos/logseq/src/test/logseq/cli/commands_test.cljs that expects add group help to include add tag.
  2. Add a failing parser test in /Users/rcmerci/gh-repos/logseq/src/test/logseq/cli/commands_test.cljs for ["add" "tag" "--name" "Quote"] to produce :add-tag.
  3. Add a failing parser validation test in /Users/rcmerci/gh-repos/logseq/src/test/logseq/cli/commands_test.cljs that missing --name returns :missing-tag-name.
  4. Add a failing build-action test in /Users/rcmerci/gh-repos/logseq/src/test/logseq/cli/commands_test.cljs that ensures :add-tag action contains :type, :repo, :graph, and normalized :name.
  5. Add a failing execute test in /Users/rcmerci/gh-repos/logseq/src/test/logseq/cli/commands_test.cljs that stubs transport and verifies :create-page options include :class? true.
  6. Add a failing execute test in /Users/rcmerci/gh-repos/logseq/src/test/logseq/cli/commands_test.cljs that simulates existing non-tag page conflict and expects a deterministic CLI error code.
  7. Add a failing format test in /Users/rcmerci/gh-repos/logseq/src/test/logseq/cli/format_test.cljs for :add-tag human output.
  8. Add a failing integration test in /Users/rcmerci/gh-repos/logseq/src/test/logseq/cli/integration_test.cljs that runs add tag, validates list tag contains the new tag, and confirms add block --tags with that tag succeeds.
  9. Add a failing integration test in /Users/rcmerci/gh-repos/logseq/src/test/logseq/cli/integration_test.cljs for duplicate title where a normal page exists and command must fail with clear error.
  10. Run focused tests and confirm all new tests fail for behavior reasons, and use @clojure-debug only if failures are caused by test setup mistakes.
  11. Extend /Users/rcmerci/gh-repos/logseq/src/main/logseq/cli/command/add.cljs with a new add-tag command spec, entry, action builder, and executor.
  12. In /Users/rcmerci/gh-repos/logseq/src/main/logseq/cli/command/add.cljs, implement execution via :thread-api/apply-outliner-ops and [:create-page [name {:class? true}]].
  13. In /Users/rcmerci/gh-repos/logseq/src/main/logseq/cli/command/add.cljs, add a post-create pull check that verifies the resulting entity is class-tagged and raise an explicit error if not.
  14. Extend /Users/rcmerci/gh-repos/logseq/src/main/logseq/cli/commands.cljs parse validation with :missing-tag-name handling for :add-tag.
  15. Extend /Users/rcmerci/gh-repos/logseq/src/main/logseq/cli/commands.cljs action dispatch and execute dispatch for :add-tag.
  16. Extend /Users/rcmerci/gh-repos/logseq/src/main/logseq/cli/commands.cljs context propagation to include the new tag field used by formatter output.
  17. Extend /Users/rcmerci/gh-repos/logseq/src/main/logseq/cli/format.cljs with format-add-tag and command routing for :add-tag.
  18. Run focused unit and integration tests and confirm they pass without changing unrelated command behavior.
  19. Run bb dev:lint-and-test and confirm the repository remains green after the feature.
  20. Refactor only local helper naming and shared logic inside add.cljs while preserving behavior and keeping tests green.

Edge cases to cover

Tag names with leading # should be normalized consistently, or rejected consistently, with one documented behavior.

Tag names containing namespace separators like A/B should produce deterministic behavior aligned with existing page creation rules.

Duplicate tag creation should be idempotent when the existing entity is already a tag class.

If a page with the same name exists but is not a tag class, add tag should fail with a dedicated error instead of silently succeeding.

Built-in tag names should remain valid and should return existing ids without creating duplicate entities.

The command should reject blank names after trim.

Verification commands

Command Expected result
bb dev:test -v logseq.cli.commands-test/test-parse-args-help New add tag appears in add group help assertions.
bb dev:test -v logseq.cli.commands-test/test-verb-subcommand-parse-add New parse and validation tests for add tag pass.
bb dev:test -v logseq.cli.commands-test/test-build-action-inspect-edit Build action includes :add-tag cases and passes.
bb dev:test -v logseq.cli.commands-test/test-execute-add-tag-builds-create-page-op Outliner op assertions pass with {:class? true}.
bb dev:test -v logseq.cli.format-test/test-human-output-add-remove Human output for :add-tag matches expected string.
bb dev:test -v logseq.cli.integration-test/test-cli-add-tag-create-and-use End to end creation and usage of a new tag passes.
bb dev:test -v logseq.cli.integration-test/test-cli-add-tag-rejects-existing-non-tag-page Conflict behavior test passes with explicit error.
bb dev:lint-and-test Full lint and unit suite pass.

Testing Details

The tests validate user-visible behavior at parser, action, executor, formatter, and integration boundaries.

The tests assert command success and failure contracts, and they verify persisted graph behavior with CLI reads such as list tag and show.

The tests avoid asserting implementation details that are not externally observable.

Implementation Details

  • Add add tag spec and entry in /Users/rcmerci/gh-repos/logseq/src/main/logseq/cli/command/add.cljs.
  • Add build-add-tag-action and execute-add-tag in /Users/rcmerci/gh-repos/logseq/src/main/logseq/cli/command/add.cljs.
  • Use existing server bootstrap and transport invoke path from /Users/rcmerci/gh-repos/logseq/src/main/logseq/cli/server.cljs and /Users/rcmerci/gh-repos/logseq/src/main/logseq/cli/transport.cljs.
  • Create tag through :create-page with {:class? true} and verify resulting entity semantics.
  • Add parse validation and missing error mapping in /Users/rcmerci/gh-repos/logseq/src/main/logseq/cli/commands.cljs.
  • Add build and execute routing for :add-tag in /Users/rcmerci/gh-repos/logseq/src/main/logseq/cli/commands.cljs.
  • Add human formatter branch for :add-tag in /Users/rcmerci/gh-repos/logseq/src/main/logseq/cli/format.cljs.
  • Add parser and executor unit tests in /Users/rcmerci/gh-repos/logseq/src/test/logseq/cli/commands_test.cljs.
  • Add formatter test in /Users/rcmerci/gh-repos/logseq/src/test/logseq/cli/format_test.cljs.
  • Add integration coverage in /Users/rcmerci/gh-repos/logseq/src/test/logseq/cli/integration_test.cljs.

Question

No open questions.