Skip to content

Latest commit

Β 

History

History
382 lines (272 loc) Β· 13.4 KB

File metadata and controls

382 lines (272 loc) Β· 13.4 KB

OpenSpec Instructions

These instructions are for AI assistants working in this project.

Always open @/openspec/AGENTS.md when the request:

  • Mentions planning or proposals (words like proposal, spec, change, plan)
  • Introduces new capabilities, breaking changes, architecture shifts, or big performance/security work
  • Sounds ambiguous and you need the authoritative spec before coding

Use @/openspec/AGENTS.md to learn:

  • How to create and apply change proposals
  • Spec format and conventions
  • Project structure and guidelines

Keep this managed block so 'openspec update' can refresh the instructions.

Sanskrit Upaya - Go + Fyne + SQLite FTS5

Project Overview

Sanskrit Upaya ("Sanskrit Method/Tool") is a cross-platform Sanskrit dictionary desktop application built in Go. It provides fast full-text search across 36 digitized Sanskrit dictionaries from the Cologne Digital Sanskrit Dictionaries project.

Repository: github.com/licht1stein/sanskrit-upaya

Architecture

sanskrit-upaya/
β”œβ”€β”€ cmd/
β”‚   β”œβ”€β”€ desktop/          # Fyne UI application
β”‚   β”‚   β”œβ”€β”€ main.go       # Main app with UI, search, state management
β”‚   β”‚   └── bundled.go    # SVG icons (star, star-filled)
β”‚   β”œβ”€β”€ indexer/main.go   # One-time tool to build SQLite DB from JSON
β”‚   └── mcp/main.go       # MCP server for LLM integration
β”œβ”€β”€ pkg/
β”‚   β”œβ”€β”€ dictdata/         # Embedded dictionary metadata JSON
β”‚   β”œβ”€β”€ download/         # First-run database download from server
β”‚   β”œβ”€β”€ ocr/              # Google Cloud Vision OCR for Sanskrit/Devanagari
β”‚   β”œβ”€β”€ gcloud/           # Google Cloud CLI utilities (shared between desktop and MCP)
β”‚   β”œβ”€β”€ search/search.go  # SQLite FTS5 search engine + dict filtering
β”‚   β”œβ”€β”€ state/state.go    # User settings, history, starred articles (SQLite)
β”‚   └── transliterate/    # IAST ↔ SLP1 ↔ Devanagari conversion
β”œβ”€β”€ .github/workflows/    # GitHub Actions for cross-platform builds
β”œβ”€β”€ sanskrit.db           # Pre-built FTS5 database (generated, ~670MB) - NOT in repo
β”œβ”€β”€ shell.nix             # Nix development environment
└── go.mod

First-Run Database Download

The dictionary database (~670MB) is NOT bundled with the binary. On first run:

  1. App checks for ~/.local/share/sanskrit-dictionary/sanskrit.db
  2. If missing, shows download dialog with progress bar
  3. Downloads from https://sanskrit.myke.blog/dict.db with secret header
  4. Saves to data directory

Server setup (nginx on sanskrit.myke.blog):

  • Database file: /mnt/photos/sanskrit.db
  • Protected by header: X-Sanskrit-Mitra: mitra-2024-sanskrit-app
  • Without header: 403 Forbidden

pkg/download/download.go handles the download logic with progress callback.

Key Features (Implemented)

  • 4 Search Modes: Exact, Prefix, Contains (fuzzy), Full-text (reverse)
  • Dictionary Selection: Filter search by dictionary, grouped by language direction (saβ†’en, saβ†’de, etc.)
  • Starred Articles: Save favorite articles with star/unstar functionality
  • Search History: Track and recall previous searches
  • Result Grouping: Toggle between grouped (by word) and ungrouped views
  • Zoom Control: 50%-200% UI scaling with Ctrl/Cmd +/-
  • Keyboard Navigation: Arrow keys to navigate results, Ctrl/Cmd+K to focus search
  • Transliteration: Auto-converts between IAST and Devanagari for search
  • OCR Support: Recognize Sanskrit/Devanagari text from images (PNG, JPG, TIFF, PDF) via Google Cloud Vision
  • MCP Server: LLM integration via Model Context Protocol for Claude Code and other MCP clients

Key Design Decisions

  1. SQLite FTS5 for search - O(log n) indexed lookups vs O(n) regex scanning
  2. Pure Go SQLite - Uses modernc.org/sqlite (no CGO required)
  3. Fyne for UI - Cross-platform GUI (Windows, macOS, Linux, Android, iOS)
  4. Separate state DB - User settings stored in ~/.local/share/sanskrit-dictionary/state.db
  5. BreakVer versioning - See https://www.taoensso.com/break-versioning

Building

# First time: download dependencies
go mod tidy

# Build the search database (only needed once)
# Dictionary JSON files from: https://github.com/ashtadhyayi-com/data
go run ./cmd/indexer -input /path/to/csl-json/ashtadhyayi.com/ -output sanskrit.db

# Run desktop app
go run ./cmd/desktop

# Build release binary
go build -o sanskrit-upaya ./cmd/desktop

# Build MCP server
go build -o sanskrit-mcp ./cmd/mcp

Desktop OCR

The desktop app includes OCR functionality for recognizing Sanskrit/Devanagari text from images.

Using OCR

  1. Click the OCR button in the toolbar (or press Ctrl/Cmd+O)
  2. If first time, complete the setup wizard (requires Google Cloud CLI)
  3. Drop an image file (PNG, JPG, TIFF, PDF) onto the window
  4. View and edit the recognized text
  5. Click Search to look up recognized words in the dictionary

OCR Setup

The desktop app includes a setup wizard that guides you through:

  1. Installing Google Cloud CLI (if not present)
  2. Authenticating with your Google account
  3. Creating a GCP project for Vision API
  4. Enabling the Vision API
  5. Setting up Application Default Credentials

Free tier: 1000 images/month, then $1.50/1000.

Keyboard Shortcuts

  • Ctrl/Cmd+O: Open OCR window

MCP Server

The MCP (Model Context Protocol) server enables LLMs like Claude to search Sanskrit dictionaries directly. It runs as a stdio-based server communicating via JSON-RPC 2.0.

Claude Code Configuration

Add to your Claude Code MCP settings (~/.config/claude/claude_desktop_config.json or similar):

{
  "mcpServers": {
    "sanskrit": {
      "command": "/path/to/sanskrit-mcp"
    }
  }
}

Available Tools

Tool Description
sanskrit_search Search dictionaries with 4 modes: exact, prefix, fuzzy, reverse
sanskrit_list_dictionaries List all 36 dictionaries with descriptions
sanskrit_get_article Retrieve full article content by ID
sanskrit_transliterate Convert between IAST and Devanagari
sanskrit_ocr OCR Sanskrit/Devanagari text from images (requires GCP setup)

Example Usage (from Claude)

  • "Search for 'yoga' in Monier-Williams dictionary"
  • "What does 'dharma' mean? Search in exact mode"
  • "Transliterate 'namaste' to Devanagari"
  • "List available Sanskrit dictionaries"
  • "OCR this Sanskrit manuscript image"

OCR Setup

The sanskrit_ocr tool requires Google Cloud Vision API credentials. Run the setup command:

sanskrit-mcp ocr-setup

This will:

  1. Check/install gcloud CLI authentication
  2. Create a GCP project sanskrit-upaya-ocr
  3. Enable Vision API
  4. Configure Application Default Credentials

Free tier: 1000 images/month, then $1.50/1000.

Prerequisites

The MCP server requires the dictionary database at ~/.local/share/sanskrit-dictionary/sanskrit.db. Run the desktop app first to download it, or place the database manually.

NixOS / Nix Users

nix-shell   # Enter dev environment with all dependencies
go run ./cmd/desktop

Releasing

Releases are built automatically via GitHub Actions on tag push.

Versioning (BreakVer)

Uses BreakVer: v<major>.<minor>.<non-breaking>

  • Major: Breaking changes (rare, signals major overhaul)
  • Minor: May contain breaking changes (read changelog)
  • Non-breaking: Bug fixes, safe updates (always safe to upgrade)

Creating a Release

# Create and push a tag
git tag v1.0.0
git push origin v1.0.0

GitHub Actions will automatically:

  1. Build binaries for Linux (amd64), Windows (amd64), macOS (Intel), macOS (Apple Silicon)
  2. Create a GitHub Release with all artifacts
  3. Generate release notes from commits

Manual Build Testing

You can manually trigger the workflow from GitHub Actions UI (workflow_dispatch) to test builds without creating a release.

Build Artifacts

Binary names include the version tag (e.g., for v1.0.0):

  • sanskrit-upaya-v1.0.0-linux-amd64 - Linux x86_64
  • sanskrit-upaya-v1.0.0-windows-amd64.exe - Windows x86_64
  • sanskrit-upaya-v1.0.0-macos-intel - macOS Intel (x86_64)
  • sanskrit-upaya-v1.0.0-macos-apple-silicon - macOS Apple Silicon (arm64)

Updating Database Checksum

When updating the dictionary database on the server:

  1. Upload new database to server
  2. Get SHA256 checksum: sha256sum /path/to/sanskrit.db
  3. Update ExpectedChecksum in pkg/download/download.go
  4. Create new release - users will auto-download on next app start

Database Schema

-- Main search database (sanskrit.db)
dicts(code, name, from_lang, to_lang, favorite)
articles(id, dict_code, content)
words(id, word_iast, word_deva, article_id, dict_code)
words_fts(word_iast, word_deva)      -- FTS5 virtual table
articles_fts(content)                 -- FTS5 virtual table

-- User state database (~/.local/share/sanskrit-dictionary/state.db)
settings(key, value)                  -- Key-value store (zoom, selected_dicts, etc.)
history(id, query, count, last_used)  -- Search history
starred(id, article_id, word, dict_code, created_at)  -- Starred articles

Code Structure

cmd/desktop/main.go

  • scaledTheme - Custom theme wrapper for zoom functionality
  • GroupedResult / DictEntry - Data structures for result grouping
  • pillLabel - Custom widget for dictionary code badges
  • createArticleContent() - Renders article with search term highlighting
  • doSearch() - Main search function with background goroutine
  • navigateTo() - Displays selected result with star button
  • Dialog builders for: History, Starred Articles, Dictionary Selection

cmd/desktop/ocr.go

  • OCRWindow - Separate window for OCR functionality
  • Drop zone UI with drag-and-drop support
  • Processing state with spinner and cancel
  • Result editor with copy/search integration
  • File validation (extension, size limits)

cmd/desktop/ocr_setup.go

  • OCRSetupWizard - GUI wizard for Google Cloud setup
  • Step-by-step progress through: auth β†’ project β†’ API β†’ ADC
  • Real-time command output streaming
  • Error handling with re-run capability
  • Billing setup integration

pkg/search/search.go

  • Search(query, mode, dictCodes) - Main search with optional dict filtering
  • GetDicts() - Returns all dictionary metadata
  • GetArticle(id) - Retrieves single article (for starred view)
  • Supports 4 search modes: ModeExact, ModePrefix, ModeFuzzy, ModeReverse

pkg/state/state.go

  • Get/Set/GetBool/SetBool - Key-value settings
  • AddHistory/SearchHistory/GetRecentHistory - Search history
  • StarArticle/UnstarArticle/IsStarred/GetStarredArticles - Starring

pkg/transliterate/

  • IASTToDevanagari() / DevanagariToIAST()
  • ToSearchTerms() - Returns both IAST and Devanagari variants for search
  • IsDevanagari() - Detects script type

cmd/mcp/main.go

  • MCP server using github.com/modelcontextprotocol/go-sdk/mcp
  • 5 tools: sanskrit_search, sanskrit_list_dictionaries, sanskrit_get_article, sanskrit_transliterate, sanskrit_ocr
  • ocr-setup subcommand for automated Google Cloud setup
  • Lazy database initialization (checks on first tool call)
  • Embedded dictionary descriptions from pkg/dictdata/dictionaries.json

pkg/ocr/ocr.go

  • Google Cloud Vision API client wrapper
  • NewClient(ctx) - Creates client using Application Default Credentials
  • RecognizeText/RecognizeFile/RecognizeBase64 - OCR methods
  • CheckCredentials(ctx) - Verifies API access
  • Image format validation (PNG, JPG, TIFF, PDF) via magic bytes
  • 30-second timeout, 20MB size limit

pkg/gcloud/gcloud.go

  • Shared Google Cloud CLI utilities
  • IsInstalled(), IsAuthenticated() - CLI status checks
  • HasApplicationDefaultCredentials() - ADC check
  • GetOrCreateOCRProjectID() - Persistent project ID management
  • RunCommand(), RunCommandAsync() - Command execution with output streaming
  • OpenBrowser() - Platform-specific browser opening

TODO / Future Work

  • GitHub Actions workflow for cross-platform releases
  • Database checksum verification and auto-redownload
  • Theme switching (light/dark/system)
  • Devanagari virtual keyboard
  • Mobile builds with bundled database
  • Export starred articles
  • Dictionary info/about dialog

Data Source

Dictionary data from Cologne Digital Sanskrit Dictionaries:

  • 36 dictionaries
  • ~1.3M words
  • ~1.3M articles
  • JSON format from ashtadhyayi.com

Performance Notes

  • Database uses WAL mode and mmap for fast reads
  • Bulk indexing: ~44 seconds for 1.3M words
  • Database size: ~670MB
  • Queries limited to 1000 results
  • First search may be slow (memory mapping), subsequent searches are fast

Dependencies

  • fyne.io/fyne/v2 - Cross-platform UI framework
  • modernc.org/sqlite - Pure Go SQLite
  • github.com/modelcontextprotocol/go-sdk/mcp - MCP server SDK (for cmd/mcp)
  • cloud.google.com/go/vision/v2 - Google Cloud Vision API (for OCR)

Common Issues

  1. "Database not loaded" - Run indexer first to create sanskrit.db
  2. Devanagari not rendering - Install Noto Sans Devanagari font
  3. Slow first search - Normal, database is memory-mapped on first access
  • Always build ./sanskrit locally