{"id":"166b405d-b697-4eb8-a76d-49756a108cd6","slug":"handwritten-math-to-obsidian","kind":"skill","name":"handwritten-math-to-obsidian","summary":"Codex skill for converting handwritten math notes into Obsidian-ready Markdown","owner":"TonyLiuYX","repoUrl":"https://github.com/TonyLiuYX/handwritten-math-to-obsidian","license":"MIT","licenseTier":"permissive","trust":"community","stars":3,"match":null,"fewStars":true,"format":"skill","createdAt":"2026-06-11T15:14:29.000Z","addedAt":"2026-10-22T01:17:01.688Z","logoUrl":"https://avatars.githubusercontent.com/u/231843420?v=4","linkOnly":false,"collection":null,"skillPath":null,"categories":["files-documents","productivity"],"tags":[],"runtime":"python","local":true,"cloudCapable":false,"cloudCapability":"unknown","cloudReadyOnPlatform":false,"needsApiKey":false,"reviewed":false,"syncedAt":"2026-10-25T19:38:20.898Z","sample":false,"url":"https://conduits.dev/tools/handwritten-math-to-obsidian","language":"Python","transports":["stdio"],"install":{"pypi":"handwritten-math-obsidian"},"requirements":{"env":[],"upstreamMayCharge":false},"tools":null,"readme":"# Handwritten Math to Obsidian\n\n> Turn a batch of handwritten mathematics photos into one faithful, reviewable, visual-rich Obsidian course note—not just OCR text.\n\n[![CI](https://github.com/TonyLiuYX/handwritten-math-to-obsidian/actions/workflows/quality.yml/badge.svg)](https://github.com/TonyLiuYX/handwritten-math-to-obsidian/actions/workflows/quality.yml)\n[![Python 3.10+](https://img.shields.io/badge/Python-3.10%2B-3776AB?logo=python&logoColor=white)](https://www.python.org/)\n[![License: MIT](https://img.shields.io/badge/License-MIT-2ea44f.svg)](LICENSE)\n[![Status: public beta](https://img.shields.io/badge/status-public_beta-f59e0b)](CHANGELOG.md)\n\n[简体中文](README.zh-CN.md) · [Quick start](#60-second-quick-start) · [Example](#what-the-result-looks-like) · [Roadmap](ROADMAP.md) · [Contributing](CONTRIBUTING.md)\n\n<p align=\"center\">\n  <img src=\"pictures/demo.gif\" alt=\"Handwritten calculus pages moving through ambiguity review into a visual-rich Obsidian course note\" width=\"920\">\n</p>\n\nMost handwriting tools stop at recognized text or a formula. This project provides an Agent Skill plus a safe CLI that carries the whole workflow: order multiple pages, surface ambiguous symbols, preserve derivations and side notes, generate useful teaching figures, validate every link and attachment, and preview an Obsidian import before anything is written.\n\nIt works with [Codex Skills](https://learn.chatgpt.com/docs/build-skills) and [Claude Code Skills](https://code.claude.com/docs/en/skills). The agent performs visual understanding; `math2obsidian` handles repeatable file, validation, rendering, installation, and import operations.\n\n## Why this is useful\n\n- **Multi-page continuity:** turn a lecture or study session into one maintainable note instead of unrelated snippets.\n- **Human review where it matters:** ask about `a` versus `α`, missing minus signs, page order, and suspected source mistakes before they silently propagate.\n- **Math-native output:** preserve detailed derivations as Obsidian Markdown and MathJax LaTeX.\n- **Visual explanations:** recreate exact graphs as deterministic SVG and use diagrams only where they improve learning.\n- **Traceable bundles:** retain stable source IDs, hashes, manifests, a source index, and a conversion report.\n- **Safe-by-default import:** portable folder first, vault preview second, explicit `--apply` and `--overwrite` only when intended.\n- **No separate API key or CLI telemetry:** use the visual model already available in Codex or Claude Code; the CLI itself does not call a model API or collect usage data.\n\n## 60-second quick start\n\nYou need Python 3.10+ and either Codex or Claude Code. Obsidian is optional until you want to open or import the result.\n\n```bash\ngit clone https://github.com/TonyLiuYX/handwritten-math-to-obsidian.git\ncd handwritten-math-to-obsidian\npipx install .\nmath2obsidian doctor\n```\n\nInstall the packaged Skill for your agent:\n\n```bash\n# Codex user scope (~/.agents/skills)\nmath2obsidian skill install --agent codex --scope user\n\n# Claude Code project scope (.claude/skills in the selected project)\nmath2obsidian skill install \\\n  --agent claude \\\n  --scope project \\\n  --project-dir /path/to/your/project\n```\n\nThen attach your pages and invoke it explicitly:\n\n```text\n# Codex\nUse $handwritten-math-to-obsidian to convert these pages into a Chinese-English\nMATH101 Obsidian note. Ask me about ambiguous symbols and preview the import.\n\n# Claude Code\n/handwritten-math-to-obsidian Convert these pages into a Chinese-English\nMATH101 Obsidian note. Ask me about ambiguous symbols before finalizing it.\n```\n\nWant to inspect the format before using private notes?\n\n```bash\nmath2obsidian demo --output .\nmath2obsidian validate ./MATH101-calculus-demo\n```\n\nWhen the PyPI release is available, the package can also be installed with `pipx install handwritten-math-obsidian` or run ephemerally with `uvx --from handwritten-math-obsidian math2obsidian doctor`.\n\n## What the result looks like\n\nThe public sample starts with five calculus pages and produces English, Chinese, and mixed-language variants. The important part is not the translation—it is the retained reasoning, review trail, figures, and Obsidian-ready structure.\n\n<p align=\"center\">\n  <img src=\"pictures/n1.jpg\" alt=\"First sanitized handwritten calculus sample page\" width=\"165\">\n  <img src=\"pictures/n2.jpg\" alt=\"Second sanitized handwritten calculus sample page\" width=\"165\">\n  <img src=\"pictures/n3.jpg\" alt=\"Third sanitized handwritten calculus sample page\" width=\"165\">\n  <img src=\"pictures/n4.jpg\" alt=\"Fourth sanitized handwritten calculus sample page\" width=\"165\">\n  <img src=\"pictures/n5.jpg\" alt=\"Fifth sanitized handwritten calculus sample page\" width=\"165\">\n</p>\n\n| English | 中文 | Chinese–English |\n|---|---|---|\n| ![English Obsidian note](pictures/main-en.png) | ![Chinese Obsidian note](pictures/main-zh.png) | ![Mixed-language Obsidian note](pictures/main-mix.png) |\n\nExample PDFs are available in [`results/`](results/). They demonstrate output style, not a benchmark claim. Model behavior can vary, so validate important mathematics against the source.\n\n## How it works\n\n```mermaid\nflowchart LR\n  A[Photos / scans / PDF] --> B[Inspect order and ambiguities]\n  B --> C[Prepare portable bundle]\n  C --> D[Transcribe and organize with the Skill]\n  D --> E[Generate exact SVG / useful diagrams]\n  E --> F[Validate notes, links, manifests and privacy]\n  F --> G{Destination}\n  G --> H[Keep portable folder]\n  G --> I[Preview vault import]\n  I --> J[Apply only with approval]\n```\n\nThe separation is intentional: the agent handles the judgments that require visual and mathematical context; the CLI handles deterministic operations that should be repeatable and testable.\n\nThe default bundle is ordinary Markdown and assets:\n\n```text\nMATH101-calculus/\n├── MATH101-calculus.md\n├── conversion-report.md\n├── print-page-numbers.css\n└── attachments/MATH101-calculus/\n    ├── source-001.jpg\n    ├── source-002.jpg\n    ├── generated-figure-001.svg\n    ├── conversion-manifest.json\n    ├── figure-manifest.json\n    └── source-index.md\n```\n\n## CLI\n\n| Command | Purpose | Writes by default? |\n|---|---|---:|\n| `math2obsidian doctor` | Check Python, agents, Obsidian CLI, and Skill installation | No |\n| `math2obsidian skill install` | Install the bundled Skill for Codex or Claude Code | Yes, unless `--dry-run` |\n| `math2obsidian prepare` | Normalize ordered inputs and create a traceable starter bundle | Yes |\n| `math2obsidian render` | Render a deterministic mathematical SVG from a JSON spec | Yes |\n| `math2obsidian validate` | Check structure, links, LaTeX delimiters, manifests, paths, and privacy | No |\n| `math2obsidian import` | Resolve and preview an Obsidian vault import | **No**; add `--apply` |\n| `math2obsidian demo` | Create a privacy-safe sample bundle and next-step prompt | Yes |\n\nEvery command supports `--json`, including usage errors. Machine output uses a stable envelope with `schema_version`, `ok`, `issues`, and `artifacts`. Exit codes are `0` for success, `1` for a runtime/validation failure, and `2` for invalid arguments.\n\n### Prepare a real bundle\n\n```bash\nmath2obsidian prepare \\\n  page-01.jpg page-02.jpg page-03.jpg \\\n  --output-dir ./exports \\\n  --course-code MATH101 \\\n  --note-title \"Calculus\" \\\n  --topic \"Limits and precise definitions\" \\\n  --language zh-en\n```\n\n### Render an exact figure\n\n```bash\nmath2obsidian render \\\n  --spec ./figure-spec.json \\\n  --out ./exports/MATH101-calculus/attachments/MATH101-calculus/generated-figure-001.svg\n```\n\n### Validate and safely import\n\n```bash\nmath2obsidian validate ./exports/MATH101-calculus\n\n# Preview only: resolves destinations and conflicts without writing\nmath2obsidian import ./exports/MATH101-calculus \\\n  --vault \"Study\" \\\n  --dest-folder calculus \\\n  --main-note MATH101-calculus.md\n\n# Repeat with --apply only after reviewing the preview\nmath2obsidian import ./exports/MATH101-calculus \\\n  --vault \"Study\" \\\n  --dest-folder calculus \\\n  --main-note MATH101-calculus.md \\\n  --apply\n```\n\nRun `math2obsidian <command> --help` for the complete option set. Legacy `scripts/*.py` entry points remain available for existing integrations, but new workflows should use `math2obsidian`.\n\n## Supported inputs and workflows\n\n- Phone photos, scans, and vector fixtures: JPEG, PNG, SVG, WebP, HEIC, TIFF, GIF, BMP, and AVIF.\n- PDF source batches.\n- Chinese, English, and mixed Chinese–English notes.\n- New course notes, append workflows, and section-aware merges against Markdown, text, PDF, or DOCX references.\n- Precise coordinate visuals, concept maps, and original-source embeds.\n- Portable folder delivery with optional Obsidian CLI or filesystem import.\n\nPlatform target: Linux, macOS, and Windows with Python 3.10–3.14. Obsidian's CLI remains optional; its availability and behavior vary by Obsidian installation and platform.\n\n## Privacy and safety\n\nHandwritten pages often contain more than mathematics. This project therefore treats privacy and path safety as release criteria:\n\n- the CLI does not upload source files, call a model API, or collect telemetry;\n- image understanding happens in the Codex or Claude Code host you choose, under that product's data controls;\n- distributable manifests use bundle-relative paths and hashes, not workstation paths;\n- validation detects sensitive image metadata, unsafe traversal, absolute paths, external symlinks, broken attachments, and inconsistent manifests;\n- repository sample photos are re-encoded without EXIF, GPS, device, or capture-time metadata;\n- imports preview first and refuse silent overwrite.\n\nDo not place private student information, unpublished research, assessment solutions, or third-party notes into a public issue. See [SECURITY.md](SECURITY.md) for private vulnerability reporting.\n\n## What this is—and is not\n\nThis is an orchestration and quality-control workflow, not a standalone handwriting OCR model. It complements OCR-focused products such as [Mathpix](https://mathpix.com/) and open-source recognition tools such as [Pix2Text](https://github.com/breezedeus/Pix2Text); it does not claim higher recognition accuracy.\n\n| Need | This project | OCR/formula recognition tools |\n|---|---|---|\n| Recognize a formula or page | Uses the host agent's vision | Often the core capability |\n| Maintain multi-page lecture continuity | Core workflow | Depends on product/integration |\n| Ask the user about ambiguous symbols | Built-in review gate | Depends on product/integration |\n| Preserve suspected mistakes rather than silently fix them | Explicit policy and report | Depends on product/integration |\n| Generate learning-oriented figures | SVG/diagram workflow | Usually a separate step |\n| Produce a traceable Obsidian bundle | Native output contract | Usually requires integration |\n| Import safety | Preview, path checks, explicit apply/overwrite | Depends on integration |\n\nCurrent beta limitations:\n\n- transcription quality depends on image clarity and the host model;\n- dense, faint, rotated, cropped, or highly stylized writing needs more human review;\n- the workflow asks questions rather than guaranteeing fully unattended conversion;\n- deterministic SVG supports a bounded spec, not arbitrary symbolic plotting;\n- print page counters and `.base` behavior depend on the final Obsidian/export renderer;\n- generated notes are study aids, not authoritative mathematical or accessibility transcriptions.\n\n## Project structure\n\n```text\nskills/handwritten-math-to-obsidian/  # distributable Agent Skill\nsrc/math2obsidian/                    # unified CLI and validation core\nschemas/                              # manifest contracts\nscripts/                              # backward-compatible entry points\ntests/                                # unit, integration, safety, and privacy tests\ndocs/                                 # evaluation and launch playbooks\n```\n\nThe Skill intentionally contains only runtime instructions and references—no duplicate README or changelog.\n\n## Contributing\n\nGood contributions include a privacy-safe evaluation fixture, a Windows path regression test, a new deterministic figure case, a clearer ambiguity workflow, or a real conversion report with all personal data removed.\n\n```bash\ngit clone https://github.com/TonyLiuYX/handwritten-math-to-obsidian.git\ncd handwritten-math-to-obsidian\npython -m venv .venv\nsource .venv/bin/activate  # Windows: .venv\\Scripts\\activate\npython -m pip install -e \".[dev]\"\npytest\n```\n\nRead [CONTRIBUTING.md](CONTRIBUTING.md) before adding fixtures or changing public CLI behavior. The project follows the [Code of Conduct](CODE_OF_CONDUCT.md), accepts private security reports as described in [SECURITY.md](SECURITY.md), and tracks release priorities in [ROADMAP.md](ROADMAP.md).\n\nIf this workflow turns a pile of pages into a note you can actually keep learning from, consider starring the repository and sharing a redacted before/after case. A reproducible case or thoughtful issue is even more valuable than a star.\n\n## License\n\n[MIT](LICENSE) © project contributors.\n"}