Skip to main content

A portable state-tracking layer for markdown note vaults (Obsidian, Dendron, Foam, and plain markdown folders).

Project description

note-state

A portable "patch" for turning a pile of notes into a pipeline: every note carries an explicit state telling you how far it's traveled from raw capture to integrated, trustworthy knowledge — the same way a ticket in an issue tracker carries a status, or a part on an assembly line carries a stage.

Works with any note application that stores notes as markdown files with YAML frontmatter on local disk — Obsidian, Dendron, Foam, Logseq, plain markdown vaults, even a folder of .md files with no app at all.

Install

pip install note-state

The pipeline

drafting → review → formatting → referencing → integrating → published
                ↘         ↘            ↘             ↘
                          needs_revision  (loops back to whichever
                                           stage flagged the problem)

              any state ──────────────────────────────→ archived
State What happens here Exit condition
Drafting Raw capture. Get the idea down with as little friction as possible. The idea has enough substance to be judged.
Review Read it critically: accurate, internally consistent, complete? Content is verified, or it's sent back to Drafting.
Formatting Give it shape: headings, atomic scope, a real title, clean prose, tags. It reads well and is scoped correctly.
Referencing Attach provenance: citations, source links, backlinks. Every non-obvious claim is traceable to a source.
Integrating Weave it into the graph: link from a Map of Content, cross-link related notes. It's reachable from at least one other place in the vault.
Published Stable and reusable — safe to cite, export, or share. Terminal, but can be pulled back into Integrating.
Needs Revision (utility state) Something's wrong. Flagged from any stage. Always exits back to the stage that flagged it.
Archived (utility state) Retired or superseded. Terminal.

This isn't sacred — it's just the bundled default. Drop your own states.yaml next to your notes (or in any parent directory) to define a different pipeline; note-state doesn't hardcode the states, it just enforces whatever pipeline you describe.

The metadata schema

Every tracked note gets two frontmatter fields: the current state, and a timestamped log of how it got there.

---
title: "Maps of Content connect clusters of related notes"
state: referencing
state_history:
  - state: drafting
    date: 2026-07-01
  - state: review
    date: 2026-07-05
  - state: formatting
    date: 2026-07-08
  - state: referencing
    date: 2026-07-12
    note: "added three sources"
tags: [pkm, moc]
---

Note body goes here as normal — nothing about the state system touches
the content itself.

state_history is what makes the system useful beyond a label: it's an audit trail you can query later ("which notes have been stuck in Review for three weeks?", "how long does formatting usually take?").

Usage

# Stamp every note in a folder with the initial state (only touches
# notes that don't already have one — safe to run repeatedly)
note-state init ./my-vault

# Move a note forward
note-state set my-vault/atomic-notes.md review

# Try to skip a stage — this is rejected unless you pass --force
note-state set my-vault/atomic-notes.md published

# See what's where
note-state list ./my-vault
note-state list ./my-vault --state review

# Find bottlenecks — counts per state + oldest untouched notes
note-state report ./my-vault

# Print the pipeline as a Mermaid diagram (paste into anything that renders it)
note-state graph

Customizing the pipeline

Two files define the state machine:

  • states.yaml — states + allowed transitions. note-state looks for this file (or .note-states.yaml) in the current directory, then any parent directory, and falls back to the bundled default pipeline above if none is found. Copy the bundled default as a starting point and edit freely — rename stages, add a translating or peer-review state, rewire transitions.
  • Pass --config path/to/states.yaml to point at a specific file instead of relying on directory discovery.

Wiring it into a specific app

  • Obsidian, Dendron, Foam, plain markdown folders — these already read and preserve YAML frontmatter, so note-state works with zero adaptation: run it straight against your vault folder. In Obsidian, the Dataview plugin can turn state into a live board, e.g.:

    TABLE state, state_history[-1].date AS "last moved"
    FROM "Notes"
    SORT state
    
  • Logseq — pages are markdown files too, but Logseq's own metadata lives as a key:: value line on the first block rather than a --- frontmatter block. Keep frontmatter and Logseq properties side by side (Logseq ignores the frontmatter block, note-state ignores the :: line), or adapt the parser in note_state/cli.py to read state:: drafting instead.

  • Notion (or any database-backed app without local files) — recreate states.yaml as a Status property with matching options, and use a Board view grouped by it. You lose note-state's enforcement of transition rules unless you script it against the Notion API, but the state vocabulary and pipeline shape carry over directly.

Design notes

  • Backward moves are allowed on purpose. Review can send a note back to Drafting; Formatting can send it back to Review. Knowledge work isn't strictly linear, and a state system that can't represent "this needs another pass" will just get ignored.
  • needs_revision is a trapdoor, not a stage. It exists so a problem found at any point can be flagged without losing the note's place in the pipeline — it always returns to wherever it came from.
  • --force exists deliberately. Rules are useful defaults, not a cage; sometimes you really do want to fast-track or bulk-correct a note.

License

MIT

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

note_state-0.1.0.tar.gz (12.4 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

note_state-0.1.0-py3-none-any.whl (9.9 kB view details)

Uploaded Python 3

File details

Details for the file note_state-0.1.0.tar.gz.

File metadata

  • Download URL: note_state-0.1.0.tar.gz
  • Upload date:
  • Size: 12.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.15

File hashes

Hashes for note_state-0.1.0.tar.gz
Algorithm Hash digest
SHA256 ca53cf9e5dd61430f484ef8eed2a6402ead10466ba4a8d6a56cfbb62561504eb
MD5 9e22224400cb58c307a83214b5e207f4
BLAKE2b-256 06e0474be2d804f51eed4bf27b85a20bd5b55387fdc6f7052e52deb0e2727384

See more details on using hashes here.

File details

Details for the file note_state-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: note_state-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 9.9 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.15

File hashes

Hashes for note_state-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 862c7e8dc274d8954177a589081a22d6ef3acc4bb250c335279c67c458042481
MD5 cc47faa5c2b1d7804b3bc16e4485cd1c
BLAKE2b-256 1b65ec8a8f4a915ab6a412acfc3108f704dd8e2524b3eca8220fee0d80f60dc5

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page