File format & storage
Every note is a Markdown file with a YAML-style frontmatter block, sitting in a folder in your repo. No database, no proprietary container, nothing you need DevNotes+ to read.
Folder layout
your-project/
.devnotes/
.gitignore # ignores everything by default
tags.json # tag definitions (committed, shared with the team)
templates.json # your custom note templates
assets/ # images pasted or dragged into notes
<id>.md # one file per note
The folder is created at the workspace root the first time you make a note, and each note is a separate file named after its ID. Nothing is stored outside the project, and nothing is sent anywhere.
A note file
---
id: n-k3f9a2
title: Why the 60s retry floor
tags: reference
starred: true
createdAt: 1756166400000
updatedAt: 1756252800000
shared: true
branch: fix/rate-limit-copy
owner: Hiba Chaabnia
codeLink_file: src/github/client.js
codeLink_line: 60
codeLink_lineContent: const RETRY_FLOOR_MS = 60_000;
---
Retrying at the exact `x-ratelimit-reset` timestamp still 403'd on
4 of 50 runs — GitHub rounds the header down to the second.
Everything below the closing --- is the note body, in ordinary Markdown. Everything above it is metadata.
Frontmatter fields
Only the first six are always present. The rest appear when the corresponding feature is used, and are simply absent otherwise.
| Field | Type | Meaning |
|---|---|---|
id | string | Note ID. Matches the filename. Required — a file without one is skipped. |
title | string | Note title. |
tags | string | Comma-separated tag IDs, e.g. bug,todo. |
starred | boolean | Whether the note is starred. |
createdAt | number | Unix timestamp in milliseconds. |
updatedAt | number | Unix timestamp in milliseconds. |
shared | boolean | Present and true when the note is un-ignored in .devnotes/.gitignore. |
branch | string | Git branch this note is scoped to. Absent means visible on every branch. |
owner | string | Git user name of whoever created the note. |
archived | boolean | Present and true when archived. |
remindAt | number | Unix timestamp in milliseconds for the reminder. |
linked_notes | string | Comma-separated IDs of related notes. |
codeLink_file | string | Workspace-relative path of the linked file. |
codeLink_line | number | 1-based line number. |
codeLink_lineContent | string | The text of that line when the link was made, used to recover the anchor when code moves. |
github_url | string | Linked issue or PR URL. |
github_repo | string | owner/repo. |
github_number | number | Issue or PR number. |
github_type | string | issue or pr. |
github_status | string | open, closed or merged. |
github_title | string | Title of the linked issue or PR. |
Frontmatter rules
The parser handles a deliberately small subset of YAML, so that reading a note never depends on a YAML library and never fails in a surprising way:
- One
key: valuepair per line. Multi-line values are not supported. - Newlines inside a value are collapsed to a single space when written, so a pasted multi-line title can never break the closing delimiter.
- The closing
---must be on its own line. A---inside a value is safe. trueandfalsebecome booleans. Values that are unambiguously integers become numbers; anything with a leading zero stays a string, so a branch named007is not silently turned into the number 7.
Images
Images pasted or dragged into the editor are written to .devnotes/assets/ and referenced from the note with a normal Markdown image link:

When you share a note, DevNotes+ scans its body for these references and un-ignores the matching asset files, so images travel with the note through git.
Editing notes by hand
You can. The files are yours, and DevNotes+ watches the folder — edit a note in another editor, or pull a teammate's change, and the sidebar picks it up without a reload.
Two things to preserve if you do: keep the id matching the filename, and keep the frontmatter block intact. A file missing its id is skipped with a warning rather than shown as a broken note.
If a note contains git conflict markers, resolve it through the conflict panel rather than by hand where you can — see sharing with your team. DevNotes+ detects the markers and will treat the file as conflicted until they are gone.
Why plain files
The format is the feature. Because notes are Markdown in your repo:
- They are readable anywhere — any Markdown editor,
cat, GitHub's file view. Uninstalling DevNotes+ does not take your notes with it. - They are diffable. A shared note shows up in
git diffand in pull request reviews like source code, because it is a text file like source code. - They are backed up wherever your repository is, with no separate sync to think about.
- They are greppable, by you and by any tool you point at the folder — which is also how the MCP server reads them.