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.
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
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..."
localhost:6379)OPENAI_API_KEY for the default OpenAI provider)# Clone the repository
git clone https://github.com/AhmadCodes/MultiverseNoteV2.git
cd MultiverseNoteV2
# Install dependencies
uv sync
redis-server
export OPENAI_API_KEY="sk-..."
uv run multiverse
| 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 is managed via Hydra with composable YAML files in src/multiverse_note/conf/.
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
uv run multiverse redis.host=myhost redis.port=6380 redis.db=1
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
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
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
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
}
| 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 |
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
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:
| Purpose | Library |
|---|---|
| Terminal UI | textual |
| Redis | redis-py with hiredis |
| LLM Integration | litellm |
| Configuration | hydra-core |
| Package Management | uv |
| Testing | pytest + fakeredis |
This project is released under the Apache License 2.0. See the LICENSE file for details.