Changelog
← Back to index · Guide
2026-02-24
Remote Claude Code task queue
- New
ClaudeTask model with status lifecycle: pending → running → completed/failed
- 4 API endpoints under
/api/claude/tasks/ (create, pending, claim, complete) secured with bearer token auth
- "Send to Claude Code" toggle added to the dictation UI — transcribed speech becomes a Claude instruction
transcribe_note management command accepts --claude-task flag to create a task after transcription
thoth_watcher.py: Mac-side polling daemon (stdlib only) that claims pending tasks, runs claude -p, and posts responses back as Thoth notes tagged "Claude Code"
- Response notes include the original instruction as a blockquote followed by Claude's response
ClaudeTaskAdmin registered with status filter, instruction excerpt, and raw_id note links
- Full flow tested: API → watcher →
claude -p → response note created
2026-02-23 (night)
Deployed to Raspberry Pi 5
- Full production deployment on Raspberry Pi 5 (8 GB RAM, Debian Bookworm aarch64)
- Gunicorn (3 workers) + nginx reverse proxy on port 80
- Accessible via Tailscale at
http://100.99.187.54/ and local network at http://192.168.86.53/
- PostgreSQL 15 database with all 4,344 notes, 40 categories, 1,107 author tags
- Systemd service (
thoth.service) auto-starts on boot
- All data backed up: code on GitHub (
mshamma/thoth-project), data rsynced to Pi (~11.4 GB total)
- Static files served directly by nginx, media (notes/resources) served from
/media/
2026-02-23 (evening)
Django + Postgres application built
- Django 6 app with Postgres backend serving the archive at
http://localhost:8000/
- 4,344 notes imported from
en_backup.db (pickled Evernote objects, XZ-compressed)
- 16,543 resources linked, 437 audio transcriptions connected
- TF-IDF emergent categorization: 40 categories generated from content analysis (scikit-learn), with 3-layer noise filtering (StopTerm table, regex patterns, max_df suppression)
- Notebook names preserved as tags only — zero influence on categorization
- Yahoo late-1990s directory-style index: grid of category cards with top notes
- Noguchi self-organization: viewing a note updates
last_accessed, bubbling it to the top of its category
- Full-text search via Postgres
SearchVector/SearchRank
- Note content served from pre-converted static HTML files with resource paths rewritten to
/media/
- Admin interface for managing stop terms, notes, categories, and tags
- Management commands:
import_notes, generate_categories
2026-02-23
Django application design documented
- Tech stack page updated with full Django + Postgres design: models, category generation (TF-IDF), Noguchi self-organization, Yahoo directory-style index, noise filtering (StopTerm table + pattern filter + TF-IDF)
- Key design decision: notebook names become tags with no organizational weight; categories are emergent from content analysis only
Back-to-index navigation
- Every note now has a "← Back to index" link at the top of the page
- Links use correct relative paths for both standalone notebooks (1 level) and stack notebooks (2 levels)
Guide and changelog
- Added
guide.html with full project documentation, usage instructions, and technical details
- Added
changelog.html (this file) for version history
- Both linked from the index header and from each other
- Neither file is overwritten by Phase 3 — maintained separately
Audio note tagging in index
- Notes containing audio recordings are now tagged with a 🎤 emoji in the index
- Legend added to the index header showing the total count of audio notes (222)
Whisper transcription complete
- All 443 audio files transcribed using Whisper
base model (437 with content, 6 empty/silent)
- 269,295 total words across all transcriptions
- Each transcription saved as
.txt alongside the audio file
- Collapsible transcription blocks injected into parent HTML notes
Initial archive build
- 4,344 notes extracted from 112 .enex files (78 standalone + 34 in 7 stacks)
- 16,543 resources (images, audio, PDFs, attachments) decoded and written to disk
- ENML converted to clean HTML with Evernote-like styling
- Web clippings preserved with original HTML structure
- Index page generated with notebooks grouped by stack
Bug fixes
- Fixed path encoding: switched from
html.escape() to urllib.parse.quote() for src/href attributes, fixing broken images in notes with apostrophes, emoji, or special characters in titles