ctanas/tiles: Tagged Instant Lightweight Emacs Snippets (TILES)


TILES is an Emacs package for taking quick, title-less notes.

Each note (or tile, if you will) is a single paragraph stored in its own org file, organized through tags and bold keywords rather than hierarchies. TILES tries to keep it simple: there are no dependencies (except for Emacs, version 27.1 at least), no links between notes (except the Org Mode syntax), no backlinks, no graphs, no database; every note is a paragraph in its own text file.

I created this package because I wanted a note taking system with the following features:

  • focus on one paragraph (like Logseq): one paragraph = one note;
  • offers a bird’s-eye view (quick preview) of recent notes (similar to Howm);
  • quick note preview, quick note edit;
  • color coding depending on the note’s age (sort of like Howm, but not really);
  • title-less, to reduce friction (why having to stop the thought process to create a title that’s never used afterwards?);
  • can use the Dynamic Block features in Org Mode (like Denote and Denote Org, ideal if you want to use your notes to create other documents;
  • can stitch notes together, after applying a search filter (like Howm, ideal if you want to use your notes to create other documents;
  • uses tags for hierarchy but also uses bold keywords (extracted automatically from words that are marked as bold);
  • can have follow-up text inside a note (and undertile, if you will), a kind of a meta-content, a private content inside a note, a paragraph prefixed with ‘&&’ hidden everywhere (not exported with Dynamic Blocks actions) except expanded view in the dashboard and, of course, in note editing buffer;
  • search after tags and/or keywords only (who really wants to search for anything else?);
  • no external dependencies needed except at least version 27.1 of Emacs and Org Mode (built-in);
  • uses Org Mode format for bold, italic, links, in-line footnotes;

Screenshot 2026-02-07 at 14 07 08
Screenshot 2026-02-07 at 14 07 29
Screenshot 2026-02-07 at 14 08 18

Each note is a file named TYYYYMMDDHHMMSS.org (T followed by a timestamp up to seconds) and stored in a predefined folder:

The Mars Sample Return (*MSR*) mission involved
a collaboration between *NASA* and *ESA* to 
retrieve samples collected by the *Perseverance* 
rover[fn:: Launched in July 2020].

space/mars
  • Content: paragraph(s) with full org-mode formatting (*bold*, /italic/, [[links]], inline footnotes);
  • Optional private paragraphs prefixed with && (see Private paragraphs below);
  • Blank line separator after the content;
  • Last non-empty line: tags separated by / (always parsed as the tag line); tags are mandatory;
  • Bold words (*word*) double as searchable keywords (optional);
  • Multi-paragraph notes are supported but discouraged; the parser always takes the last non-empty line as tags.

Clone the repository and add to your load path:

(add-to-list 'load-path "/path/to/tiles")
(require 'tiles)

Set your notes directory (default ~/notes/tiles/):

(setq tiles-directory "~/notes/tiles/")

All commands are under the C-c m prefix:

Key Command Description
C-c m m tiles-show-notes Open dashboard
C-c m n tiles-new Create a new note (buffer)
C-c m q tiles-quick Quick capture via minibuffer
C-c m y tiles-yank Quick capture from clipboard
C-c m t tiles-tag-search Search by tags
C-c m k tiles-keyword-search Search by keywords

C-c m m launches the dashboard, which displays a chronological list of all notes. Each entry shows color-coded timestamps (showing hours and minutes to save space), inline previews, tags, and keywords. Timestamps are color-coded: green for today, darker green for recent (

  *T*agged *I*nstant *L*ightweight *E*macs *S*nippet (TILES) | 42 notes | loaded in 0.023s
  SPC:preview  RET:open  d:change date  t:filter tag  k:filter keyword  c:clear filter  g:refresh  q:quit
  ========================================================================

  2026-02-06 08:12  Hello world, I'm the first tile!  meta/test
  2026-02-06 08:12  This note is ready for production  meta/prod

Dashboard keybindings:

Key Action
n/p Navigate notes
SPC Open editable preview split (follows cursor)
RET Open note file
TAB Toggle expanded view (private &&, keywords, stats)
M-up Move selected note up
M-down Move selected note down
d Change note date/timestamp (renames file)
D Delete note (with confirmation)
t Filter displayed notes by tag
k Filter displayed notes by keyword
c Clear filter
f Toggle raw preview (strip org formatting)
+ Load next batch of notes
0 Stitch displayed notes into flowing view
l New note (same as C-c m n)
g Refresh
q Quit

Tag queries use / for AND and SPC for OR:

Query Meaning
b218/lx2026 Notes with both b218 and lx2026
b218 misc Notes with either b218 or misc
b218/lx2026 misc (b218 AND lx2026) OR misc

This syntax applies everywhere: tiles-tag-search, dashboard filter (t), and dynamic block :tags parameter.

Keyword queries use SPC-separated terms with OR logic — any matching term is enough:

Query Meaning
emacs Notes with emacs as a bold keyword
emacs lisp Notes with either emacs or lisp

Keywords are the *bold* words extracted from note content. This syntax applies to tiles-keyword-search, dashboard filter (k), and dynamic block :keywords parameter.

Tag and keyword searches (C-c m t / C-c m k) open a two-panel view: results list on top, live preview below.

Key Action
n/p Navigate results
RET Open note file
SPC Toggle to stitched view
r Refine search (new query)
t/k Switch to tag/keyword search
q Quit

Press SPC from the search view to enter the stitched view: all matching notes concatenated into a single flowing org buffer, stripped of tag lines and private (&&) paragraphs, in inverse chronological order. This is useful for reading related notes as continuous prose or if you want to include multiple related notes into another document, like a newsletter.

Key Action
n/p Jump between note boundaries
RET/e Open the source file at point
SPC Toggle back to two-panel view
r Refine search
q Quit

C-c m n opens a capture buffer. Write your paragraph, add a blank line, then your tags. Press C-c C-c to save, C-c C-k to cancel. While keywords are not mandatory, tags are, so if the user forgets to add tags, it will be asked to do so.

For faster capture, C-c m q prompts for content and tags directly in the minibuffer. C-c m y does the same but pre-fills the content from the clipboard (kill ring), which you can edit before confirming.

Any paragraph in a note that starts with && is treated as private. Private paragraphs are hidden from dashboard previews, stitched views, search panels, and dynamic blocks. They are only visible in two places: when expanding a note with TAB in the dashboard, and when editing the file directly.

This is useful for keeping personal annotations, reminders, or context that you don’t want surfacing in exports or shared views.

The Mars Sample Return (*MSR*) mission involved
a collaboration between *NASA* and *ESA*.

&& Personal note: double-check the timeline
with the ESA press release from January.

space/mars

In the example above, the && paragraph will not appear in previews or stitched output, but pressing TAB on this note in the dashboard will reveal it in the expanded area.

Updating a note’s timestamp

While editing a note, M-x tiles-touch updates the file’s timestamp to the current time and renames the file accordingly. Asks for confirmation before proceeding. Useful for bumping a note to the top of the chronological list after editing.

TILES provides two dynamic block types for embedding note data in org files:

tiles-notes – Insert a linked list of matching notes:

#+BEGIN: tiles-notes :tags "space mars" :sort "newest" :limit 10
- [[file:~/notes/tiles/T20260206081250.org][2026-02-06 08:12:50]] The Mars Sample Return...  space/mars
- [[file:~/notes/tiles/T20260206081227.org][2026-02-06 08:12:27]] NASA announced today...  space/nasa
#+END:

tiles-files – Embed note contents directly:

#+BEGIN: tiles-files :tags "journal" :keywords "review" :separator "\n-----\n"
First matching note content...

-----
Second matching note content...
#+END:

Parameters (all optional):

Parameter Description Default
:tags Space-separated tags (OR logic)
:keywords Space-separated keywords (OR logic)
:sort "newest" or "oldest" "newest"
:limit Maximum number of notes unlimited
:separator String between notes (tiles-files only) blank line

  • C-c C-x x to insert a dynamic block from a menu
  • C-c C-x C-u to update the block under cursor

TILES uses an in-memory cache that stores parsed note data keyed by filepath. Files are only re-read from disk when their modification time changes. The first load reads all files; subsequent operations are fast. Use M-x tiles-clear-cache to force a full reload.

All settings are available via M-x customize-group RET tiles.

Variable Description Default
tiles-directory Root directory for notes (recursive) ~/notes/tiles/
tiles-preview-length Max characters for inline preview 105
tiles-line-padding Extra padding beyond preview and tags 22
tiles-preview-raw Strip all org formatting from previews t
tiles-dashboard-limit Max notes per page (nil = unlimited) 50

Example configuration:

(setq tiles-directory "~/Documents/tiles/")
(setq tiles-preview-length 120)

All faces can be customized via M-x customize-face or in your config:

Face Description Default
tiles-timestamp-today Today’s timestamps #228b22
tiles-timestamp-recent Recent timestamps ( #3a5a2a
tiles-timestamp-old Older timestamps (> 2 weeks) #999999
tiles-tags Tag display #a00000
tiles-keywords Keyword display in expanded view #006600
tiles-notes-hl-line Selection highlight #FFC700
tiles-notes-expanded Background of expanded lines #FFF8DC

Example:

(set-face-attribute 'tiles-timestamp-today nil :foreground "#008800")
(set-face-attribute 'tiles-notes-hl-line nil :background "#FFD700")
  • 0.3 — Private paragraphs: paragraphs starting with && are hidden from dashboard previews, stitched views, search panels, and dynamic blocks. Only visible via TAB expansion in the dashboard or direct file editing.
  • 0.2 — Initial public release.

Many thanks to Protesilaos Stavrou for Denote and Denote Org, Kazuyuki Hiraoka for Howm, Andrei Sukhovskii for Howm Manual, Jethro Kuan for Org-roam, Jason Blevins for Deft, Zachary Schneirov for Notational Velocity, and to all the developers of Logseq and Obsidian for their inspiration into creating this package.

This package was developed with the assistance of Claude, an AI assistant created by Anthropic.

GNU GPLv3



Source link

Leave a Reply

Your email address will not be published. Required fields are marked *