Person/codekiln/GitHub/logseq-gardener/Project/Proposal
logseq-gardener: Project proposal
- logseq-gardener is a proposed command-line tool, called
lsg, for managing Logseq knowledge gardens. It will help people and coding agents find notes, follow links, review changes, and eventually edit and publish their gardens. The aim is to make years of accumulated notes easy to use from the terminal and Neovim, with continued support for the existing Markdown files and Git workflow. Why build it?
- A Logseq garden contains relationships that ordinary file tools cannot fully explain. A page can exist through links from other notes even when it has no file. An alias can give a page another name. A reference can point to an individual bullet and its children, which Logseq calls a block. Searching filenames alone misses these relationships.
- People need those relationships when navigating their notes; coding agents need them when choosing where to put new information. Today, agents repeatedly search this repository to reconstruct enough context to make an edit.
lsg will provide a consistent way to ask the garden directly and identify the source of each answer. - The longer-term benefit is freedom to choose how to work with the garden. A person should be able to write in Neovim, delegate maintenance to an agent, and publish readable web pages while retaining the connections that make the notes useful.
Use cases
- Find the right place for a note. Before creating a page, an agent runs
lsg page resolve "Logseq/Publish". The result identifies the page, explains how the name matched, and gives a source location. If several pages claim the name, the command lists the candidates for review. - Write with links in Neovim. While a person types a page link, the editor offers matching names and aliases. Following a link opens the note; finding references lists the places that use it. For a page without a file, the editor shows the notes that mention it.
- Understand a change before committing. Suppose Studio has the alias Workshop and a journal links to Workshop. Removing that alias changes what the journal link means, even though the journal text stays the same.
lsg diff --staged will show the removed alias and the journal links affected by it. - Share a readable garden.
lsg export will prepare pages for a static website, including links, embedded notes, and referenced assets. A visitor will be able to open a page and read its content without first downloading the whole garden. - Maintain notes with an agent. Later editing commands will preview a page rename or block move, including changes to references elsewhere. A person can review the patch before applying it, and
lsg will detect intervening edits before writing.
First release
- Start with commands for finding and inspecting information. These commands will read the garden and maintain a reusable index of its pages, blocks, and references. The first release will leave garden files unchanged, making it suitable for daily use on real notes while compatibility is established.
- The initial command set:
lsg page resolve "Logseq/Publish" — identify a page and explain the match.lsg page complete "Logseq/Pub" — suggest page names and aliases.lsg page backlinks "Logseq/Publish" — find notes that link to a page.lsg block get <uuid> — retrieve a block by its saved identifier, with its source location.lsg search "publishing" — search note text and show matching locations.
- Output will be readable by default.
--format json will return the same information in a documented structure for scripts and agents. Batch page resolution will accept names from standard input so a link checker can inspect a draft in one invocation. - Version every JSON format. When
--format json is requested, standard output will contain one result document and no commentary. Warnings, progress, and errors will go to standard error so a caller can safely pipe or redirect the result. - Every advertised command path will provide equivalent
help and --help output that explains its purpose, behavior, usage, immediate child commands, side effects, permissions, and a likely task. Help will support offline JSON discovery of child commands as well as outline and section retrieval, following Clilint's navigable help standard. - Read commands and help commands will complete without prompts. They will close standard input unless the command contract accepts input, omit terminal control sequences when output is redirected, and require no network access to inspect a local garden.
- Page resolution will distinguish a match, competing matches, no match, and an incomplete search. A match will also say whether a content file exists. The quiet
lsg page exists command will expose those outcomes through documented exit codes; scripts must distinguish an incomplete search from an absent page before creating anything. - The release is ready for regular use when this repository's link-hygiene workflow can resolve names through
lsg, explain its findings with source locations, and pass the compatibility tests below. Repeated commands must reuse prior parsing work. The command line and help system must pass Person/codekiln/GitHub/clilint with its global standard and codekiln-help check bundle.
Technical design
Shared graph model
- A core library will read Logseq files and represent pages, nested blocks, properties, aliases, and references. The CLI, Neovim integration, and exporter will call this library so they agree about what a name or reference means.
lsg will select the nearest garden containing logseq/config.edn, or use an explicit --graph <path>. The core will read the garden's naming configuration before interpreting filenames, titles, and journal dates. Every lookup will belong to a specific garden.- Each page and block will retain its source file and text location. Blocks with an explicit UUID will keep that identity when moved. For other blocks, the core will record their location in the current outline and report uncertainty when comparing possible moves between versions.
Project and dependency licensing
logseq-gardener will use the GNU Affero General Public License, version 3. This choice supports direct reuse of AGPL code from lsdoc, Tine, mldoc, Logseq/OG, and Looksyk, subject to each dependency's license terms.- Markdown Oxide and obsidian.nvim use Apache-2.0. Marksman, Logseq graph-validator, and Logseq publish-spa use MIT. Record the revision, license, attribution, modification notices, and source-distribution requirements for every dependency or adapted source.
Repository layout and project workflow
- Begin with one Rust binary crate and a small set of internal modules for source parsing, graph meaning, indexing, commands, and output formats. Create separate workspace crates after a component has demonstrated an independent reuse, dependency, or build boundary. Keep fixtures under the tests that use them and keep the number of top-level folders small.
- A root
mise.toml and committed lockfile will manage Rust and every project development tool. Repeated jobs will be executable files under .mise/tasks/, with a #MISE description and #USAGE metadata for accepted arguments and flags. Local development and continuous integration will run the same named tasks for formatting, linting, tests, benchmarks, OpenSpec validation, RuleSync checks, builds, and releases. - Use OpenSpec for planned changes. Each requirement will include an observable scenario, and each implementation area will carry its own verification tasks. Comparative prototypes will live in a named
experiments/ directory within the OpenSpec change that motivated them, so the experiment and the resulting decision stay together when the change is archived. - Keep project instructions and OpenSpec skills in
.rulesync/ source and generate the supported agent files. Continuous integration will check that generated files match their source and that each OpenSpec skill matches the mise-managed OpenSpec version.
Clilint as the project model
- Use Person/codekiln/GitHub/clilint as the working example for repository setup, documentation, command behavior, hierarchical help, conformance checks, and release automation. Adapt its patterns to Logseq Gardener's graph engine while keeping the conventions familiar across both command-line tools.
- Model the root README on the Clilint README. Its opening will explain the problem, intended users, and practical value before implementation details. It will state project maturity, supported systems, continuous-integration status, maintainer, and AGPL license; provide one copyable mise installation and first-use path; and link to focused documents for advanced and contributor work. Verify its commands, links, and factual claims against the repository before release.
- Run a pinned Person/codekiln/GitHub/clilint version and the selected check bundles through the aggregate mise task used by continuous integration. Treat a failed CLI or hierarchical-help check as a product regression. Apply the same command-line expectations to each new public subcommand as it is introduced.
- Follow Clilint's automated release flow as the Semantic Versioning model. Validate git/commit/Conventional/gitmoji pull request titles and derive release impact from them. Release-plz will maintain the version, changelog, release pull request, and tag. Cargo-dist will publish tested, checksummed native binaries after required checks pass. Maintainers will run the same release checks locally through mise.
Parser and compatibility
- Rust is the proposed starting language, with lsdoc, a Rust parser for Logseq Markdown, as the parser candidate.
lsdoc provides source spans, outline and reference APIs, differential tests against mldoc, and a graph-check command for comparing both parsers on a real garden. Its young age makes the compatibility experiment a prerequisite for adoption. Study Tine's GUI-free Rust core for graph, index, query, source-preserving edit, and publishing patterns. - Use official
mldoc as the syntax reference. Use the current Logseq OG graph parser and Logseq graph-validator as the reference for graph meaning. The comparison must cover page identities, aliases, namespaces, journal names, properties, block hierarchy, block references, page references, queries, assets, and missing page targets. Generate expected graph fixtures through Logseq's own logseq.graph-parser.cli/parse-graph entry point. - Keep the original file text and test source locations separately. Parsing and writing a file without edits must preserve every byte. Later editing tests must also prove that a small requested change leaves surrounding text intact.
- If
lsdoc requires extensive syntax repairs on the test gardens, compare that effort with using mldoc, Logseq's parser written in OCaml, including its outline-only parser, before settling the language. Either implementation must pass the same syntax, graph, and source-preservation tests.
Index and responsiveness
- Store a rebuildable SQLite index outside the garden, under
$XDG_CACHE_HOME/logseq-gardener/, using ~/.cache when the variable is unset. Give each garden checkout its own directory, keyed by its real path, so separate Git worktrees can contain different notes safely. Deleting the index will cause lsg to rebuild it from the files. - Commands will refresh changed files and reconsider references affected by those changes. For example, removing an alias requires resolving links in other notes again, while reusing their parsed text. File content hashes, configuration, and parser versions will determine whether cached information is current. Database transactions will keep partial updates out of query results.
- Neovim will start
lsg lsp, a process that communicates through the Language Server Protocol over standard input and output. The server will load cached information when a garden file opens, parse the current file first, and continue indexing in the background. Completion can return available candidates promptly; a definitive existence check must finish the relevant search or report that it is incomplete. - The language server will keep unsaved editor text separate from the saved index and discard parsing results for older buffer versions. Terminal commands will answer from saved files. Installation will provide the
lsg executable; Neovim will manage the language server's lifetime. - Follow Markdown Oxide's separation of completion, definitions, references, rename, symbols, and diagnostics. Let Marksman continue to provide generic Markdown features while
lsg lsp provides Logseq page identity, fileless pages, aliases, namespaces, journals, block UUIDs, block references, properties, and embeds. Use obsidian.nvim as a reference for Neovim interactions such as updating links after a file rename.
Review, export, and editing
lsg diff will compare complete garden versions so it can explain effects in unchanged files. The staged form will compare the last commit with Git's staged contents, using each version's configuration. It will report changed link targets, missing block references, and changed block relationships with source locations.lsg export will produce ordinary Markdown for a site generator, beginning with a trial of Quartz. Use Logseq publish-spa as the reference for file-graph publication rules and study the older Logseq static publisher for per-page rendering patterns. The exporter will resolve links and embeds and copy referenced assets. Unsupported queries or macros will get visible placeholders and a local report. Publication filtering must also cover embedded text, backlinks, and assets so excluded notes stay out of the website.- Editing commands will prepare patches from original text and check that affected files still match the preview before applying them. Multi-file operations will record recovery information before writing. After interruption, recovery must preserve any newer edits and report files requiring attention.
Starting tasks
- Record the AGPL licensing strategy. Add the AGPL license to the repository and document how the project will satisfy the licenses of reused code from
lsdoc, Tine, mldoc, Logseq/OG, and Looksyk. Completion means the repository states its license and tracks the revision, license, notices, modifications, and source obligations for every dependency or adapted source. - Establish the repository workflow. Create the single Rust binary crate, pinned mise environment, described file tasks, aggregate continuous-integration task, OpenSpec directories, and RuleSync source. Completion means a fresh checkout can install its tools with mise and run the same aggregate check used by continuous integration.
- Write the project entry points. Create a root README modeled on Clilint and focused documents for installation, command use, architecture, and contribution. Completion means a new user can understand the purpose, install
lsg, run and understand a first command within five minutes, and follow verified links to deeper guidance. - Build a compatibility test set. Use this public garden as the release-acceptance corpus, the Logseq documentation garden as a first-party compatibility corpus, Pengx's public garden as a publishing corpus, and small fixtures for aliases, fileless pages, journal names, nested blocks, and UUID references. Pin
mldoc, the Logseq OG graph parser, and graph-validator, then record expected syntax and graph results. Completion means a repeatable comparison that identifies each disagreement and its source file. - Choose the parser. Run
lsdoc's tools/graph-check.mjs on the test set in comparison and benchmark modes, compare the result with Logseq graph-validator, check source preservation, and measure parsing time and memory. Inspect the useful parts of Tine. Completion means a decision record naming the implementation, dependency licenses, and compatibility repairs needed to proceed. - Deliver page resolution with a reusable index. Implement graph selection,
lsg page resolve, versioned --format json output, batch input, and navigable help. Add tests for duplicate aliases, fileless pages, changed configuration, deleted files, changed content with unchanged file size and timestamps, standard-output and standard-error separation, closed input, redirected output, and offline help discovery. Completion means an updated index produces the same answers as a clean rebuild, separate worktrees remain independent, and the public commands pass the selected Clilint checks. - Use the CLI in garden maintenance. Add completion, backlinks, block lookup, and text search, then integrate batch resolution into this repository's link-hygiene workflow. Completion means an agent can find an existing destination for a note and check its links with actionable source locations.
- Measure everyday speed. Record cold startup, repeated commands in fresh processes, and the time for a saved edit to appear in backlinks. Generate larger gardens with controlled namespace depth, references, block identities, and heavily linked pages so scaling problems can be reproduced. Set response-time targets from those measurements and keep the slow runs visible. Before delivering Neovim support, also measure completion while background parsing is busy.
Subsequent work
- Deliver Neovim completion and navigation after the CLI is useful in daily maintenance. Test unsaved aliases, unfinished links, Unicode cursor positions, and delayed parsing results by replaying editor requests.
- Add graph comparison to commit checks and PR review, then export the public garden and measure how quickly visitors can read a page. Test partially staged edits for comparison and nested embeds with mixed publication settings for export.
- Add page and block editing once reading and comparison are dependable. Test preview accuracy, intervening edits, and interrupted multi-file writes.
- Support concurrent work through a Git merge driver that combines edits to confidently matched independent blocks and exposes structural conflicts for a person to resolve. Validate references across the whole garden after merging. Later, evaluate live shared editing with conflict-free replicated data types, which coordinate concurrent edits, when simultaneous work in the same files requires it.