Looking for a simpler onboarding path? Check out the Getting Started: Beginner's Guide if you prefer to learn basic note management without SQL first. You can always come back to this guide when you're ready for advanced features!
Welcome to Jot! This guide is designed for experienced developers who want to unlock the full power of Jot in 15 minutes.
Unlike basic note tools, Jot gives you:
- SQL Querying: Query your entire markdown collection using DuckDB's powerful SQL engine
- Markdown Intelligence: Extract structure, statistics, and metadata from markdown files
- Automation Ready: JSON output designed for piping to jq, shell scripts, and external tools
- Developer-Friendly: CLI-native, git-compatible, markdown-native, zero external dependencies
Perfect for: Developers managing large markdown collections, building personal knowledge bases, automating note processing, and creating data-driven workflows.
Jot works best with your existing markdown files. No migration needed—just point it at your notes directory.
# Create a notebook from your existing markdown folder
jot notebook create "My Notes" --path ~/my-notes
# Verify the import worked
jot notes listYou should see your markdown files listed with titles extracted from frontmatter or filenames. For example:
### Notes (142)
- [Meeting Notes 2024-01] notes/meeting-notes-2024-01.md
- [Project Alpha Spec] notes/projects/alpha-spec.md
- [TODO List] notes/todo.md
Pro Tip: If you have multiple note collections (work, personal, projects), create separate notebooks:
jot notebook create "Work" --path ~/work/notes
jot notebook create "Personal" --path ~/personal/notes
jot notebook create "Projects" --path ~/projects/notes
# Switch between contexts automatically by changing directories
cd ~/work/notes && jot notes list # Uses "Work" notebookNow for the magic. Execute sophisticated queries against your entire note collection.
# Find all your markdown files
jot notes search --sql "SELECT file_path FROM read_markdown('**/*.md')"What this does: Queries all markdown files in your notebook using DuckDB's SQL engine, returning clean JSON.
# Search for "deadline" across all notes
jot notes search --sql \
"SELECT file_path, content FROM read_markdown('**/*.md', include_filepath:=true)
WHERE content ILIKE '%deadline%'
LIMIT 10"# Find your longest notes (by word count)
jot notes search --sql \
"SELECT file_path, (md_stats(content)).word_count as words
FROM read_markdown('**/*.md', include_filepath:=true)
ORDER BY words DESC
LIMIT 10"# Find all unchecked tasks in your notes
jot notes search --sql \
"SELECT file_path FROM read_markdown('**/*.md', include_filepath:=true)
WHERE content LIKE '%[ ]%'
ORDER BY file_path"# See word count distribution
jot notes search --sql \
"SELECT
CASE
WHEN (md_stats(content)).word_count < 500 THEN 'short'
WHEN (md_stats(content)).word_count < 2000 THEN 'medium'
ELSE 'long'
END as category,
COUNT(*) as count
FROM read_markdown('**/*.md')
GROUP BY category
ORDER BY count DESC"All the examples above just scratch the surface. For complete documentation:
- SQL Query Guide - Complete patterns and best practices
- SQL Functions Reference - Full function reference with examples
- DuckDB Markdown Extension - Official docs
All Jot query results are JSON—perfect for piping to tools and scripts.
# All SQL query results are automatically JSON
jot notes search --sql "SELECT file_path FROM read_markdown('**/*.md')"
# Output:
# [
# { "file_path": "notes/project-ideas.md" },
# { "file_path": "notes/meeting-notes.md" },
# ...
# ]# Get just the file paths for piping to other commands
jot notes search --sql "SELECT file_path FROM read_markdown('**/*.md')" \
| jq -r '.[].file_path'# Total word count across all notes
jot notes search --sql \
"SELECT (md_stats(content)).word_count FROM read_markdown('**/*.md')" \
| jq 'map(.word_count) | {
total: add,
count: length,
average: (add / length | round)
}'# Export as CSV
jot notes search --sql \
"SELECT file_path, (md_stats(content)).word_count FROM read_markdown('**/*.md')" \
| jq -r '.[] | [.file_path, .word_count] | @csv'
# Export as tab-separated
jot notes search --sql \
"SELECT file_path, (md_stats(content)).word_count FROM read_markdown('**/*.md')" \
| jq -r '.[] | [.file_path, .word_count] | @tsv'# Find markdown files and get real file size
jot notes search --sql "SELECT file_path FROM read_markdown('**/*.md')" \
| jq -r '.[].file_path' \
| xargs ls -lh
# Output:
# -rw-r--r-- 1 user group 42K Jan 20 12:34 notes/big-project.md# Count total lines across all notes
jot notes search --sql "SELECT file_path FROM read_markdown('**/*.md')" \
| jq -r '.[].file_path' \
| xargs wc -l | tail -1# Find notes created today and show their content
jot notes search --sql "SELECT file_path FROM read_markdown('**/*.md')" \
| jq -r '.[].file_path' \
| xargs find -mtime -1
# Combine with other tools
jot notes search --sql "SELECT file_path FROM read_markdown('**/*.md')" \
| jq -r '.[].file_path' \
| xargs ls -lh | awk '{print $9, $5}'Use cron + Jot for automated note processing:
#!/bin/bash
# Save as ~/bin/note-stats.sh
STATS=$(jot notes search --sql \
"SELECT
COUNT(*) as total_notes,
AVG((md_stats(content)).word_count) as avg_words
FROM read_markdown('**/*.md')" \
| jq '.[] | "\(.total_notes) notes, \(.avg_words) avg words"')
echo "$(date): $STATS" >> ~/note-stats.logAdd to crontab:
# Run daily at 9am
0 9 * * * ~/bin/note-stats.shNow that you understand the core capabilities, here are some practical workflows.
# Indexed knowledge base with search
jot notebook create "Knowledge" --path ~/knowledge
# Find related topics
jot notes search --sql \
"SELECT DISTINCT file_path FROM read_markdown('**/*.md', include_filepath:=true)
WHERE content ILIKE '%machine learning%' OR content ILIKE '%neural networks%'
ORDER BY file_path"
# Generate index of all notes
jot notes search --sql \
"SELECT file_path, (md_stats(content)).word_count FROM read_markdown('**/*.md')
ORDER BY file_path" \
| jq -r '.[] | "- [\(.file_path)](\(.file_path)) (\(.word_count) words)"'# Create notebook for project docs
jot notebook create "ProjectDocs" --path ~/projects/docs
# Find all decision records
jot notes search --sql \
"SELECT file_path FROM read_markdown('**/*.md', include_filepath:=true)
WHERE file_path LIKE '%decision%' OR file_path LIKE '%adr%'
ORDER BY file_path DESC LIMIT 20"
# Get documentation completeness
jot notes search --sql \
"SELECT
file_path,
CASE WHEN (md_stats(content)).word_count > 500 THEN 'complete' ELSE 'needs-work' END
FROM read_markdown('**/*.md')
ORDER BY (md_stats(content)).word_count DESC"# Create research notebook
jot notebook create "Research" --path ~/research
# Find all references to specific topics
jot notes search --sql \
"SELECT file_path FROM read_markdown('**/*.md', include_filepath:=true)
WHERE content LIKE '%@TODO%' OR content LIKE '%[CITATION NEEDED]%'"
# Get topic frequency (markdown headings)
jot notes search --sql \
"SELECT file_path, content FROM read_markdown('**/*.md', include_filepath:=true)
LIMIT 100" | jq '.[] | select(.content | startswith("#"))'# Weekly stats email
WEEKLY_REPORT=$(jot notes search --sql \
"SELECT
COUNT(*) as new_notes,
ROUND(AVG((md_stats(content)).word_count)) as avg_length
FROM read_markdown('**/*.md')" \
| jq '.[] | "Weekly: \(.new_notes) notes, \(.avg_length) avg words"')
echo "Subject: Weekly Notes Report" | \
{ cat; echo "$WEEKLY_REPORT"; } | \
mail -s "Weekly Notes Report" you@example.comYou now understand the Jot power-user workflow. Here's what's available for deeper dives:
- SQL Functions Reference — Complete list of available SQL functions and markdown-specific operations
- SQL Query Guide — Advanced patterns, performance tips, and security considerations
- JSON Output Guide — Comprehensive automation examples and tool integration patterns
- Notebook Discovery — Multi-notebook management and context-aware workflows
- Performance Optimization — Query large notebooks efficiently
- Security — Understanding query validation and sandbox restrictions
- Custom Workflows — Building shell scripts and automation
- Integration — Connecting with other tools and systems
# Verify your notebook is set up correctly
jot notes list
# Try a simple query first
jot notes search --sql "SELECT file_path FROM read_markdown('*.md') LIMIT 1"
# Check file patterns (use forward slashes, even on Windows)
# ✓ Good: '**/*.md', 'notes/*.md'
# ✗ Bad: '**\*.md', 'notes\.md'File patterns are resolved from your notebook's root directory:
# If your notebook is at ~/my-notes/
# Pattern '**/*.md' means: ~/my-notes/**/*.md
# Create a test file to verify
mkdir -p ~/my-notes/test
echo "# Test" > ~/my-notes/test/sample.md
# Then try:
jot notes search --sql "SELECT file_path FROM read_markdown('test/*.md')"Jot always returns an array of objects:
# Single result
[{"file_path": "notes.md"}]
# Multiple results
[{"file_path": "notes1.md"}, {"file_path": "notes2.md"}]
# Parse with jq
jot notes search --sql "SELECT file_path FROM read_markdown('**/*.md')" | jq '.[].file_path'For notebooks with 1000+ notes:
# Limit results
jot notes search --sql "... LIMIT 100"
# Filter early with WHERE clauses
jot notes search --sql "SELECT * FROM read_markdown('**/*.md') WHERE ..."
# See SQL optimization tips in sql-guide.md✅ Jot = Markdown + SQL + Automation
- Import your existing markdown instantly—no migration needed
- Query using SQL to find patterns and insights across your notes
- Automate with JSON output for shell scripts and external tools
- Scale efficiently from dozens to thousands of notes
✅ Your New Superpowers
- Find any note by content, pattern, or metadata
- Calculate statistics and generate reports
- Build automated workflows and monitoring
- Integrate with Unix tools, shell scripts, and external systems
✅ What's Different
Most note tools give you basic search. Jot gives you a full database query language over your markdown—a unique combination of simplicity and power.
- Import Workflow Guide - Comprehensive guide for importing existing markdown collections
- Step-by-step import process for all scenarios
- Migration from Obsidian, Bear, and generic markdown folders
- Troubleshooting common import issues
- SQL Quick Reference - Progressive learning path with 20+ practical examples
- Level 1: Basic queries
- Level 2: Content search
- Level 3: Metadata analysis
- Level 4: Complex queries
- Practice exercises for each level
- SQL Query Guide - Detailed query documentation and patterns
- SQL Functions Reference - Complete SQL function list
- JSON Output Guide - Automation and tool integration
- Notebook Discovery - Manage multiple notebooks and contexts
- Check the SQL Quick Reference to start learning SQL progressively
- Read the SQL Guide for advanced query patterns
- See the Import Guide if you're having import issues
- Join the Community on GitHub