Skip to main content

Hanger logo

Hanger

Local Markdown document automation with durable workflows
한국어 | English
Quick start · How it works · Using it from AI tools

Quick start

You need macOS or Linux, Python 3.12 or later, uv, and a signed-in Claude Code (claude) or Codex (codex). Hanger uses no API keys; it runs models through the subscription you already have.

uv tool install hanger
hanger setup
claude mcp add --scope user hanger -- hanger serve
hanger closet add ~/notes

hanger setup asks no questions. It finds a model provider (Claude Code if present, otherwise Codex) and downloads and installs the search engine (Elasticsearch with the Korean analyzer). When no provider is found, setup stops and says why. You can register your notes folder in the terminal, as on the last line, or let your AI tool ask you for it on first use.

To connect Codex, use codex mcp add hanger -- hanger serve. To install the latest unreleased code, use uv tool install git+https://github.com/woonyong-choi/hanger.

To update:

uv tool upgrade hanger
hanger setup

Why

As Markdown notes pile up, the same topic ends up in several notes, and an AI tool asked to tidy them may change things without evidence or touch folders it should leave alone. Hanger sits between your AI tools and your notes folder and handles search, change planning, review and writing. It changes only passages of notes it has read, follows the rule files (HANGER.md) and ignore file (.hangerignore) you set, and stops instead of overwriting when a note changed in the meantime.

If you keep a handful of notes in one folder and editing them yourself is quicker, an editor is enough.

How it works

  1. Register a closet: a notes folder Hanger keeps is called a closet. You can register several. A folder inside, or containing, a registered closet is refused as a duplicate. Registering creates a default .hangerignore and HANGER.md at the root only when they are missing.
  2. Index: a background service watches for file changes and keeps the search index current. Files matched by .hangerignore (.gitignore syntax) and HANGER.md files are not indexed. The default file holds only syntax notes and no patterns, so at first every Markdown note is indexed.
  3. Keyword tree: alongside indexing, each note gets a concept name, other names, a definition and broader, related and prerequisite concepts, forming a tree per closet. See "Keyword tree" below.
  4. Request: an AI tool searches, or asks to write, edit or organize. Change requests are queued and the service works through them.
  5. Draft and review: the model gets the related notes together with the HANGER.md rules for their folders and drafts a change; a separate call reviews it. A rejected draft is written again with the reasons.
  6. Write: files change only after Hanger confirms the source is unchanged. Folders with write: false and ignored files are never changed.

Rule files, HANGER.md: one can sit in any folder and applies to that folder and below. For settings between the top --- lines, the nearest file wins; the written rules all reach the model, from the root down to the nearest folder. The file has its own name so it does not mix with other AI tools' rule files (AGENTS.md, CLAUDE.md and so on).

Setting Default Meaning
write true false keeps Hanger from creating, changing or deleting notes here
tree empty (one tree for the closet) Keyword tree name. Folders with different names never link concepts
keywords true false keeps notes here out of the keyword tree (they are still indexed and searched)
merge empty auto queues a merge when two notes answer the same central question
---
write: false
---

Notes in this folder are final. Quote them; do not change them.

Keyword tree: one note is one concept. Broader concepts the user wrote come first: a parent in the front matter (a slug, file name or link), and index notes whose list lines start with a link (that note is the parent of the notes it lists). Where the user wrote nothing, the model reads the note with its 20 nearest notes and proposes a concept name, other names, a definition and broader, related and prerequisite concepts; the program checks and stores them.

  • A broader concept must be in the same tree and cannot form a cycle.
  • A new broader name joins a note or concept of the same name; otherwise it becomes a concept when a second note proposes it, and goes back to waiting if it drops to one child.
  • A concept with more than 15 direct children is split into narrower groups by the model.
  • When a note is deleted, its children move up a level and are placed again.
  • Notes that answer the same central question are reported, and when both folders set merge: auto a merge job is queued. Merges are reviewed like any other change.
  • Concept names and other names add lightly to search, so a note is found by names its text never uses. Search results and drafts carry each note's place in the tree.

The tree is built in the background, one note at a time, while no user request waits. hanger keywords and list_closets show progress.

The user approves ignore-rule changes: editing the patterns in .hangerignore or deleting the file does not take effect at once; it is recorded as a decision. An edit that only changes comments cannot affect the index and applies at once. While a decision is pending, Hanger refuses every search and change request and asks for the answer first. If a closet's folder is missing or empty (an unplugged drive, say), its decision is withdrawn and asked again when the folder is back. File watching and index updates keep running. Hanger asks because a note taken out of the index may not get the same keywords and links when it is indexed again. For a deleted file, approving recreates the default file and declining restores the previous one.

Using it from AI tools

Connected as an MCP server, Hanger offers these tools. Its messages and questions are in English, and it tells AI tools to translate them into the user's language.

Tool What it does
list_closets Shows registered closets and pending decisions; with none, says to ask for a folder
register_closet Registers a closet by absolute path
remove_closet Always refuses and gives the terminal command for the user to run
list_decisions, decide Shows pending decisions and applies the user's answer
search_documents, read_document Search and read; each result shows its place in the keyword tree
keyword_tree The top of each tree, or one concept's names, definition, place, broader, narrower, related and prerequisite concepts
issue_key, request_change, collect Write, edit and organize requests; keep a file or text unchanged in inbox/
job_status, cancel_job, resolve_conflict Check progress, cancel, reconsider a job stopped by a changed note

With more than one closet, each request passes closet as an id or a path inside the closet. Usage guidance for AI tools is in skills/hanger/SKILL.md.

Terminal commands

Command What it does
hanger setup [--reinstall] Checks the model provider and installs the search engine
hanger provider Shows the CLI and model for each role (draft, review)
hanger closet add <folder> / list / remove <id|path> [--yes] Adds, lists and removes closets. Removing keeps the notes and rule files and deletes only the index and job history
hanger ignore show / add <pattern> / remove <pattern> [--closet] [--yes] Shows and changes ignore rules, showing how many notes change and asking to confirm
hanger decisions / hanger decide <id> approve|decline Lists and answers pending decisions
hanger config list / get <key> / set <key> <value> / unset <key> Lists, changes and resets settings
hanger search <query> [--closet] [--folder] Searches from the terminal
hanger keywords [concept] [--closet] Keyword tree progress and top, or one concept (a note path or name)
hanger stop Stops the background service; it starts again on the next request

Main settings:

Key Default Meaning
model.provider automatic claude or codex. Empty picks an installed one, Claude Code first
model.name automatic Empty uses haiku for Claude Code and gpt-6-luna for Codex
model.effort CLI default low, medium or high
models.draft.*, models.review.*, models.keywords.* model.* Separate values for the draft, review and keyword tree roles; empty values follow model.*
search.candidates 20 Number of search candidates
service.idle_minutes 30 How long the service waits without requests before it exits
elasticsearch.port 19200 Port of the search engine Hanger runs

Settings, the closet list, applied ignore rules and decisions are stored in ~/.local/share/hanger/state/hanger.db. Setting changes apply when the service restarts (hanger stop).

Status

Several closets, ignore rules with approval, per-folder rule files, search, the keyword tree, write/edit/organize requests with review, and subscription CLIs (Claude Code, Codex) are supported. Before 1.0, formats and commands may change without notice.

Development

uv sync
HANGER_TEST_SEARCH_URL=http://127.0.0.1:19200 uv run pytest
uv run ruff check src tests
uv run ruff format --check src tests
uv run mypy src

Tests that need search use the Elasticsearch (with the Nori analyzer) given in HANGER_TEST_SEARCH_URL and are skipped without it.

Metadata

Release files for hanger 0.2.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for hanger 0.2.0
File Size Uploaded Provenance
hanger-0.2.0.tar.gz 151.5 kB With provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for hanger 0.2.0
File Interpreter ABI Platform
hanger-0.2.0-py3-none-any.whl Python 3 none any Details

Total release size: 273.4 kB

Release files / hanger-0.2.0.tar.gz

Download URL hanger-0.2.0.tar.gz
Size 151.5 kB
Tags Source
SHA-256 checksum
How to use checksums
5806019640ec9e94a2238ea1cc239af3d1c1c87ce15138b7759c97d19439bfa2
BLAKE2b-256 checksum
How to use checksums
a3e94ee5be1949be1f824f211a57be5a91333cd27ede371c6ac93b4df318bacb
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 17, 2026.

Transparency log

Release files / hanger-0.2.0-py3-none-any.whl

Download URL hanger-0.2.0-py3-none-any.whl
Size 121.9 kB
Tags Python 3
SHA-256 checksum
How to use checksums
d6323fa76354c34176ce9d0569c387ea7907b9679e37cd3e2829340deb4147a4
BLAKE2b-256 checksum
How to use checksums
acaed42de5c53704307492e8b85b691ca1f196720d2c97dd3b2387d73cd2cb6a
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 17, 2026.

Transparency log

Security for hanger 0.2.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

Full provenance

All 2 files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for hanger-0.2.0.tar.gz

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 17, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

Release history Release notifications | RSS feed

This release

0.2.0 This release

2 release files Full provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page