Claude Code Plugins

Community-maintained marketplace

Feedback

>

Install Skill

1Download skill
2Enable skills in Claude

Open claude.ai/settings/capabilities and find the "Skills" section

3Upload to Claude

Click "Upload skill" and select the downloaded ZIP file

Note: Please verify skill by going through its instructions before using it.

SKILL.md

name building-logseq-plugins
version 1.0.0
description Expert guidance for building Logseq plugins compatible with the new DB architecture. Auto-invokes when users want to create Logseq plugins, work with the Logseq Plugin API, extend Logseq functionality, or need help with plugin development for DB-based graphs. Covers plugin structure, API usage, and DB-specific considerations.
allowed-tools Read, Grep, Glob, WebFetch, WebSearch, Write, Edit, Bash

Building Logseq Plugins

When to Use This Skill

This skill auto-invokes when:

  • User wants to create a Logseq plugin
  • Questions about the Logseq Plugin API
  • Working with logseq.Editor, logseq.DB, logseq.App namespaces
  • Slash command registration
  • Plugin settings schema definition
  • DB vs MD version compatibility for plugins
  • User mentions "logseq plugin", "logseq extension", "@logseq/libs"

You are an expert in Logseq plugin development, with special focus on DB-version compatibility.

Plugin Architecture Overview

Logseq plugins run in sandboxed iframes and communicate with the main app via the Plugin API.

Plugin Structure

my-logseq-plugin/
├── package.json          # Plugin manifest
├── index.html            # Entry point
├── index.js              # Main logic (or TypeScript)
├── icon.png              # Plugin icon (optional)
└── README.md             # Documentation

package.json Manifest

{
  "name": "logseq-my-plugin",
  "version": "1.0.0",
  "main": "index.html",
  "logseq": {
    "id": "my-plugin-id",
    "title": "My Plugin",
    "icon": "./icon.png",
    "description": "Plugin description"
  }
}

Plugin API Basics

Initialization

import '@logseq/libs'

async function main() {
  console.log('Plugin loaded')

  // Register commands, settings, etc.
  logseq.Editor.registerSlashCommand('My Command', async () => {
    // Command logic
  })
}

logseq.ready(main).catch(console.error)

Key API Namespaces

Namespace Purpose
logseq.Editor Block/page manipulation
logseq.DB Database queries
logseq.App App-level operations
logseq.UI UI components
logseq.Settings Plugin settings

DB-Version Specific APIs

Working with Properties

// Get block with properties (DB version)
const block = await logseq.Editor.getBlock(blockUuid, {
  includeChildren: true
})

// Properties are structured differently in DB version
// Access via block.properties object
const author = block.properties?.author

// Set property value
await logseq.Editor.upsertBlockProperty(blockUuid, 'author', 'John Doe')

Working with Classes/Tags

// Get blocks with a specific tag/class
const books = await logseq.DB.datascriptQuery(`
  [:find (pull ?b [*])
   :where
   [?b :block/tags ?t]
   [?t :block/title "Book"]]
`)

// Add tag to block
await logseq.Editor.upsertBlockProperty(blockUuid, 'tags', ['Book', 'Fiction'])

Enhanced Block Properties APIs (2024+)

// New APIs for DB version
await logseq.Editor.getBlockProperties(blockUuid)
await logseq.Editor.setBlockProperties(blockUuid, {
  author: 'Jane Doe',
  rating: 5,
  published: '2024-01-15'
})

Datalog Queries in Plugins

Basic Query

const results = await logseq.DB.datascriptQuery(`
  [:find ?title
   :where
   [?p :block/title ?title]
   [?p :block/tags ?t]
   [?t :db/ident :logseq.class/Page]]
`)

Query with Parameters

const results = await logseq.DB.datascriptQuery(`
  [:find (pull ?b [*])
   :in $ ?tag-name
   :where
   [?b :block/tags ?t]
   [?t :block/title ?tag-name]]
`, ['Book'])

DB vs MD Query Differences

// MD version - file-based queries
const mdQuery = `
  [:find ?content
   :where
   [?b :block/content ?content]
   [?b :block/page ?p]
   [?p :block/name "my-page"]]
`

// DB version - entity-based queries
const dbQuery = `
  [:find ?title
   :where
   [?b :block/title ?title]
   [?b :block/tags ?t]
   [?t :block/title "My Tag"]]
`

UI Components

Slash Commands

logseq.Editor.registerSlashCommand('Insert Book Template', async () => {
  await logseq.Editor.insertAtEditingCursor(`
- [[New Book]] #Book
  author::
  rating::
  status:: To Read
`)
})

Block Context Menu

logseq.Editor.registerBlockContextMenuItem('Convert to Task', async (e) => {
  const block = await logseq.Editor.getBlock(e.uuid)
  await logseq.Editor.upsertBlockProperty(e.uuid, 'tags', ['Task'])
  await logseq.Editor.upsertBlockProperty(e.uuid, 'status', 'Todo')
})

Settings Schema

logseq.useSettingsSchema([
  {
    key: 'apiKey',
    type: 'string',
    title: 'API Key',
    description: 'Your API key for the service',
    default: ''
  },
  {
    key: 'enableFeature',
    type: 'boolean',
    title: 'Enable Feature',
    default: true
  },
  {
    key: 'theme',
    type: 'enum',
    title: 'Theme',
    enumChoices: ['light', 'dark', 'auto'],
    default: 'auto'
  }
])

DB-Version Compatibility Checklist

When building plugins for DB version:

  • Use :block/title instead of :block/content for page names
  • Handle structured properties (not just strings)
  • Support typed property values (numbers, dates, checkboxes)
  • Use tag-based queries instead of namespace queries
  • Test with both DB and MD graphs if supporting both
  • Handle the unified node model (pages ≈ blocks)
  • Use new block properties APIs when available

Common Patterns

Feature Detection

async function isDBGraph() {
  // Check if current graph is DB-based
  const graph = await logseq.App.getCurrentGraph()
  return graph?.name?.includes('db-') || graph?.type === 'db'
}

async function main() {
  const isDB = await isDBGraph()
  if (isDB) {
    // DB-specific initialization
  } else {
    // MD-specific initialization
  }
}

Property Type Handling

function formatPropertyValue(value, type) {
  switch (type) {
    case 'date':
      return new Date(value).toISOString().split('T')[0]
    case 'number':
      return Number(value)
    case 'checkbox':
      return Boolean(value)
    case 'node':
      return `[[${value}]]`
    default:
      return String(value)
  }
}

Development Workflow

  1. Setup: Clone logseq-plugin-template or start fresh
  2. Develop: Use npm run dev for hot reload
  3. Test: Load unpacked plugin in Logseq
  4. Build: npm run build for production
  5. Publish: Submit to Logseq Marketplace

Loading Development Plugin

Logseq > Settings > Advanced > Developer Mode: ON
Logseq > Plugins > Load unpacked plugin > Select folder

Resources