| Component | Description |
|---|---|
| Skills | Markdown instructions under skills/ that Claude executes as slash commands |
| MCP server | Python process project-hub-mcp (stdio), started through bin/run-server with the Python from ~/.project-hub/venv |
| Database | SQLite file, by default ~/.project-hub/project-hub.db |
| Files | Markdown notes and attachments under docs_root, knowledge documents under knowledge_root |
The plugin defines no hooks. The server initializes the database at startup and adds missing tables and columns itself.
~/.project-hub/
βββ config.yaml
βββ project-hub.db (plus -wal and -shm while running)
βββ venv/
βββ knowledge/<project-type>/*.md
βββ project-types/<type>/ custom project types
βββ reports/ HTML reports
βββ exports/ JSON exports
{docs_root}/<project-slug>/docs/
βββ emails/
βββ meeting-notes/
βββ misc/
βββ attachments/
| Table | Content |
|---|---|
projects |
Slug (unique), name, type, status, description, market, products, phase, go-live, budget, notes, docs path, timestamps |
contacts |
Project, name, role, type (internal or external), email, phone, company, notes, is_shared |
notes |
Project, title, type, content, agenda, attachments (JSON list), file path, timestamps |
project_links |
Links between two projects |
session |
exactly one row: active project and last used skill |
successor or related. predecessor is the reverse view of a successor.When a note is created, the server writes the text to the database and also as a Markdown file in the project's docs folder:
| Note type | Target folder | File |
|---|---|---|
meeting-notes |
meeting-notes/ |
<date>-<title-slug>.md |
email |
emails/ |
<date>-<title-slug>.md |
decision, note |
misc/ |
<date>-<title-slug>.md |
action-item |
misc/ |
entry in the shared file todo.md under "Open" |
The database is the authoritative source:
tool_update_note (and thus edit-note) write to the database only. The Markdown file keeps the old title, content and subfolder.action-item, because todo.md holds several tasks.note and a decision share misc/. The title slug is truncated to 50 characters, so different long titles with the same beginning can collide as well. In all cases the database keeps both notes. A date or a distinguishing prefix at the start of the title avoids this.{docs_root}/<slug>/docs/attachments/. The original stays untouched.tool_add_note with source_paths preserves the originals in the same call, so referenced files are not lost.An export (compose export) is a JSON file with the project, contacts, notes and links (links by the other project's slug).
rename appends a timestamp to the slug. overwrite deletes the existing project completely, including its docs folder with note Markdown files and attachments on disk, and recreates it.The report is a single HTML file rendered from a Jinja2 template. When opened in a browser, the file loads its chart library (Chart.js) from cdn.jsdelivr.net. Without an internet connection this library is missing. Labels are in German. The "Offene Aufgaben" (open tasks) section contains all notes of type action-item, without a completion filter.
Search is a simple substring search (SQL LIKE) without an index and without ranking. Case is ignored for ASCII letters only, umlauts are compared exactly. % and _ in the search term act as wildcards. Notes are returned newest first, contacts sorted by name.