nt

command module
v0.11.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jun 9, 2026 License: MIT Imports: 3 Imported by: 0

README ΒΆ

nt

Tasks and notes as plain text β€” and durable memory your AI agents can't lose.

Agents forget. Your files don't. nt is a terminal-first task & note manager that keeps everything as plain files β€” todo.txt tasks and Markdown notes β€” so your editor, grep, git, and your AI coding agents all read and write the same source of truth. One static binary. No database. No cloud.

CI Release Go Report Card Go version

Quickstart Β· Why nt Β· AI memory Β· The three faces Β· vs. alternatives Β· Docs


Most tools make you choose: a slick app that locks your data in a cloud silo, or a pile of text files with no structure. nt refuses the trade-off. Your tasks live in tasks.txt (the todo.txt format). Your notes live as .md files with YAML frontmatter and [[wikilinks]]. On top of those plain files, nt gives you a fast CLI, a gorgeous terminal UI, an embedded web app, and a first-class memory loop for AI coding sessions β€” without ever changing the files underneath. Point Obsidian at the same folder, grep it, git it, or let Claude read it back next week. It's all just text you own.

πŸš€ Quickstart

# Install the latest release binary β€” no Go, no checkout (β†’ ~/.local/bin)
curl -fsSL https://raw.githubusercontent.com/navbytes/nt/main/install.sh | bash
nt add "fix token refresh race" --pri high --due today --tag auth   # capture a task
nt note "Chose flock over SQLite" --folder decisions                # capture a note
nt                                                                  # open the TUI (just run it)
nt ready                                                            # what should I do next?
nt recall --source claude                                          # read back what an AI captured
nt web                                                              # browse it all in your browser

That's it β€” you're up. nt help lists every command; more install options below.

✨ Why you'll like it

  • πŸ“„ It's just files. todo.txt + Markdown in one folder. Open them in any editor, grep them, git init them. No lock-in, no proprietary database, nothing to export.
  • πŸ€– Built for AI memory. The action items and notes an agent writes today survive as plain text the next agent β€” or the next you β€” reads back tomorrow. (see below)
  • πŸ–₯️ Three UIs, one store. A scriptable CLI, a live terminal UI, and an embedded web app β€” all over the exact same files, always in sync.
  • πŸ“¦ One static binary. Pure Go, no CGo, no system dependencies, no runtime. curl | bash and go. Works fully offline.
  • πŸ”— Wikilinks & backlinks. [[link]] any task or note to any other; "linked from" is computed on demand by scanning files β€” no index to corrupt. Rename a note and every link follows.
  • 🧩 Obsidian-compatible. Notes are plain .md + frontmatter, so you can point an Obsidian vault at the notes/ folder and use it as your GUI while nt owns tasks, the CLI/TUI, and the AI loop.
  • ⛓️ Real task semantics. Full A–Z priorities, due dates (with optional time-of-day), start/defer dates, projects, tags, recurrence, sub-tasks and dependencies (blocks:/parent:) with cycle detection, time estimates + start/stop tracking, and typed provenance (discovered-from).
  • πŸ—“οΈ A planner, not just a list. nt today / nt agenda group your work by date, nt review is a weekly triage (overdue Β· stale Β· undated Β· stuck projects), and daily notes (nt journal) give you a dated log your agents can append to.
  • πŸ”’ Safe by construction. Every write goes through one locking, atomic, ULID-keyed engine with transactional undo/redo β€” so a concurrent nt add from an AI session is never clobbered. Lossless todo.txt round-trip is enforced by test.
  • 🌿 Git-native. nt git-init sets up merge=union so branches don't conflict on every add; nt doctor reconciles after a merge.

🧠 Durable memory for your AI agents

Your AI assistant just created three action items β€” then the session ended and they vanished. Next session it has no idea what it was doing.

nt is the place that memory lives. Because the store is plain text, an agent doesn't need a special database or a running service to remember β€” it just reads and writes files. Three ways to wire it up:

  • PostToolUse hook β€” nt hook mirrors Claude Code's TodoWrite list into your store automatically (idempotent, tagged src:claude). Wire it once in ~/.claude/settings.json.
  • MCP server β€” nt mcp exposes typed tools (nt_ready, nt_add, nt_recall, nt_search, nt_note, …) over stdio. Register it with one command:
    nt mcp install              # add nt to Claude Code / Claude Desktop (absolute path, idempotent)
    
  • The /nt skill + recall loop β€” teach the agent to capture as it works and nt recall prior context when it resumes.
# During a session (the hook does this for you, or call it directly):
nt add "fix token refresh race" --source claude --tag auth
# A week and three sessions later β€” read it straight back:
nt recall --source claude --json

Why plain files beat a vector DB for this: the model reads the real note, not an embedding's best guess (reliability); you open only what's relevant (token cost); and you can git diff and roll back its memory (auditability). It's the Karpathy "LLM wiki" pattern, with tasks and a recall loop on top. Full setup & walkthrough β†’ docs/claude-integration.md.

πŸͺŸ Three faces, one store

Terminal UI β€” just run nt

A Bubble Tea TUI that adapts to your terminal width (compact strip β†’ standard list β†’ wide split with a live detail pane) and live-refreshes via fsnotify when a CLI call or an AI session writes the store. Three tabs β€” tasks, notes, and a Logbook of completed work grouped by date β€” with multi-select bulk ops, search-as-you-type, mouse support, undo/redo, and a read-only lock. A : command palette runs any action by name, vim motions take counts (5j, 12G), notes capture inline (no $EDITOR bounce), and the whole UI follows your terminal's light/dark theme. Press ? for the full keymap.

Notes Logbook
Notes view Logbook view
Web app β€” nt web

A fast single-page app (Svelte + TypeScript) compiled into the binary β€” still one static file, still fully offline, no CDN, no external requests. Browse the folder tree, read Markdown with [[wikilink]] navigation, Mermaid diagrams, and syntax-highlighted code in light/dark Tokyo Night.

It's built for moving fast: a ⌘K command palette to jump anywhere, ranked search with highlighted snippets, a /tasks planner with an agenda view, a /journal of daily notes, a clickable /graph of your links, /tags and /orphans browsers, an activity feed, an in-note table of contents + backlinks, and a mobile-friendly layout you can install as a PWA. Pass --edit for a real CodeMirror editor β€” markdown highlighting, [[-wikilink and /-slash-command autocomplete, live preview, and backlinks while you write β€” to create and edit notes and tasks right in the browser (saves are guarded by a per-process CSRF token and an If-Match check so nothing gets clobbered). Binds 127.0.0.1 only and read-only by default β€” your notes are never on the network.


The /graph view β€” your notes and links as a constellation.
CLI β€” scriptable everything
nt add "write migration" --blocks task:5 --project api   # task:5 hides until this is done
nt ready --json                                          # open, unblocked work by urgency (agent entry point)
nt agenda --days 7                                       # Overdue / Today / Upcoming, grouped
nt add "weekly review" --due monday --recur weekly       # completing spawns the next occurrence
nt search "auth" --tag backend                           # ripgrep + title match, tag-filtered
nt links jwt-expiry                                      # forward links + backlinks for a note
nt log --since 2026-01-01 --json                         # the Logbook, machine-readable
Full command cheatsheet
nt add "title" --pri high --due "fri 5pm" --est 2h --tag t --project p   # capture a task (a = alias)
nt note "title" --folder work --field status=stable         # capture a note (folders + frontmatter)
nt journal                  # open today's daily note (j = alias)
nt                          # TUI            nt list [--status|--tag|--sort urgency|--tree|--all|--json]
nt view <name>              # saved views    nt view save <name> [list flags]   nt view list / rm <name>
nt ready / today / agenda   # what's next    nt done <id|task:N>     nt update <id> --status doing
nt review [--stale N]       # weekly triage  nt start <id> … nt stop <id>   (time tracking β†’ spent:)
nt search <q> [--tag…]      # find           nt tags                 nt tag <note…> +ref -inbox
nt links <id> [--orphans]   # graph          nt recall [--source] [--json]   nt log [--since|--days N]
nt skip <id>                # recurring: next occurrence      nt mv <note> <dest>   (rewrites [[links]])
nt edit <id|task:N>         # safe $EDITOR round-trip        nt rm <note> [--force]   (β†’ .trash/)
nt web [--edit] [--port N]  # browser app (--detach to run in the background; --status / --stop)
nt undo / "redo"   nt mcp [install]   nt hook
nt git-init && nt doctor    # version-control the store + reconcile merges (+ dependency checks)
nt path                     # print $NT_DIR  nt archive   nt --version   nt help
# Optional defaults live in $NT_DIR/config.toml ([defaults]/[web]/[tui]).

πŸ†š How it compares

nt todo.txt CLIs Taskwarrior Obsidian mem0 / MCP memory
Storage you own (plain files) βœ… .txt+.md βœ… .txt βž– own DB βœ… .md ❌ vector DB
Tasks and notes, unified βœ… tasks only tasks only notes only β€”
Agent-readable with no service βœ… (or MCP if you want) βœ… βž– βž– plugin ❌ needs the service
Single static binary, no cloud βœ… varies βœ… ❌ app ❌ service
Works with grep/git/editor βœ… βœ… βž– βœ… ❌
CLI + TUI + web in one βœ… ❌ βž– GUI ❌
Built for AI session memory βœ… ❌ ❌ βž– βœ…

Honest take: if you want a polished cloud app with shared boards and assignees, use Notion or Linear. nt is for people who want their data as text they control.

πŸ—‚οΈ How your stuff is stored

One global store at $NT_DIR (default ~/.local/share/nt):

~/.local/share/nt/
β”œβ”€β”€ tasks.txt     # todo.txt format, one line per task
β”œβ”€β”€ done.txt      # archived completed tasks
β”œβ”€β”€ undo.jsonl    # undo transaction journal
└── notes/*.md    # Markdown notes with YAML frontmatter

A task line is just todo.txt with a few conventions:

(A) fix auth bug +api @backend due:2026-06-05 [[jwt-expiry]] src:claude id:01JZ8RT3

(A)–(Z) priority Β· +project Β· @tag Β· due: (optionally …T17:00) Β· t: start/defer Β· rec: recurrence Β· est:/spent: time Β· src: origin Β· id: ULID Β· [[target]] links to any note or task Β· parent:/blocks: are typed task links. Unknown key:value tokens from other todo.txt tools are preserved byte-for-byte.

Notes ↔ Obsidian (use Obsidian as the GUI, nt as the brain)

nt has no notes GUI of its own β€” and doesn't need one. Notes are plain .md + YAML frontmatter + [[wikilinks]], so you can point an Obsidian vault at the notes/ folder and use Obsidian as the GUI while nt owns tasks, the CLI/TUI, and the AI-memory loop. nt reads back what Obsidian writes: nested subfolders, block-list tags:/aliases:, notes without an H1 (title falls back to the filename), and link variants ([[folder/note]], [[note#heading]], [[note|alias]]) resolved by shortest path-suffix β€” a bare name colliding across folders is flagged ambiguous rather than guessed.

Rename/move is nt-native: nt mv <note> <new> (or r in the TUI) renames the file and rewrites every [[link]] to it across tasks and notes, so links never dangle. It deliberately does not route agents through Obsidian's REST-API MCP (slow, token-heavy, whole-vault exposure) β€” Obsidian stays an optional human GUI, never a dependency in the agent's path.

πŸ›‘οΈ What's guaranteed (the hard parts)

  • Lossless round-trip β€” an unmodified tasks.txt line is re-emitted byte-for-byte, preserving unknown tokens from other todo.txt tools (enforced by test).
  • No lost updates β€” every write locks, re-reads, mutates, and atomically renames through one ULID-keyed engine, so a concurrent AI-session write is never clobbered (concurrency test included).
  • Transactional undo/redo β€” each change journals before-images keyed by ULID; nt undo reverses them and nt's redo re-applies them.
  • Dependency integrity β€” nt doctor detects dependency cycles (so a blocks: deadlock never silently hides tasks) and stale/dangling links, and reconciles duplicate ids after a git merge.

πŸ™… When nt is not for you

  • You want a managed cloud app with shared boards, assignees, and dashboards β†’ Notion / Linear / Things.
  • You never touch a terminal and want zero file management β†’ a GUI-first app will feel better.
  • You need a native mobile app from an app store β†’ nt web is an installable PWA, but it's not a packaged native app.

πŸ“¦ Install

# Curl β€” latest release binary to ~/.local/bin (no Go needed)
curl -fsSL https://raw.githubusercontent.com/navbytes/nt/main/install.sh | bash

# Go β€” install the latest tagged release
go install github.com/navbytes/nt@latest

# From source
git clone https://github.com/navbytes/nt && cd nt && make install

Single static binary for Linux & macOS (amd64/arm64). Releases are automated by GoReleaser on a vX.Y.Z tag (RELEASING.md). Homebrew is planned (brew install navbytes/tap/nt).

Build from source / develop
go build -o nt .       # Go 1.25+
./nt                   # launch the TUI
make test              # run the Go test suite
make web-build         # rebuild the embedded web app (needs Node 22+)
vhs docs/demo.tape     # (optional) render an animated demo β†’ docs/demo.gif

The web app's built bundle is committed and embedded with //go:embed, so go build / go install need no Node toolchain. See SPEC.md for the full design.

🀝 Contributing

Issues and PRs welcome. go test ./... must pass; run make test. The architecture and design rationale live in SPEC.md; AI-integration details in docs/.

License

MIT Β© navbytes

Documentation ΒΆ

Overview ΒΆ

Command nt is a terminal task & note manager that stores data as plain files (todo.txt tasks + markdown notes) so editors, grep, git, and AI agents can read and write it directly. See SPEC.md for the design.

Directories ΒΆ

Path Synopsis
internal
aisync
Package aisync mirrors a Claude Code session's TodoWrite list into the nt store (SPEC Β§8, Β§10).
Package aisync mirrors a Claude Code session's TodoWrite list into the nt store (SPEC Β§8, Β§10).
cli
Package cli implements nt's command-line interface.
Package cli implements nt's command-line interface.
config
Package config loads nt's optional config file, $NT_DIR/config.toml.
Package config loads nt's optional config file, $NT_DIR/config.toml.
dateparse
Package dateparse parses the human date and priority inputs nt accepts on the CLI and in the TUI (SPEC Β§7.3), kept in one place so both surfaces agree.
Package dateparse parses the human date and priority inputs nt accepts on the CLI and in the TUI (SPEC Β§7.3), kept in one place so both surfaces agree.
links
Package links implements the unified cross-item linking model (SPEC Β§5.1): a single [[target]] syntax that resolves to a note (by slug, title, or id) or a task (by ULID / short prefix), plus backlinks computed on demand by scanning files β€” no stored index.
Package links implements the unified cross-item linking model (SPEC Β§5.1): a single [[target]] syntax that resolves to a note (by slug, title, or id) or a task (by ULID / short prefix), plus backlinks computed on demand by scanning files β€” no stored index.
lock
Package lock provides an advisory file lock around the critical section that mutates tasks.txt (SPEC Β§6.4).
Package lock provides an advisory file lock around the critical section that mutates tasks.txt (SPEC Β§6.4).
mcp
Package mcp serves nt over the Model Context Protocol (stdio, JSON-RPC 2.0), so an agent uses typed tools (nt_ready, nt_add, …) instead of constructing CLI shell strings.
Package mcp serves nt over the Model Context Protocol (stdio, JSON-RPC 2.0), so an agent uses typed tools (nt_ready, nt_add, …) instead of constructing CLI shell strings.
mutate
Package mutate is the single ULID-keyed mutation engine shared by the CLI and (later) the TUI, implementing the write contract from SPEC Β§6.1–6.3.
Package mutate is the single ULID-keyed mutation engine shared by the CLI and (later) the TUI, implementing the write contract from SPEC Β§6.1–6.3.
note
Package note implements nt's markdown notes with light YAML frontmatter (SPEC Β§5).
Package note implements nt's markdown notes with light YAML frontmatter (SPEC Β§5).
quickadd
Package quickadd normalizes the natural-language conventions people type into a task's text β€” across the CLI, TUI, web, and MCP add paths β€” so they all behave identically.
Package quickadd normalizes the natural-language conventions people type into a task's text β€” across the CLI, TUI, web, and MCP add paths β€” so they all behave identically.
search
Package search implements files-only search (SPEC Β§7.1): ripgrep when a real rg binary is on PATH, otherwise a built-in walker.
Package search implements files-only search (SPEC Β§7.1): ripgrep when a real rg binary is on PATH, otherwise a built-in walker.
store
Package store resolves the nt data directory ($NT_DIR) and the paths of the files within it.
Package store resolves the nt data directory ($NT_DIR) and the paths of the files within it.
task
Package task implements nt's todo.txt task model with the lossless round-trip guarantee from SPEC Β§4: a file is parsed into an ordered list of nodes (each a parsed task or a preserved raw line), and an unmodified line is re-emitted byte-for-byte.
Package task implements nt's todo.txt task model with the lossless round-trip guarantee from SPEC Β§4: a file is parsed into an ordered list of nodes (each a parsed task or a preserved raw line), and an unmodified line is re-emitted byte-for-byte.
tui
Package tui implements nt's terminal UI (SPEC Β§12) with Bubble Tea.
Package tui implements nt's terminal UI (SPEC Β§12) with Bubble Tea.
ulid
Package ulid generates ULIDs (Universally Unique Lexicographically Sortable IDs) with zero external dependencies.
Package ulid generates ULIDs (Universally Unique Lexicographically Sortable IDs) with zero external dependencies.
undo
Package undo implements the append-only transaction journal from SPEC Β§6.3.
Package undo implements the append-only transaction journal from SPEC Β§6.3.
view
Package view persists named "smart views" β€” saved bundles of the `nt list` filter so a user can capture a query once and recall it by name (T4).
Package view persists named "smart views" β€” saved bundles of the `nt list` filter so a user can capture a query once and recall it by name (T4).
web
Package web is the HTTP adapter: a localhost notes viewer (`nt web`).
Package web is the HTTP adapter: a localhost notes viewer (`nt web`).
web/apitypes
Package apitypes defines the JSON wire contract for the web SPA's /api/* endpoints.
Package apitypes defines the JSON wire contract for the web SPA's /api/* endpoints.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL