claude/skills/logseq-plugin/SKILL.md
Bootstrap, author, debug, and publish Logseq plugins. Use when the user asks to create a logseq plugin, build a logseq plugin, scaffold a logseq plugin, add a feature to an existing Logseq plugin, fix a Logseq plugin bug, publish a plugin to the Logseq marketplace, or when working in a repo that contains a `logseq` field in package.json. Triggers on phrases "create a logseq plugin", "build a logseq plugin", "scaffold a logseq plugin", "new logseq plugin", "logseq plugin development", "logseq plugin API", "publish to logseq marketplace", "logseq plugin bug", "@logseq/libs".
npx skillsauth add kendreaditya/.config logseq-pluginInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Author Logseq Desktop plugins using @logseq/libs + Vite + TypeScript. Covers scaffolding a new plugin, extending an existing one, navigating Logseq's plugin API, avoiding well-known gotchas, and publishing to the logseq/marketplace registry.
Do NOT use this skill for:
logseq field in package.json)? → §2 Extend.references/gotchas.md.Copy assets/starter/ into the target directory, rename, and install.
cp -R ~/.config/claude/skills/logseq-plugin/assets/starter/ ~/workspace/<plugin-name>
cd ~/workspace/<plugin-name>
Edit package.json:
name — match the directory name.description — one-line summary.repository.url — GitHub URL.logseq.id — same as name (lowercase, hyphen-separated). This is the plugin's marketplace identifier.logseq.title — user-facing display name.Edit src/main.ts: replace the placeholder style.key and log label with the plugin id.
Edit README.md: explain what it does and how to load.
Install + build:
npm install
npm run build # or: npm run dev (vite build --watch)
Load in Logseq Desktop: Settings → Advanced → Developer mode (enable) → top-right ⋯ → Plugins → Load unpacked plugin → select the plugin folder. Reload from the Plugins page after each rebuild.
The starter boots a valid plugin (empty provideStyle, one console log). Pick the architecture you need — the two canonical shapes are documented with code sketches in references/architecture.md:
MutationObserver on body, read date from DOM title, inject HTML next to .references.provideUI into .cp__header or .left-sidebar-inner, with provideModel for click routing via data-on-click.When dropped into an unfamiliar plugin repo:
CLAUDE.md first if present — it contains the project's onboarding order and gotchas. Follow the order.package.json — logseq field (id, title), main field (entry HTML), build scripts (likely vite build).logseq.ready(main) (usually src/main.ts). Trace what main() does: provideStyle → state.load → first run/render → listeners (onRouteChanged, MutationObserver, onCurrentGraphChanged, DB.onChanged)..insertAdjacentElement, logseq.provideUI (templated HTML slot), or logseq.provideModel (click routing).src/state.ts typically has a singleton with a Persisted type, load()/dump() methods, and loose transient fields. Anything in dump() gets persisted via logseq.updateSettings; everything else is per-session.logseq.Editor.registerSlashCommand; if adding a sidebar panel, follow provideUI with a fresh key.See references/apis.md for the full API cheatsheet.
Each of these ate real hours. Expanded explanations in references/gotchas.md.
Editor.getCurrentPage(). getCurrentPage() returns null on fresh journal mounts. Read .journal-title h1.title with a h1.title fallback, and parse both ISO (2026-04-17) and pretty (Apr 17th, 2026) formats.logseq.DB.datascriptQuery returns flat, namespace-stripped pull keys. A pull of :block/uuid comes back as pull.uuid, not pull["block/uuid"]. Nested pulls: pull.page.id, not pull["block/page"]["db/id"]. Always use a defensive reader with both shapes as fallbacks. Log a sample pull at startup (diagnoseSchema) — the shape is right there..references is a DOM sibling of .journal.page, not a child. Rooting querySelector('.references') at the journal page element will miss it. Try the journal root, then fall back to document.querySelector. Journal-root selectors vary across builds: try .journal-item, .journal.page, .page.is-journals, .page-inner-wrap.is-journals in order.margin-left: -30px. External CSS loses specificity fights with themes, and .block-control collapses to zero width without a flex-parent context. Set style="width:14px;height:16px;margin-left:-30px" inline on the <a class="block-control"> — do not "clean up" this inline style.collapsedCards accumulate stale uuids as the user navigates. Persist only what users explicitly want to outlast a session (typically: section-level collapse, user preferences). Call state.collapsedCards.clear() at the top of run().Editor.scrollToBlockInPage(uuid) to jump to the native editable rendering on the source page..ls-foldable-* classes are master-only. Stable Logseq 0.10.x uses a simpler foldable shape (<div class="content"><div class="flex-1 flex-row foldable-title">...). Target 0.10 unless you know the user is on a DB-based beta.Full step-by-step in references/marketplace.md. The happy path:
.github/workflows/release.yml — push a v* tag (e.g. git tag v0.1.0 && git push --tags) and it builds + zips dist/ + package.json + icon.svg + README.md into <plugin-id>.zip attached to the Release.logseq/marketplace, branch add-<plugin-id>.packages/<plugin-id>/:
manifest.json — { title, description, author, repo, icon: "icon.svg", theme: false }icon.svg — 128x128 recommended.logseq/marketplace:master with a short description, repo link, feature list. A reviewer will merge if the release zip is present.npm run dev # vite build --watch — rebuilds on file change
In Logseq Desktop: Plugins page → find your plugin → click the reload icon. This re-runs main() with the fresh bundle without restarting Logseq.
Console logs from plugins appear in Logseq's main DevTools (Cmd+Opt+I / Ctrl+Shift+I). Always prefix logs with [<plugin-id>] for grepping.
SKILL.md — this file.references/architecture.md — bootstrap lifecycle, state pattern, journal-injection vs sidebar-UI archetypes with code sketches, delegated click handler pattern.references/apis.md — cheatsheet of logseq.* APIs grouped by namespace, each with a real call site.references/datascript.md — pull-query shape, namespace-stripped keys, defensive reader, DB-graph vs file-graph fallbacks.references/gotchas.md — expanded debugging notes for §3 plus more.references/marketplace.md — full publication flow with worked example.assets/starter/ — copy-and-adapt plugin skeleton.When editing an existing plugin:
CLAUDE.md, docs/architecture.md, docs/debugging-notes.md) before modifying a pipeline.npm run build before committing. TypeScript errors in a Logseq plugin are easy to miss because the runtime is tolerant.logseq.id stable once published — changing it breaks upgrade paths for existing installs.dist/ (gitignored in the starter).development
Search and read content from leetcode.com — problem catalog, daily challenge, full problem statements with hints and starter code, the Discuss forum (interview experiences, comp posts, layoff threads), and company question-list metadata. Read-only, no auth, no API key. Use when the user wants to look up a LeetCode problem by name/number/slug, see today's daily challenge, search Discuss for interview write-ups at a specific company (Google, Waymo, Meta, Amazon, etc.), browse a tag-filtered discuss feed, read a Discuss post + comments, or check what a LeetCode company list covers. Triggers — "lcsearch", "leetcode search", "search leetcode", "leetcode discuss", "leetcode problem", "daily leetcode", "interview discuss", "what's the leetcode for X", URLs containing leetcode.com/problems/, leetcode.com/discuss/, or leetcode.com/company/. Pair with the `interviewcoder` skill (structured leetcode-style writeups from 1point3acres) and `blind` (anonymous workplace chatter) for the same companies.
development
Terminal Spotify playback/search via spogo (preferred) or spotify_player.
development
Search and read posts from interviewcoder.co — a Next.js-fronted aggregator of technical-interview writeups (largely sourced from 1point3acres) tagged by company, position, stage (Phone Screen / OA / Onsite / etc.), period, job type, and structured leetcode-style questions. Use when the user wants real interview questions for a specific company, recent writeups from a hiring loop, leetcode-style problems with tags and difficulty, or to look up a specific interviewcoder.co URL. Read-only, no auth, no API key. Triggers — "interviewcoder", "interviewcoder.co", "interview questions at [company]", "what's been asked at [company] recently", "interview writeup", and URLs containing interviewcoder.co.
tools
Small Yahoo Finance CLI for ticker info + N-year stock returns. Use when the user asks about: stock price, market cap, sector/industry classification, dividend yield, P/E ratio, beta, 52-week range, N-year stock return, company description for a public company. Triggers: 'yfinance', 'yfin', 'stock price', 'market cap of', 'how much has X stock returned', 'sector for ticker', 'industry classification'. Pairs with the levels-fyi skill for cross-checking public/private status (levels gives ticker, yfin returns live data).