Skip to main content

Async conflict-aware spec/planning, for me, you and your LLM/agent

Project description

Niwa 庭

Async conflict-aware spec/planning, for me, you and your LLM/agent

pip install niwa
# or
uv pip install niwa

Niwa (庭, "garden") is a CLI tool that enables multiple LLM agents to collaboratively edit markdown documents with automatic conflict detection and resolution. Like a zen garden where gravel is raked into patterns, Niwa helps agents weave their edits together harmoniously.

Built on LMDB for high-performance concurrent access, with full GitHub Flavored Markdown support via markdown-it-py.

Features

  • Concurrent Editing: Multiple agents can read/edit simultaneously
  • Conflict Detection: Automatic version tracking detects when agents edit the same section
  • Smart Merging: Auto-merge suggestions for compatible changes, detailed diffs for conflicts
  • Sub-Agent Support: Stored conflicts survive context switches, status commands for fresh context
  • Version History: Full audit trail with rollback capability
  • Search: Find content by keyword when you don't know the node ID
  • Full Markdown Support: GFM tables, task lists, footnotes, frontmatter, and more
  • LLM-Friendly: Comprehensive error messages with usage guides
  • Claude Code Integration: Hooks to inject usage context on session start and compaction

Installation

# From PyPI
pip install niwa

# Or from source
git clone https://github.com/secemp9/niwa
cd niwa
pip install .

# For development (editable install)
pip install -e ".[dev]"

Dependencies

Niwa automatically installs:

  • lmdb - Lightning Memory-Mapped Database for storage
  • markdown-it-py - CommonMark-compliant markdown parser
  • mdit-py-plugins - Frontmatter, footnotes, definition lists, task lists
  • linkify-it-py - Automatic URL detection

Markdown Support

Niwa uses markdown-it-py with the GFM-like preset for robust markdown parsing. Unlike regex-based parsers, this properly handles:

Feature Support
ATX Headings (# H1) Full
Setext Headings (underline) Full
Fenced Code Blocks Full (with language hints)
Indented Code Blocks Full
GFM Tables Full (with alignment)
Task Lists (- [ ]) Full
Strikethrough (~~text~~) Full
Autolinks Full
Footnotes ([^1]) Full
Definition Lists Full
YAML/TOML Frontmatter Full
HTML Blocks Preserved
Nested Lists/Quotes Full

Key benefit: # characters inside code blocks, HTML comments, or inline code are correctly ignored - they won't be mistaken for headings.

Quick Start

# 1. Initialize database
niwa init

# 2. Load a markdown file
niwa load document.md

# 3. View structure
niwa tree

# 4. Read a section (as an agent)
niwa read h2_3 --agent claude_1

# 5. Edit
niwa edit h2_3 "New content" --agent claude_1 --summary "Updated section"

# 6. Export back to markdown
niwa export > updated.md

Commands

Setup

Command Description
init Initialize a new database
load <file> Load markdown file into database
check Verify database health
setup claude Set up Claude Code hooks integration
setup claude --remove Remove Claude Code hooks

Browse

Command Description
tree Show document structure with node IDs
peek <id> Quick view (doesn't track read version)
search <query> Find content by keyword

Edit

Command Description
read <id> --agent <name> Read for editing (tracks version)
edit <id> <content> --agent <name> Edit a node
resolve <id> <resolution> --agent <name> Resolve a conflict
title <id> <title> Update node title
summarize <id> <summary> Add summary to node

Agent Status

Command Description
status --agent <name> Check pending reads, conflicts, recent edits
conflicts --agent <name> List unresolved conflicts
agents List all agents who've used this DB
whoami Get suggested unique agent name

History & Undo

Command Description
history <id> View version history
rollback <id> <version> --agent <name> Restore to previous version
dry-run <id> <content> --agent <name> Preview edit without applying
cleanup Remove stale pending reads/conflicts

Output

Command Description
export Export database to markdown
help Show full usage guide

Multi-Agent Workflow

Agent A: reads section (v1)          Agent B: reads section (v1)
    │                                     │
    ▼                                     ▼
Agent A: edits                       Agent B: edits
    │                                     │
    ▼                                     ▼
SUCCESS (v1→v2)                      CONFLICT! (expected v1, found v2)
                                          │
                                          ▼
                                     Agent B resolves with MANUAL_MERGE
                                          │
                                          ▼
                                     SUCCESS (v2→v3) - both changes preserved!

Conflict Resolution

When a conflict is detected, you get 4 options:

# Use your version (discard theirs)
niwa resolve h2_3 ACCEPT_YOURS --agent me

# Use their version (discard yours)
niwa resolve h2_3 ACCEPT_THEIRS --agent me

# Use auto-merge suggestion
niwa resolve h2_3 ACCEPT_AUTO_MERGE --agent me

# Manual merge (recommended!)
niwa resolve h2_3 MANUAL_MERGE "merged content" --agent me
niwa resolve h2_3 MANUAL_MERGE --file merged.md --agent me

Complex Content

For content with quotes, newlines, or special characters, use --file or --stdin:

# Edit from file
niwa edit h2_3 --file content.txt --agent me

# Edit from stdin
cat content.md | niwa edit h2_3 --stdin --agent me

# Resolve from file
niwa resolve h2_3 MANUAL_MERGE --file merged.md --agent me

Sub-Agents / Fresh Context

If you're a sub-agent or have fresh context, run these first:

# Get a unique agent name
niwa whoami

# Check your state
niwa status --agent <your_name>

# Check for pending conflicts
niwa conflicts --agent <your_name>

Key rules:

  • Use a unique agent name (check with agents command)
  • Use the same name for all your reads/edits
  • Conflicts are stored and survive context switches

Node IDs

Nodes follow the pattern h{level}_{index}:

[root] v1 "Document"
  [h1_0] v1 "Main Title"
    [h2_1] v3 "Section 1" (by agent_A)     ← node_id is "h2_1"
    [h2_2] v1 "Section 2"
      [h3_3] v2 "Subsection" (by agent_B)  ← node_id is "h3_3"

Use tree to find node IDs, or search to find by content.

Examples

Basic editing workflow

niwa init
niwa load README.md
niwa tree
niwa read h2_1 --agent editor
niwa edit h2_1 "# Updated Heading\n\nNew content here." \
    --agent editor --summary "Rewrote introduction"
niwa export > README_updated.md

Handling a conflict

# You tried to edit but got a conflict
niwa edit h2_3 "My changes" --agent me
# Output: CONFLICT DETECTED!

# View the diff, then resolve
niwa resolve h2_3 MANUAL_MERGE \
    "Combined content from both versions" --agent me

Finding and editing content

# Don't know the node ID? Search for it
niwa search "authentication"
# Output: [h2_5] "Authentication" - 3 matches

# Read and edit
niwa read h2_5 --agent me
niwa edit h2_5 --file auth_rewrite.md --agent me

Rollback a bad edit

# Check history
niwa history h2_3
# Output: v3, v2, v1...

# Rollback to v2
niwa rollback h2_3 2 --agent me

Claude Code Integration

Niwa integrates with Claude Code via hooks for automatic context awareness:

# Set up Claude Code hooks
niwa setup claude

# Remove hooks later
niwa setup claude --remove

What the hooks do

Hook Trigger Action
SessionStart Session begins Injects full Niwa usage guide + current status
PreCompact Before /compact Preserves Niwa context so Claude remembers after compaction
PreToolUse Before Write/Edit Warns if there are unresolved conflicts
PostToolUse After Write/Edit Hints to sync markdown changes to database
Stop Session ending Reminds about unresolved conflicts

The SessionStart and PreCompact hooks ensure Claude always knows how to use Niwa, even after context compaction.

How it works

  1. Run setup claude in your project directory
  2. Creates .claude/settings.json with hook configuration
  3. Hooks automatically call niwa hook --hook-event <event>
  4. Claude receives context about your markdown database state

Example workflow with Claude Code

# 1. Initialize and set up hooks
niwa init
niwa load design_doc.md
niwa setup claude

# 2. Start Claude Code session
# Claude will see: "[Niwa Status] Database active with 15 nodes..."

# 3. When Claude edits markdown files
# Claude will see: "[Niwa] Markdown file modified... Consider syncing"

# 4. If conflicts exist when stopping
# Claude will see: "[Niwa Reminder] There are 2 unresolved conflict(s)..."

Architecture

┌─────────────────────────────────────────────────────────────┐
│                        Niwa CLI                             │
├─────────────────────────────────────────────────────────────┤
│  Markdown Parser (markdown-it-py)                           │
│  ├── GFM-like preset (tables, strikethrough, autolinks)     │
│  ├── front_matter_plugin (YAML/TOML)                        │
│  ├── footnote_plugin                                        │
│  ├── deflist_plugin                                         │
│  └── tasklists_plugin                                       │
├─────────────────────────────────────────────────────────────┤
│  Document Model                                             │
│  ├── Nodes (headings → content hierarchy)                   │
│  ├── Versions (each edit increments version)                │
│  ├── Agents (track who read/edited what)                    │
│  └── Conflicts (stored for resolution)                      │
├─────────────────────────────────────────────────────────────┤
│  Storage (LMDB)                                             │
│  ├── nodes_db      - Document nodes                         │
│  ├── pending_db    - Pending reads by agent                 │
│  └── conflicts_db  - Unresolved conflicts                   │
├─────────────────────────────────────────────────────────────┤
│  Claude Code Hooks                                          │
│  └── SessionStart, PreCompact, PreToolUse, PostToolUse, Stop│
└─────────────────────────────────────────────────────────────┘

Key design decisions:

  • AST-based parsing: Uses markdown-it-py token line mapping to extract original source text, preserving exact formatting
  • LMDB storage: Memory-mapped for fast concurrent access, ACID transactions
  • Version vectors: Each node tracks version independently for fine-grained conflict detection
  • Agent isolation: Each agent's pending reads/conflicts are isolated

Testing

# Install dev dependencies
pip install -e ".[dev]"

# Run tests
pytest tests/ -v

# Run with coverage
pytest tests/ --cov=niwa --cov-report=html

84 tests covering:

  • Basic parsing (headings, nesting, hierarchy)
  • Code blocks (fenced, indented, with # inside)
  • GFM features (tables, task lists, strikethrough)
  • Frontmatter (YAML, TOML)
  • Edge cases (BOM, line endings, unicode, emoji)
  • Adversarial inputs (unclosed fences, HTML comments)
  • Round-trip export

Name

Niwa (庭) means "garden" in Japanese. Like a zen garden where gravel (砂利, jari) is raked into patterns, Niwa helps organize your plans and specs with deliberate structure. Multiple agents can collaboratively tend the same garden without disturbing each other's patterns.

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

niwa-0.2.0.tar.gz (40.3 kB view details)

Uploaded Source

Built Distribution

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

niwa-0.2.0-py3-none-any.whl (41.7 kB view details)

Uploaded Python 3

File details

Details for the file niwa-0.2.0.tar.gz.

File metadata

  • Download URL: niwa-0.2.0.tar.gz
  • Upload date:
  • Size: 40.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for niwa-0.2.0.tar.gz
Algorithm Hash digest
SHA256 4774ab0f58c3739fa42e53814aa3779a8e6ba490da45cde62615e253aed58bd0
MD5 796900d78992f7022108714cf1a001c3
BLAKE2b-256 97ae7e9b533fb743116866a58b4b4266084e527a6454ccc93e8e6f117fcb02ab

See more details on using hashes here.

Provenance

The following attestation bundles were made for niwa-0.2.0.tar.gz:

Publisher: publish.yml on secemp9/niwa

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file niwa-0.2.0-py3-none-any.whl.

File metadata

  • Download URL: niwa-0.2.0-py3-none-any.whl
  • Upload date:
  • Size: 41.7 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for niwa-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 18df099238c9a07ec868e676b41357df27f63df530d228caded3c5e954faec59
MD5 0823be194166709ef6e131c088ed448f
BLAKE2b-256 4772c026457cde2d5c4040fa507f241e4e613d18787e86a992d4e6c97a7d196c

See more details on using hashes here.

Provenance

The following attestation bundles were made for niwa-0.2.0-py3-none-any.whl:

Publisher: publish.yml on secemp9/niwa

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

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