Metadata-Version: 2.3
Name: hafiz
Version: 1.0.1
Summary: Agentic memory layer for LLM agents — filesystem MCP server with PARA+LYT vault conventions
Keywords: mcp,obsidian,memory,agents,llm,knowledge-management
Author: Yahia Khallouk
Author-email: Yahia Khallouk <yahia.khallouk@gmail.com>
License: MIT
Classifier: Development Status :: 5 - Production/Stable
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Software Development :: Libraries
Requires-Dist: fastmcp>=3.2.0,<4.0.0
Requires-Dist: python-frontmatter>=1.1.0,<2.0.0
Requires-Dist: sqlite-vec>=0.1.9,<0.2.0
Requires-Dist: fastembed>=0.5.0,<1.0.0 ; extra == 'vector'
Requires-Python: >=3.12
Project-URL: Homepage, https://github.com/yahiaklk/hafiz
Project-URL: Repository, https://github.com/yahiaklk/hafiz
Project-URL: Issues, https://github.com/yahiaklk/hafiz/issues
Provides-Extra: vector
Description-Content-Type: text/markdown

# hafiz

Agentic memory layer for LLM agents. A filesystem MCP server that gives agents structured read/write access to an Obsidian-style vault — projects, daily notes, tasks, MOCs, resources, and decisions — instead of ad-hoc file edits.

Uses PARA+LYT folder layout by default. All folder names are configurable. Part of the Personal AI OS stack (Hafiz + Kothar + Anzar).

## Install

```
pip install hafiz
# or
uv add hafiz
```

## MCP registration

```bash
claude mcp add -s user hafiz -- uv run --directory ~/projects/hafiz python -m hafiz.server
```

Do **not** edit `mcpServers` blocks in `settings.json` directly. The `claude mcp add` command writes to the correct registry; hand-edited `mcpServers` blocks spawn the process but the tools never appear in the session.

Verify registration:

```bash
claude mcp list
```

### Allow tools without per-call approval

Add a permission rule to `~/.claude/settings.json` (or `~/.claude-work/settings.json` if `CLAUDE_CONFIG_DIR` is set):

```json
{
  "permissions": {
    "allow": ["mcp__hafiz__*"]
  }
}
```

## Quick start

Zero configuration required. By default hafiz looks for your vault at `~/Documents/Obsidian Vault`.

Point it at your vault:

```bash
export VAULT_PATH="/path/to/your/vault"
uv run python -m hafiz.server
```

Tools fail gracefully when optional folders are absent — you don't need the full PARA structure on day one. `10_Projects/` and `70_Tasks/` cover most workflows.

## Configuration

Create `~/.hafiz/config.yaml` to override folder names. All keys are optional — omitted keys stay at their defaults.

```yaml
# ~/.hafiz/config.yaml
projects_dir: 10_Projects    # default
tasks_dir: 70_Tasks          # default
daily_dir: 50_Daily          # default
mocs_dir: 60_MOCs            # default
resources_dir: 30_Resources  # default
areas_dir: 20_Areas          # default
archive_dir: 40_Archive      # default
meta_dir: 99_Meta            # default
```

Example for a non-PARA vault with flat folder names:

```yaml
projects_dir: Projects
tasks_dir: Tasks
daily_dir: Journal
mocs_dir: Maps
resources_dir: Resources
areas_dir: Areas
archive_dir: Archive
meta_dir: .meta
```

For per-project overrides, set `HAFIZ_CONFIG` to an absolute path:

```bash
export HAFIZ_CONFIG=/path/to/project-specific-config.yaml
```

Resolution order (later wins): dataclass defaults → `~/.hafiz/config.yaml` → `HAFIZ_CONFIG`.

`VAULT_PATH` is separate and not handled by `config.yaml`.

## Tool reference

| Tool | Purpose |
|------|---------|
| `get_project` | Read CONTEXT.md + DECISIONS.md + NOTES.md for a project |
| `get_project_section` | Read a single file or one section from a project triplet; cheaper than `get_project` |
| `list_projects` | List all project slugs under the projects directory |
| `create_project` | Scaffold project triplet (CONTEXT/DECISIONS/NOTES) + MOC + seed task |
| `archive_project` | Move project to archive, close open tasks, rewrite MOC links |
| `add_observation` | Append an atomic structured observation to a project's Observations section |
| `update_project` | Append or prepend content under a section heading in CONTEXT.md or NOTES.md |
| `update_daily_note` | Append or prepend to a section in today's daily note; creates note from skeleton if missing |
| `list_tasks` | List tasks with optional filter by project slug and/or status |
| `close_task` | Mark a task done and move its file to the `done/` subfolder |
| `create_task` | Create a new task file with correct frontmatter |
| `update_task` | Mutate frontmatter fields on an open task |
| `update_task_notes` | Append or prepend content into a section of a task file's body |
| `log_decision` | Append a dated ADR entry to a project's DECISIONS.md |
| `get_moc` | Read a MOC file from the MOCs directory |
| `update_moc` | Append or prepend content under a section heading in a MOC file |
| `get_area` | Bundle all .md files directly under an area folder |
| `get_profile` | Read `20_Areas/Career/professional-profile.md` |
| `run_studyctl` | Bridge to the studyctl CLI for CKA/CKS study sessions |
| `search_vault` | Ranked search across vault .md files with a token budget |
| `rebuild_index` | Rebuild the SQLite FTS5 and vector index from vault files |
| `get_resource` | Read a resource note from the resources directory |
| `list_resources` | List all resource notes under the resources directory |
| `update_resource` | Append or prepend content under a section heading in a resource note |
| `vault_lint` | Run structural and provenance health checks; returns a grouped markdown report |
| `get_context_for_goal` | Assemble a token-budgeted context bundle for Anzar session bootstrapping |
| `add_fact_triple` | Store a (subject, predicate, object) fact triple with optional metadata |
| `query_fact_triples` | Filter stored fact triples by subject, predicate, and/or object |

## Architecture

Markdown files are canonical and Obsidian-compatible — open them in any editor at any time. SQLite (`.hafiz-index.db` at the vault root) is a materialised query layer rebuilt on demand: it holds an FTS5 full-text index, optional sqlite-vec vector embeddings (bge-large-en-v1.5, enabled when `hafiz[vector]` is installed), and a fact-triple store. MCP tools are the write API for agents — they go through atomic file writes and frontmatter parsing so concurrent agent sessions don't corrupt each other. There is no cloud dependency and no background daemon.

## Development

```bash
git clone https://github.com/yahiaklk/hafiz
cd hafiz
uv sync --all-extras
uv run pytest
uv run ruff check src/ tests/
uv run python -m hafiz.server   # starts the MCP server on stdio
```
