# Logseq AI
AI-powered interactions with Logseq through two interfaces:
1. **MCP Server** - Enables external AI tools (Windsurf, Claude Desktop) to interact with your Logseq graph
2. **Lain** - Embedded AI assistant plugin within the Logseq UI
> "No matter where you go, everyone's connected." - Serial Experiments Lain
## Prerequisites
- Node.js 18+
- Logseq desktop app with HTTP API server enabled (Settings → Features → HTTP APIs server)
## Setup
```bash
# Install dependencies
pnpm install
# Build all packages
pnpm build
```
## Quick Start
### Using the Core Library
```typescript
import { LogseqClient, LogseqOperations } from "@logseq-ai/core";
// Create client and operations
const client = new LogseqClient({
baseUrl: "http://localhost:12315",
token: "your-api-token" // optional
});
const ops = new LogseqOperations(client);
// Search for pages
const results = await ops.search("meeting notes");
// Get page content as text
const content = await ops.getPageContent("My Notes");
// Create a new block
const block = await ops.createBlock({
pageName: "My Notes",
content: "New idea from AI!"
});
// Create multiple blocks with hierarchy (more efficient for structured content)
const result = await ops.createBlocks("My Notes", [
{
content: "## Project Overview",
children: [
{ content: "Goal: Build a new feature" },
{ content: "Timeline: Q1 2025" },
]
},
{
content: "## Tasks",
children: [
{ content: "Design the API" },
{ content: "Implement backend" },
{ content: "Write tests" },
]
}
]);
console.log(`Created ${result.created} blocks`);
// Run a Datalog query to find TODOs
const todos = await ops.query(`
[:find (pull ?b [*])
:where [?b :block/marker "TODO"]]
`);
```
### Task Management
```typescript
import { LogseqClient, LogseqOperations } from "@logseq-ai/core";
const client = new LogseqClient();
const ops = new LogseqOperations(client);
// Get all active tasks
const tasks = await ops.getTasks();
// Get tasks from a specific page
const projectTasks = await ops.getTasks({ pageName: "Project A" });
// Create a new task with priority and deadline
const task = await ops.createTask({
pageName: "Project A",
content: "Review pull request",
priority: "A",
deadline: "2024-12-15"
});
// Mark task as in progress
await ops.markTask(task.uuid, "DOING");
// Complete the task
await ops.markTask(task.uuid, "DONE");
// Set/change priority
await ops.setTaskPriority(task.uuid, "B");
// Set scheduled date
await ops.setTaskScheduled({ uuid: task.uuid, date: "2024-12-10" });
// Remove deadline
await ops.setTaskDeadline({ uuid: task.uuid, date: null });
```
### Task Analytics
```typescript
// Get overdue tasks
const overdue = await ops.getOverdueTasks();
console.log(`You have ${overdue.length} overdue tasks`);
// Get tasks due in the next 7 days
const dueSoon = await ops.getTasksDueSoon({ days: 7 });
// Get task statistics
const stats = await ops.getTaskStats();
console.log(`Total: ${stats.total}, Overdue: ${stats.overdue}`);
console.log(`By status:`, stats.byMarker);
// Search tasks by keyword
const reviewTasks = await ops.searchTasks({ query: "review", markers: ["TODO"] });
```
### Journal Operations
```typescript
// Get or create today's journal
const today = await ops.getToday();
console.log(`Today's journal: ${today.page.name}`);
// Quick capture to today's journal
await ops.appendToToday("Meeting notes: discussed Q1 roadmap");
// Get recent journal entries
const journals = await ops.getRecentJournals({ days: 7, includeContent: true });
journals.forEach(j => console.log(`${j.date}: ${j.content.substring(0, 50)}...`));
```
### Page Links & Backlinks
```typescript
// Find pages related to a topic
const links = await ops.findRelatedPages("Project A");
console.log("Pages linking to Project A:", links.backlinks);
console.log("Pages Project A links to:", links.forwardLinks);
// Find blocks referencing a specific block
const backlinks = await ops.getBlockBacklinks("block-uuid-123");
console.log(`Found ${backlinks.backlinks.length} references`);
```
### Error Handling
```typescript
import {
LogseqOperations,
LogseqApiError,
LogseqNotFoundError,
isLogseqError
} from "@logseq-ai/core";
try {
await ops.getPageContent("Nonexistent Page");
} catch (error) {
if (error instanceof LogseqNotFoundError) {
console.log(`Page not found: ${error.identifier}`);
} else if (isLogseqError(error)) {
console.log(`Logseq error: ${error.toDetailedString()}`);
}
}
```
## Packages
### @logseq-ai/core
Shared library for Logseq API interactions. Used by both the MCP server and plugin.
**Key exports:**
- `LogseqClient` - Low-level HTTP client for Logseq API
- `LogseqOperations` - High-level operations with error handling
- Error classes: `LogseqError`, `LogseqApiError`, `LogseqConnectionError`, `LogseqNotFoundError`, `LogseqValidationError`
- Type definitions: `Page`, `Block`, `SearchResult`, etc.
### @logseq-ai/mcp-server
MCP server that exposes Logseq operations as tools for AI clients.
**Features:**
- 34 tools for comprehensive Logseq interaction
- Input validation with clear error messages (powered by Zod)
- Proper error handling for Logseq API errors
```bash
# Build
pnpm --filter @logseq-ai/mcp-server build
# Run
LOGSEQ_API_TOKEN=your-token pnpm --filter @logseq-ai/mcp-server start
# Test
pnpm --filter @logseq-ai/mcp-server test
```
#### Configure in Windsurf/Claude Desktop
Add to your MCP configuration:
```json
{
"mcpServers": {
"logseq": {
"command": "node",
"args": ["/path/to/logseq-ai/packages/mcp-server/dist/index.js"],
"env": {
"LOGSEQ_API_URL": "http://localhost:12315",
"LOGSEQ_API_TOKEN": "your-token"
}
}
}
}
```
#### Available Tools
**Page & Block Operations**
| Tool | Description |
|------|-------------|
| `search_logseq` | Search for pages and blocks |
| `get_page` | Get page content as plain text |
| `get_pages` | Get multiple pages in a batch (more efficient) |
| `get_page_with_context` | Get page with backlinks and forward links |
| `list_pages` | List all pages in the graph |
| `create_page` | Create a new page (optionally with blocks) |
| `delete_page` | Delete a page |
| `create_block` | Create a single block |
| `create_blocks` | Create multiple blocks with hierarchy |
| `update_block` | Update a block's content |
| `delete_block` | Delete a block |
| `query_logseq` | Run Datalog queries |
| `update_page_properties` | Update properties on an existing page |
**Graph Discovery**
| Tool | Description |
|------|-------------|
| `get_current_graph` | Get current graph info |
| `get_graph_stats` | Get graph statistics (pages by type, orphans, etc.) |
| `find_missing_pages` | Find referenced pages that don't exist |
| `find_orphan_pages` | Find pages with no incoming links |
| `find_pages_by_properties` | Find pages by property values |
| `find_related_pages` | Find backlinks and forward links |
| `get_block_backlinks` | Find blocks referencing a block |
**Journal Operations**
| Tool | Description |
|------|-------------|
| `get_today` | Get today's journal page |
| `append_to_today` | Add content to today's journal |
| `get_recent_journals` | Get recent journal entries |
**Task Management**
| Tool | Description |
|------|-------------|
| `get_tasks` | Get TODO/DOING tasks |
| `create_task` | Create a new task |
| `mark_task` | Change task status |
| `mark_tasks` | Change multiple tasks' status (batch) |
| `search_tasks` | Search tasks by keyword |
| `get_overdue_tasks` | Get tasks past deadline |
| `get_tasks_due_soon` | Get tasks due within N days |
| `get_task_stats` | Get task statistics |
| `set_task_priority` | Set task priority (A/B/C) |
| `set_task_deadline` | Set task deadline |
| `set_task_scheduled` | Set task scheduled date |
#### Example: Creating Structured Content
When creating pages with multiple sections, use `create_blocks` for efficiency:
```
User: Create a page about Python with sections for Overview, Features, and Links
AI uses:
1. create_page("Python", "type:: #Technology\ntags:: #Programming")
2. create_blocks("Python", [
{
content: "## Overview",
children: [
{ content: "Python is a high-level programming language." }
]
},
{
content: "## Features",
children: [
{ content: "Dynamic typing" },
{ content: "Garbage collection" },
{ content: "Large standard library" }
]
},
{
content: "## Links",
children: [
{ content: "[Official Site](https://python.org)" }
]
}
])
```
### logseq-lain
Lain - AI assistant plugin for Logseq.
```bash
# Build
pnpm --filter logseq-lain build
# Development (watch mode)
pnpm dev:plugin
```
#### Install in Logseq
1. Enable Developer Mode in Logseq (Settings → Advanced → Developer mode)
2. Go to Plugins → Load unpacked plugin
3. Select the `packages/logseq-plugin` directory
4. Use `/lain ask`, `/lain summarize`, `/lain expand` slash commands
## Architecture
See [doc/architecture.md](doc/architecture.md) for detailed architecture documentation.
## Development
```bash
# Build everything
pnpm build
# Run all tests (188 tests)
pnpm test
# Type check all packages
pnpm typecheck
# Lint
pnpm lint
```
## License
MIT