Claude-skill-registry emacs-org

Use when working with Emacs org-mode - provides elisp patterns for headings, properties, tables, links, and org-mode manipulation

install
source · Clone the upstream repo
git clone https://github.com/majiayu000/claude-skill-registry
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/majiayu000/claude-skill-registry "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/data/emacs-org" ~/.claude/skills/majiayu000-claude-skill-registry-emacs-org && rm -rf "$T"
manifest: skills/data/emacs-org/SKILL.md
source content

Emacs Org-Mode Skill

Display Guidelines

E-ink Monitor Compatibility: User uses an e-ink monitor that only supports black, white, and grey.

  • NEVER use colors (
    :foreground "red"
    ,
    :foreground "cyan"
    , etc.)
  • Use
    :weight bold
    ,
    :weight light
    ,
    :slant italic
    ,
    :underline t
    for differentiation
  • Standard Emacs faces (font-lock-*-face) are acceptable as they adapt to themes

Org Properties

Get property with inheritance

(org-entry-get nil "PROPERTY_NAME" t)  ; t enables inheritance

Get property without inheritance

(org-entry-get nil "PROPERTY_NAME" nil)

Set property

(org-entry-put nil "PROPERTY_NAME" "value")

Safe property access (for header-line, mode-line contexts)

;; Wrap in ignore-errors when called from non-org-mode contexts
(ignore-errors
  (org-entry-get nil "PROPERTY_NAME" t))

Headings Navigation

Go to heading

(org-back-to-heading t)  ; t means error if not at heading

Walk up headings

(while (org-up-heading-safe)
  ;; process each parent heading
  )

Check if at heading

(org-at-heading-p)

Get current level

(org-current-level)  ; returns integer

Tags

Get tags for current heading

(org-get-tags nil t)  ; returns list of strings

Check for specific tag

(member "my_tag" (org-get-tags nil t))

Subtree Operations

Get subtree end

(save-excursion
  (org-end-of-subtree t t)
  (point))

Map over entries with tag

(org-map-entries
 (lambda ()
   ;; body executed at each matching heading
   (org-entry-get nil "PROPERTY"))
 "+my_tag")

File-Level Properties

Get file keyword (#+PROPERTY: NAME value)

(save-excursion
  (goto-char (point-min))
  (when (re-search-forward "^#\\+PROPERTY:\\s-+NAME\\s-+\\(.+\\)$" nil t)
    (match-string 1)))

Tables

Move in table

(org-table-goto-column 2)  ; go to column 2
(org-table-next-row)       ; go to next row

Get cell value

(org-table-get-field)  ; current cell
(org-table-get-field 3)  ; column 3 of current row

Links

Parse link at point

(org-element-context)  ; returns element with :path, :type properties

Create link

(org-link-make-string "https://example.com" "description")

Common Patterns

Safely get session info for mode-line

(defun my-get-session-id ()
  "Get session ID safely from any context."
  (ignore-errors
    (save-excursion
      (org-entry-get nil "SESSION_ID" t))))

Find heading with property value

(save-excursion
  (goto-char (point-min))
  (catch 'found
    (while (re-search-forward "^\\*+ " nil t)
      (when (equal "target" (org-entry-get nil "MY_PROP"))
        (throw 'found (point))))
    nil))

Insert property drawer

(org-back-to-heading t)
(forward-line 1)
(insert ":PROPERTIES:\n")
(insert ":MY_PROP: value\n")
(insert ":END:\n")

Error Prevention

Functions called from header-line or mode-line should wrap org-* calls:

;; BAD - will error in non-org buffers
(defun my-header-line ()
  (org-entry-get nil "PROP" t))

;; GOOD - safe in any buffer
(defun my-header-line ()
  (ignore-errors
    (org-entry-get nil "PROP" t)))

CRITICAL: Async/Callback Context Warning

org-entry-get nil
uses CURRENT cursor position!

In async callbacks (

:on-complete
,
run-at-time
, process filters), the cursor may have moved. See
/emacs-async
skill for full patterns.

Quick Fix Pattern for Async

;; When called from async context with a marker:
(defun handle-async-result (session-key result)
  (let ((marker (get-session-marker session-key)))
    (when (marker-buffer marker)
      (with-current-buffer (marker-buffer marker)
        (save-excursion
          (goto-char marker)  ; Position cursor FIRST!
          ;; NOW org-entry-get works correctly
          (org-entry-get nil "PROPERTY" t))))))

Common Bug Pattern

;; BUG: Called from async callback, cursor may be anywhere!
(defun bad-error-handler (error)
  (let ((session-key (my-get-session-from-cursor)))  ; WRONG!
    (recover-session session-key)))

;; FIX: Pass session-key explicitly from the original call
(defun good-error-handler (session-key error)
  (recover-session session-key))