A local-first, modular, graph-based knowledge-work application built with Python and PySide6.
Most knowledge tools force you to think in files and folders. Notes go in one app, tasks in another, outlines in a third — and the relationships between ideas live nowhere. When a project grows complex, the structure you actually need (hierarchies, networks, cross-references, typed relationships) is constantly fighting the flat document model that most tools provide.
There are graph databases and graph editors, but they are either developer-facing infrastructure or expensive enterprise tools. There is no lightweight, extensible, locally-owned desktop application where the graph is the first-class artifact and where the shape of the graph — its node types, edge types, and validation rules — can be defined per-domain by the user or developer.
Knowledge Platform treats structured graphs as first-class artifacts. Each workspace holds one or more graph instances, each governed by a graph type that declares what nodes and edges are valid and what attributes they carry. The application is built on a modular plugin architecture: each module contributes a graph type, a domain service, a projection (view), and a UI widget, and modules are loaded at runtime from configuration rather than hard-wired into the host.
The result is an application that can host very different knowledge tools — a hierarchical outline, a kanban board, a concept map, a bibliography — each with its own semantics, all sharing the same persistence and identity infrastructure.
Version 0.1 ships with a single module: the Outline module, which models hierarchical document outlines as a tree of nodes connected by parent-child edges.
- Typed graph engine — Nodes and edges carry a semantic type validated against a registered schema before any write reaches the database.
- Local-first persistence — All data lives in a single SQLite file per workspace. No cloud account, no server, no sync required.
- Config-driven plugin architecture — Installed modules can be enabled through
modules.yamlwithout editingapp.pyorMainWindow. - Immutable value-objects — Nodes and edges are frozen dataclasses; every mutation produces a versioned new instance, making history tracking straightforward.
- Strict layer separation — UI contains no business logic; domain logic contains no Qt imports. All layers communicate through explicit typed contracts (
typing.Protocol). - Tree projection — The Outline module projects a graph into an ordered tree view with full expand/collapse, context menu, and inline editing.
graph TB
subgraph UI
MW[MainWindow]
OV[OutlineView]
OVM[OutlineViewModel]
EB[AppEventBus]
end
subgraph SVC
IGS[IGraphService Protocol]
GS[GraphService]
WS[WorkspaceService]
end
subgraph MOD
OM[OutlineModule]
OS[OutlineService]
OTP[OutlineTreeProjection]
end
subgraph CORE
G[Graph]
N[Node]
E[Edge]
GE[GraphEngine]
GT[GraphType]
TR[TypeRegistry]
end
subgraph PERSIST
REPO[SqliteGraphRepository]
DB[(SQLite)]
end
UI -->|service calls| SVC
SVC --> CORE
SVC --> MOD
MOD --> CORE
CORE --> PERSIST
style UI fill:#dbeafe,stroke:#3b82f6,color:#1e3a5f
style SVC fill:#dcfce7,stroke:#22c55e,color:#14532d
style MOD fill:#fef9c3,stroke:#eab308,color:#713f12
style CORE fill:#fce7f3,stroke:#ec4899,color:#831843
style PERSIST fill:#f3f4f6,stroke:#6b7280,color:#111827
For the full design — class diagrams, sequence diagrams, state machines, ER diagram, and the module extension guide — see DESIGN.md.
| Dependency | Version |
|---|---|
| Python | 3.11 or later |
| PySide6 | 6.6 or later |
| SQLAlchemy | 2.0 or later |
| PyYAML | 6.0 or later |
| pydantic | 2.0 or later |
| structlog | 24.0 or later |
| ulid-py | 1.1 or later |
git clone https://github.com/mattbriggs/knowledge-platform.git
cd knowledge-platformpython3 -m venv .venv
source .venv/bin/activate # macOS / Linux
# .venv\Scripts\activate # WindowsFor end users (runtime only):
pip install -e .For developers (includes test runner, type checker, linter, docs):
pip install -e ".[dev]"Note on PySide6: The first install downloads the Qt runtime (~130 MB). This is a one-time cost per virtual environment.
python -c "import knowledge_platform; print(knowledge_platform.__version__)"
# 0.1.0knowledge-platformOr, if the entry point script is not on your PATH:
python -m knowledge_platform.mainThe application starts with an empty window. Follow these steps to create your first outline:
- File → New Workspace… — enter a name (e.g.
My Notes). - Select the Outline tab if it is not already active.
- File → New Outline… or click New Outline in the toolbar.
- The outline panel appears with a root item. Use the toolbar or right-click context menu to add, edit, and remove items.
Modules are loaded from configuration at startup.
Lookup order:
KNOWLEDGE_PLATFORM_MODULES_FILE~/.knowledge_platform/modules.yaml- the packaged default config
Example:
version: 1
strict: true
modules:
- id: outline
enabled: true
source: entry_pointFor local development, an explicit import path is also supported:
version: 1
strict: true
modules:
- id: outline
enabled: true
source: import
factory: knowledge_platform.modules.outline.module:OutlineModulesource: entry_point is the preferred mode for installed plugins. source: import is useful while developing modules in-tree before reinstalling package metadata.
The Outline module presents a hierarchical tree of items, each with a title and optional content body.
| Action | Description |
|---|---|
| Add Root Item | Creates a new top-level item with no parent |
| Add Child Item | Creates a child of the currently selected item |
| Edit Item | Opens a dialog to edit the title and content of the selected item |
| Remove Item | Deletes the selected item and all its descendants |
Right-click any item in the tree to access the same actions contextually.
Selecting an item displays its full content in the panel on the right. The tree column shows a truncated preview; the detail panel shows the complete text.
- Click Add Root Item and type a title to create the document root.
- Select the root, click Add Child Item to add a first section.
- Select a section, keep adding children to build a nested hierarchy.
- Double-click or press Edit Item to fill in the content of any node.
# All unit and integration tests (no display required)
pytest tests/unit tests/integration --no-cov
# With coverage report (domain + services, UI rendering excluded)
pytest tests/unit tests/integration
# Specific test file
pytest tests/unit/modules/outline/test_service.py -vThe exact test count will vary as the module and loader coverage evolves.
pip install -e ".[dev]"
mkdocs serve
# Open http://127.0.0.1:8000These are known constraints in the current v0.1 release. They are design decisions for a local, single-user first version — not bugs.
| Limitation | Detail |
|---|---|
| Data not persisted between sessions | The current build uses an in-memory SQLite database (:memory:). All workspace and graph data is lost when the application closes. A file-backed database path is planned for Milestone 1. |
| Single active workspace | The application manages one active workspace at a time, but you can create or open a different workspace from the running app. |
| Single active graph | The UI loads one graph into the active module at a time. There is no side-by-side multi-graph editing yet. |
| No undo / redo | Mutations are immediately committed to the graph and database. There is no undo stack. The Transaction primitive exists and could support undo in a future milestone. |
| No drag-and-drop reordering | Items can be moved via OutlineService.move_item() but the UI does not yet expose drag-and-drop. |
| Single bundled module | The host can load modules from configuration, but only the Outline module ships in this repository today. |
| No graph export | There is no JSON, Markdown, or PDF export in the current version. |
| No search | There is no cross-graph or cross-workspace search. |
| No multi-window | Each module lives in a tab. There is no way to open two outlines side-by-side. |
| Single-user only | The cache and persistence layer assume a single writer. Multi-process access to the same SQLite file is not safe. |
| No attribute indexing | Node and edge attributes are stored as JSON blobs. SQL-level queries against attribute values are not supported. |
The following milestones are planned in rough priority order. None are committed dates — they represent the natural next steps from the current architecture.
- Persist the last-opened workspace and reopen it on launch.
- Add a startup chooser for opening an existing workspace or creating a new one.
- Persist the last-opened graph per module.
- Drag-and-drop reordering of outline items.
- Keyboard shortcuts (Enter to add sibling, Tab/Shift-Tab to indent/outdent).
- Inline title editing directly in the tree (no dialog needed for title changes).
- Undo / redo via the
Transactionprimitive already in the engine.
- Export an outline to Markdown (heading hierarchy).
- Export to plain text and HTML.
- Import a Markdown file as an outline graph.
- Implement a second module (e.g. Kanban board or concept map) using only package installation plus
modules.yaml. - This milestone validates the config-driven plugin host against a different graph shape.
- Full-text search across node titles and content within a workspace.
- Backlink view: show all nodes that reference a given node by title.
- Surface the
versioncounter already stored on every node and edge. - Record a changelog per graph (timestamp, operation, old/new attributes).
- Allow diff-view and point-in-time restore.
- Allow each module to register more than one projection (e.g. Outline can show tree view OR flat reading view).
- Add a projection switcher to the module tab toolbar.
- The architecture was designed to be migrated to Swift with data compatibility.
- Milestone: define a portable on-disk format (JSON or SQLite schema) shared between the Python and Swift implementations.
knowledge-platform/
├── pyproject.toml # Build system, dependencies, tool config
├── requirements.txt # Flat dependency list for pip
├── DESIGN.md # Architecture, diagrams, patterns, extension guide
├── docs/ # MkDocs source
└── src/knowledge_platform/
├── core/ # Graph engine, Node, Edge, Transaction
├── domain/ # GraphType system, TypeRegistry
├── persistence/ # SQLAlchemy ORM, SqliteGraphRepository
├── services/ # IGraphService contract + implementations
├── workspace/ # Workspace container
├── modules/
│ ├── base.py # ModuleDescriptor + GraphWidget protocols
│ ├── registry.py # ModuleRegistry
│ └── outline/ # Outline plugin (self-contained)
└── ui/
├── app.py # Application bootstrap
├── events.py # AppEventBus (cross-component signals)
├── main_window.py # QMainWindow
└── outline/ # Outline view + viewmodel
Contributions are welcome. Before opening a pull request:
- Run the test suite:
pytest tests/unit tests/integration --no-cov - Run the type checker:
mypy src/ - Run the linter:
ruff check src/ tests/ - Run the formatter:
ruff format src/ tests/ - Add tests for any new domain or service logic.
- If adding a new module, follow the module extension guide in DESIGN.md.
MIT — see LICENSE.