Skip to content

Repository files navigation

Chai (拆) - Reading, Highlights, and Export

中文

What is Chai (拆)

“拆” (chāi) — to dismantle, break down, and digest complex knowledge into your own understanding.

Chai is a lightweight Emacs reading workflow. It does not move text into a separate note-taking system; instead, you read directly in ordinary Org files and leave lightweight marks where they belong. Chai then gives those marks color, mouse actions, annotation overlays, context navigation, and structured export.

Early versions of Chai included a heavier Refinery workflow: content was forked into a separate workbench, rewritten there, and then saved as notes. The current design is much lighter:

  • Source files stay plain .org files.
  • Highlights are standard Org links: [[chai:TYPE][TEXT]].
  • Comments are standard Org special blocks: #+BEGIN_CHAI_COMMENT ... #+END_CHAI_COMMENT.
  • Export results are ordinary Org headlines with property drawers.
  • Save, copy, and edit all work through native Org/Emacs mechanisms.

Without Chai, the files remain readable and editable as normal Org documents. With Chai enabled, the same syntax gains semantic faces, mouse commands, note overlays, a context panel, and one-key export.

The workflow has three parts:

  1. Library — Manage reading materials as Org files
  2. Highlights & Comments — Mark important fragments while reading
  3. Export & Preview — Copy or preview an Org export of your marks

📖 Read in Library → 🔖 Highlight / Comment → ✍️ Export / Preview into your notes

Demo

pics/demo.gif

Installation

Dependencies

  • Emacs 29.1+
  • Pandoc (file conversion, used by import)
  • Python 3.x + PyMuPDF (PDF processing, used by import)
  • transient (Library quick-command menu only)

macOS OCR Support (Optional)

pip install pyobjc-framework-Vision Pillow

⚠️ OCR features are only available on macOS, using Apple Vision framework for scanned PDFs.

Configuration

;; Add to load-path
(add-to-list 'load-path "~/path/to/chai/")

;; Load core modules
(require 'chai)               ;; Highlights, comments, and export
(require 'chai-library)       ;; Library management
(require 'chai-library-table) ;; Library table interface

;; Optional: Global keybindings
(global-set-key (kbd "C-c l") #'chai-library-open)
(global-set-key (kbd "C-c b") #'chai-library-open-book)
(global-set-key (kbd "C-c i") #'chai-library-import)

Directories

Chai uses the following default directory structure (under ~/.emacs.d/chai/):

~/.emacs.d/chai/
├── library/          ;; Library files (managed .org files)
├── inbox/            ;; Import inbox
├── archive/          ;; Archived source files after import
└── exports/          ;; Editable export preview files

Customize via these variables:

VariableDescriptionDefault
chai-library-directoryLibrary directory~/.emacs.d/chai/library/
chai-library-import-inboxImport inbox~/.emacs.d/chai/inbox/
chai-library-import-archiveArchive directory~/.emacs.d/chai/archive/
chai-export-preview-directoryExport preview directory~/.emacs.d/chai/exports/

Library

Chai’s Library is a directory of Org files. Once an .org file is placed in chai-library-directory, it is automatically adopted when the library is opened or refreshed. You do not have to run an import command first.

Importing Files

If you start with PDF/Markdown/EPUB/HTML, use one of the import paths to convert them into Org and move them into the library:

  • M-x chai-library-import — Batch import all files from the inbox
  • C-u M-x chai-library-import — Import a single specified file
  • M-x chai-library-auto-rename-all — Rename/adopt all unmanaged .org files already in the library directory

For Web Pages: Copy as Org Mode Chrome Extension

For web articles, use the Copy as Org Mode browser extension. It supports defuddle, so copied pages include author, title, and other metadata already formatted as Org. Paste the result directly into chai-library-directory; Chai will adopt it with the metadata intact, no manual filename editing required.

From the terminal:

# Batch import
python convert-to-org.py \
  --temp ~/.emacs.d/chai/inbox/ \
  --reference ~/.emacs.d/chai/library/ \
  --archive ~/.emacs.d/chai/archive/

# Single file import
python convert-to-org.py \
  --file ~/Downloads/paper.pdf \
  --reference ~/.emacs.d/chai/library/

Supported Formats

  • PDF (supports scanned PDF OCR, macOS only)
  • Markdown
  • EPUB
  • HTML

Opening a Book Directly

Run M-x chai-library-open-book to show the Library’s filenames directly in the minibuffer. Type to filter, press RET, and Chai opens the selected Org file without opening the Library table first. The command only lists .org filenames; it does not parse book contents or metadata before selection.

File Naming Convention

Imported files use structured naming:

ID__Author__Title==keyword1_keyword2--status-rating.org

Delimiter meanings:

  • __ — Metadata separator (ID, author, title)
  • ==== — Keyword separator
  • -- — Status and rating

You can also run the batch rename script from the terminal:

emacs --batch -L . -l chai-library.el -l chai-library-batch-rename.el \
      --eval '(chai-library-batch-rename)'

Using the Library

Run M-x chai-library-open to open the library interface (full-frame):

pics/chai-library.png

KeyFunction
?Open the transient quick-command menu
RETOpen selected book/document
sSet reading status (unread/reading/done/archived)
r / 0-5Set rating (0-5 stars)
kSet keywords (comma-separated, stored in filename)
aManually rename/adopt selected file
dDelete file (requires confirmation)
/Filter by title/author/keywords
cClear filter
SToggle sort order
gRefresh list

The ? key opens a transient quick-command menu — it is a shortcut palette, not a persistent operating panel. Use it to run a single command and return to the table.

Refresh (g) preserves the current book/selection position when possible.

Evil is automatically disabled in chai-library-mode so that the plain keymap above is not shadowed by Evil bindings.

Customize Library keys with chai-library-keybindings. If you change it after loading Chai, run M-x chai-library-apply-keybindings.

(setq chai-library-keybindings
      '(("RET" . chai-library-open-book-at-point)
        ("R"   . chai-library-refresh)
        ("K"   . chai-library-set-keywords)))
(chai-library-apply-keybindings)

Highlights and Comments

Storage Syntax

While reading an Org file, mark fragments with Chai links and free-standing comment blocks:

  • Highlighted text: [[chai:TYPE][TEXT]]
  • Highlighted text with annotation: [[chai:TYPE:NOTE][TEXT]]
  • Free-standing comment: #+BEGIN_CHAI_COMMENT#+END_CHAI_COMMENT

Commands

CommandFunction
M-x chai-highlight-regionHighlight selected region
M-x chai-highlight-annotateHighlight selected region with note
M-x chai-remove-highlightRemove highlight at point
M-x chai-add-commentPrompt for a free-standing comment
M-x chai-insert-commentInsert a #+BEGIN_CHAI_COMMENT block
M-x chai-export-highlights-copyCopy highlights and comments as plain text
M-x chai-export-highlights-copy-orgCopy highlights and comments as Org markup
M-x chai-export-previewOpen editable Org preview buffer
M-x chai-export-preview-saveSave Org export directly to the preview file
M-x chai-context-panel-toggleToggle highlight overview panel
M-x chai-refresh-annotationsRefresh annotation overlays

Highlighting System

Chai provides 12 semantic highlight types. Each type is rendered with a face, so highlights are visible directly in the buffer. Faces work in both light and dark themes, and you can customize them or add your own types.

Right-click anywhere in a Chai-enabled Org buffer to add a free-standing comment. Right-click a chai link to change type, edit the note, remove the highlight, or copy the highlighted text. With an active region, right-click to highlight it with any type from chai-highlight-types.

The context menu also shows region commands. Use them with an active region:

  • Chai: highlight region… — choose any highlight type for the region
  • Chai: highlight TYPE — quick entries generated from chai-highlight-types
  • Highlight with note… — highlight the region and attach a note (annotation)
  • Chai: add comment — wrap the region in a #+BEGIN_CHAI_COMMENT block

If no region is active, Chai: add comment inserts an empty comment block at point.

pics/chai-context-menu.png

pics/chai-annotation.png

Built-in Types

  • 🔴 important — Important viewpoint
  • 🟢 idea — Inspiration/thought
  • 🟠 question — Question
  • 🟡 critical — Critical content
  • 💛 key — Central idea/main point (yellow)
  • 🔴 core — Definition/core concept (red/orange)
  • 🟢 detail — Data/key details (green, underline)
  • 🔵 example — Cases/supporting evidence (blue, underline)
  • 🟣 hard — Difficulty/logical turn (purple, wavy)
  • block — Complete viewpoint paragraph (grey, border)
  • 🟪 view — Author’s opinion/personal insight (purple)
  • outdated — Excluded/outdated info (strikethrough)

Customize highlight types:

(setq chai-highlight-types
      '(("important" . chai-highlight-important)
        ("idea" . chai-highlight-idea)
        ("key" . chai-highlight-key)
        ;; ... add custom types
        ("todo" . hl-line)))

Context Panel

Press C-c p (when bound) to toggle a side window showing all highlights grouped by type. The current highlight’s group is highlighted for easy navigation.

Free-Standing Comments

Use #+BEGIN_CHAI_COMMENT blocks for notes that are not attached to a specific highlighted fragment:

This is my own thought about the section above.
  • M-x chai-add-comment prompts for comment text and inserts a complete block.
  • M-x chai-insert-comment inserts an empty block, or wraps the active region.
  • Comments are collected and exported together with highlights in source order.

Export Format

Chai distinguishes between storage syntax (what you type while reading) and export syntax (what is copied to the kill ring or shown in the preview buffer).

M-x chai-export-highlights-copy-org copies highlights and comments as source-ordered Org headlines. Each highlight type becomes a TODO keyword, and source metadata lives in a :PROPERTIES: drawer. The #+SEQ_TODO: line is generated dynamically from your chai-highlight-types, with COMMENT appended for free-standing comments.

The file header prefers the source Org buffer’s #+TITLE, falls back to the source file’s base name, and finally to “Chai Export” when no source is known.

M-x chai-export-preview opens the same export in an editable *Chai Export Preview* buffer. The buffer is associated with ~/.emacs.d/chai/exports/<source-base>_chai.org (customize via chai-export-preview-directory) so you can edit it and press C-x C-s to save normally. No file is written until you save.

M-x chai-export-preview-save writes the same export directly to that file.

#+TITLE: Source Title
#+SOURCE: /path/to/source.org
#+EXPORTED_AT: 2026-06-21 12:30
#+SEQ_TODO: IMPORTANT IDEA QUESTION KEY COMMENT

* IMPORTANT highlighted text
:PROPERTIES:
:SOURCE: [[file:/path/to/source.org::25][L25]]
:END:

Annotated highlights keep the note in a #+BEGIN_CHAI_ANNOTATION block under the headline:

* IDEA highlighted text
:PROPERTIES:
:SOURCE: [[file:/path/to/source.org::25][L25]]
:END:
annotation text

Free-standing comments export as COMMENT headlines:

* COMMENT free-standing comment text
:PROPERTIES:
:SOURCE: [[file:/path/to/source.org::120][L120]]
:END:

The L25 link jumps to the source line in the original file.

Commands Reference

Library Commands

CommandFunction
M-x chai-library-openOpen the Library table
M-x chai-library-open-bookSelect a book in the minibuffer and open it
M-x chai-library-importImport files from inbox (or a single file with prefix)
M-x chai-library-auto-rename-allRename/adopt all unmanaged .org files in the library directory
M-x chai-library-refreshRefresh the Library table
M-x chai-library-set-statusSet reading status for book at point
M-x chai-library-set-rating / 0-5Set rating for book at point
M-x chai-library-set-keywordsSet keywords for book at point
M-x chai-library-deleteDelete book at point
M-x chai-library-apply-keybindingsRe-apply custom chai-library-keybindings

Reading / Highlight Commands

CommandFunction
M-x chai-highlight-regionHighlight selected region
M-x chai-highlight-annotateHighlight selected region with note
M-x chai-remove-highlightRemove highlight at point
M-x chai-add-commentPrompt for and insert a free-standing comment
M-x chai-insert-commentInsert a #+BEGIN_CHAI_COMMENT block
M-x chai-export-highlights-copyCopy marks as plain text
M-x chai-export-highlights-copy-orgCopy marks as Org markup
M-x chai-export-previewOpen editable Org preview buffer
M-x chai-export-preview-saveSave Org export directly to preview file
M-x chai-context-panel-toggleToggle highlight overview panel
M-x chai-refresh-annotationsRefresh annotation overlays

Quick Start

  1. Put materials in the library — Drop .org files into chai-library-directory, or import PDF/Markdown/EPUB/HTML with M-x chai-library-import.
  2. Open a book — run M-x chai-library-open-book to select one in the minibuffer, or run M-x chai-library-open and press RET on the current entry.
  3. Highlight — Select text and M-x chai-highlight-region or M-x chai-highlight-annotate.
  4. ExportM-x chai-export-highlights-copy-org and paste into your notes, or M-x chai-export-preview to edit and save the export directly.

Integration with Other Tools

Chai is designed to work alongside existing note-taking systems:

  • Org-roam — Paste exported highlights into Org-roam notes
  • Denote — Chai uses Denote-compatible timestamp IDs
  • Citar/Org-cite — Add #+BIBLIOGRAPHY references in book files

Contributing

Issues and PRs welcome!

  • Code style: Follow standard Emacs Lisp conventions
  • Tests: Add tests in test/ directory for new features
  • Documentation: Update this README to reflect changes

License

GPL-3.0-or-later

Author

Yibie <yibie@outlook.com>

Acknowledgments

  • Design philosophy inspired by Zettelkasten and Progressive Summarization

Changelog

v2.0.0 (2026-06)

  • Workflow redesign: Chai no longer forks content into a separate workbench. You now read directly in ordinary Org files, mark text with standard Org links ([[chai:TYPE][TEXT]]), add notes with standard Org blocks (#+BEGIN_CHAI_COMMENT), and export collected marks only when needed.
  • Refinery removed: The intermediate Refinery workbench and note-saving flow have been removed. Chai now focuses on Library management and highlight export.
  • Headline export: Org export now uses source-ordered headlines with dynamic #+SEQ_TODO keywords, source metadata in :PROPERTIES: drawers, and #+BEGIN_CHAI_ANNOTATION blocks for notes. The old CHAI_QUOTE / CHAI_COMMENT special blocks are gone.
  • Export preview: New M-x chai-export-preview opens an editable preview buffer, and M-x chai-export-preview-save writes directly to the preview file.
  • Export headers: Exported file titles now prefer the source #+TITLE and fall back to the source file name.
  • Library transient menu: ? opens a quick transient command menu in the Library table.
  • tp.el removed: Library table no longer depends on tp.el; status/rating changes refresh the standard tabulated-list display.
  • Batch rename retained: Duplicate auto-rename logic merged into a single core function used by both interactive import and the batch script.
  • README rewrite: README.org and README_cn.org rewritten around the current Library + Highlight/Comment + Export Preview workflow.
  • Browser extension: README now recommends Copy as Org Mode for importing web pages with metadata.

v1.1.0 (2026-02)

  • Library: Add k keybinding to set keywords for a book; keywords are encoded in the filename (===kw1_kw2= section) and searchable via =/
  • Library: Fix keywords column not refreshing after changes
  • Library: Open in full-frame window (delete-other-windows)
  • Annotations: Automatically render note overlays in any Org buffer containing chai links, without requiring chai-mode to be active

v1.0.0 (2025-01)

  • Initial release
  • Library knowledge base management
  • Highlighting and linking system
  • Context Panel for structured annotation review
  • macOS OCR support

About

"拆" (chāi) — to dismantle, break down, and digest complex knowledge into your own understanding.

Resources

Stars

63 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages