Skip to content

Open-source terminal-based application that transforms AI chatbot interactions into structured knowledge management workflows with branch management system.

License

Notifications You must be signed in to change notification settings

AierLab/MultiverseNoteV2

 
 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

3 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

MultiverseNote v2

Introduction

MultiverseNote is an open-source terminal-based application that transforms AI chatbot interactions into structured knowledge management workflows. It introduces a branch management system where users can discuss topics on a main branch and create new branches for in-depth exploration, enabling systematic and continuous knowledge development.

Each conversation is organized into branches with numbered references (e.g. #1, #2), allowing you to fork discussions, load context from other branches, and tag conversation pairs for easy retrieval.

Core Architecture

Every component (UI, LLM, context management) runs as an isolated process node, communicating exclusively through Redis Pub/Sub. This ensures modularity and allows components to be developed, tested, and scaled independently.

flowchart LR
    UI["Terminal UI\n(Textual)"]
    CTX["ContextNode\n(Branch & Context)"]
    LLM["LLMNode\n(litellm)"]
    R[(Redis)]

    UI -- "ch:user_input" --> R
    R -- "ch:user_input" --> CTX
    CTX -- "store user node\n+ assemble context" --> R
    CTX -- "ch:llm_request" --> R
    R -- "ch:llm_request" --> LLM
    LLM -- "ch:llm_response" --> R
    R -- "ch:llm_response" --> UI

    style R fill:#dc382c,color:#fff
    style UI fill:#1a8cff,color:#fff
    style CTX fill:#2b8a3e,color:#fff
    style LLM fill:#7c3aed,color:#fff
Loading

Features

gitGraph
    commit id: "user: What is Rust?"
    commit id: "assistant: Rust is a..."
    branch deep-dive
    commit id: "user: Explain ownership"
    commit id: "assistant: Ownership in Rust..."
    branch ownership-examples
    commit id: "user: Show me borrowing"
    commit id: "assistant: Here is an example..."
    checkout deep-dive
    commit id: "user: What about lifetimes?"
    commit id: "assistant: Lifetimes ensure..."
    checkout main
    commit id: "user: Compare Rust vs Go"
    commit id: "assistant: Both are systems..."
Loading
  • Branch Management — Create, switch, and navigate conversation branches with parent-child relationships
  • Context References — New branches can reference existing branches, loading their conversation history as context for the LLM
  • Tag System — Tag conversation pairs with colored labels for organization and retrieval
  • Multi-Provider LLM — Supports OpenAI, Anthropic, and local models via litellm
  • Terminal UI — Full keyboard-navigable TUI built with Textual
  • Isolated Nodes — Each component runs as a separate process communicating via Redis
  • File-based Logging — All logs written to rotating files, no terminal output clutter

Prerequisites

  • Python >= 3.11
  • Redis server running locally (default: localhost:6379)
  • uv package manager
  • An LLM API key (e.g. OPENAI_API_KEY for the default OpenAI provider)

Installation

# Clone the repository
git clone https://github.com/AhmadCodes/MultiverseNoteV2.git
cd MultiverseNoteV2

# Install dependencies
uv sync

Usage

Start Redis

redis-server

Set your API key

export OPENAI_API_KEY="sk-..."

Launch the application

uv run multiverse

Keyboard Shortcuts

Key Action
Enter Send message
Ctrl+B Open branch tree
Ctrl+Q Quit
Escape Close modal / Go back
N New branch (in branch tree)

Configuration

Configuration is managed via Hydra with composable YAML files in src/multiverse_note/conf/.

LLM Provider

Default is OpenAI. To use Anthropic:

uv run multiverse llm=anthropic

Or override individual settings:

uv run multiverse llm.model=openai/gpt-4o-mini llm.temperature=0.5

Redis

uv run multiverse redis.host=myhost redis.port=6380 redis.db=1

Config Files

src/multiverse_note/conf/
├── config.yaml            # Main config (composes all groups)
├── redis/default.yaml     # host, port, db, password
├── llm/
│   ├── default.yaml       # Default provider (OpenAI)
│   ├── openai.yaml
│   └── anthropic.yaml
├── ui/default.yaml        # Theme, layout preferences
└── logging/default.yaml   # Log level, file path, rotation

Process Model

flowchart TB
    MAIN["main.py\n@hydra.main"]

    MAIN -->|"multiprocessing.Process\n(daemon)"| CTX_PROC["ContextNode Process"]
    MAIN -->|"multiprocessing.Process\n(daemon)"| LLM_PROC["LLMNode Process"]
    MAIN -->|"runs in main process\n(needs terminal)"| UI_PROC["MultiverseApp (Textual)"]

    CTX_PROC -. "Redis Pub/Sub" .- REDIS[(Redis)]
    LLM_PROC -. "Redis Pub/Sub" .- REDIS
    UI_PROC -. "Redis Pub/Sub" .- REDIS

    MAIN -->|"SIGINT / Ctrl+Q"| SHUTDOWN["Graceful Shutdown"]
    SHUTDOWN -->|"ch:system → shutdown"| REDIS

    style REDIS fill:#dc382c,color:#fff
    style MAIN fill:#333,color:#fff
    style SHUTDOWN fill:#e67700,color:#fff
Loading

Project Structure

MultiverseNoteV2/
├── pyproject.toml                  # UV-managed dependencies
├── src/
│   └── multiverse_note/
│       ├── conf/                   # Hydra configuration (bundled in package)
│       ├── main.py                 # Entry point: launches all nodes
│       ├── models/                 # Data models (dataclasses)
│       │   ├── branch.py           # Branch model
│       │   ├── node.py             # ConversationNode model
│       │   └── tag.py              # Tag model
│       ├── store/                  # Redis storage layer
│       │   ├── redis_client.py     # Redis connection wrapper
│       │   ├── branch_store.py     # Branch CRUD operations
│       │   ├── node_store.py       # ConversationNode CRUD
│       │   └── tag_store.py        # Tag CRUD operations
│       ├── nodes/                  # Isolated process nodes
│       │   ├── base.py             # Abstract BaseNode class
│       │   ├── llm_node.py         # LLM processing node
│       │   └── context_node.py     # Context & branch management node
│       ├── ui/                     # Terminal UI (Textual)
│       │   ├── app.py              # Main Textual App
│       │   ├── screens/
│       │   │   ├── conversation.py # Active conversation screen
│       │   │   ├── branch_tree.py  # Branch navigation/overview
│       │   │   └── tag_select.py   # Tag selection modal
│       │   └── widgets/
│       │       ├── message_view.py # Renders conversation messages
│       │       ├── context_bar.py  # Shows loaded context refs
│       │       └── tag_badge.py    # Colored tag display
│       └── utils/
│           └── logging.py          # File-based logging utility
├── tests/                          # Test suite (51 tests)
│   ├── conftest.py                 # fakeredis fixtures
│   ├── test_models/
│   ├── test_store/
│   └── test_nodes/
└── logs/                           # Git-ignored log output

Redis Schema

erDiagram
    BRANCH {
        int id PK
        string name
        string created_at
        int parent_branch_id FK
        string status
    }
    BRANCH ||--o{ NODE : "branch:id:nodes"
    BRANCH ||--o{ BRANCH : "branch:id:context_refs"

    NODE {
        int id PK
        int branch_id FK
        string role
        string content
        string title
        string summary
        string timestamp
    }
    NODE ||--o{ TAG : "node:id:tags"

    TAG {
        int id PK
        string name
        string color
        string created_at
    }
Loading

Key Patterns

Key Type Description
counter:branch int Auto-increment ID for branches
counter:node int Auto-increment ID for nodes
counter:tag int Auto-increment ID for tags
branch:{id} Hash Branch metadata
branch:{id}:nodes List Ordered node IDs in a branch
branch:{id}:context_refs Set Referenced branch IDs as context
node:{id} Hash Conversation node data
node:{id}:tags Set Tag IDs assigned to a node
tag:{id} Hash Tag metadata
tags:all Set All tag IDs

Pub/Sub Channels

flowchart TB
    subgraph Channels
        direction LR
        ui_in["ch:user_input"]
        llm_req["ch:llm_request"]
        llm_res["ch:llm_response"]
        br_ev["ch:branch_event"]
        tag_ev["ch:tag_event"]
        sys["ch:system"]
    end

    UI(["Terminal UI"]) -->|user text| ui_in
    ui_in -->|consumed by| CTX(["ContextNode"])
    CTX -->|assembled context| llm_req
    llm_req -->|consumed by| LLM(["LLMNode"])
    LLM -->|response| llm_res
    llm_res -->|displayed by| UI

    UI -->|create/switch| br_ev
    br_ev -->|handled by| CTX
    UI -->|create/assign| tag_ev
    tag_ev -->|handled by| CTX

    MAIN(["main.py"]) -->|shutdown| sys
    sys -->|stops| CTX
    sys -->|stops| LLM
    sys -->|stops| UI
Loading

Testing

Tests use fakeredis to simulate Redis without a running server.

# Run all 51 tests
PYTEST_DISABLE_PLUGIN_AUTOLOAD=1 uv run pytest tests/ -v

Test coverage includes:

  • Model tests — Serialization roundtrips for Branch, ConversationNode, Tag
  • Store tests — Full CRUD operations with fakeredis
  • Node tests — BaseNode lifecycle, ContextNode branch/context/tag management, LLMNode with mocked litellm

Key Libraries

Purpose Library
Terminal UI textual
Redis redis-py with hiredis
LLM Integration litellm
Configuration hydra-core
Package Management uv
Testing pytest + fakeredis

License

This project is released under the Apache License 2.0. See the LICENSE file for details.

About

Open-source terminal-based application that transforms AI chatbot interactions into structured knowledge management workflows with branch management system.

Resources

License

Stars

Watchers

Forks

Languages

  • Python 100.0%