asobi 0.0.1

A persistent, project-local knowledge graph CLI for AI agents.
Documentation
# Miku: Usage Guide

## For humans

### Installation

From source via cargo (Rust 1.85+ toolchain required for edition 2024):

```bash
cargo install --git https://github.com/azusachino/miku miku
```

Prebuilt binary via `cargo-binstall` (once GitHub releases are published):

```bash
cargo binstall miku
```

Or build locally:

```bash
git clone https://github.com/azusachino/miku && cd miku
make build            # graph/MCP CLI at ./target/debug/miku
make build-documents  # includes ingest/query/compact
```

### Workspace setup

Run once on a new machine — defaults to user-level XDG paths:

```bash
miku init
# created  ~/.local/share/miku/data
# created  ~/.local/share/miku/topics
# created  ~/.local/share/miku/config
```

The user-level workspace is a single `$XDG_DATA_HOME/miku/` root (default `~/.local/share/miku/`) holding the same `{data,config,topics,caches}` subtree as a project-local `.miku/`. `XDG_DATA_HOME` is honored on every platform — macOS included. No root or elevation needed: it lives inside `$HOME` and is owned by the invoking user.

To keep a project's graph isolated and checked in alongside the code, use the local layout:

```bash
cd ~/code/my-project
miku init --local
# writes ./miku.toml + ./.miku/{data,topics,config}/
```

`miku.toml` (project-local mode):

```toml
data_dir   = ".miku/data"
config_dir = ".miku/config"
topics_dir = ".miku/topics"
```

Path resolution order at runtime: project-local `miku.toml` → project-local `.miku/` → XDG. Both `init` modes are idempotent.

Add `.miku/` to `.gitignore`; the `miku.toml` itself can be checked in.

### Common workflows

**Start a work session — load prior context:**

```bash
miku search-nodes "session"
miku open-nodes "my-project:session"
```
**Store a decision (supports hierarchical naming):**

```bash
miku create-entities "project-x:architecture" "project"
miku add-observations "project-x:architecture" "Switched from serde_yaml to toml crate — better error messages"
```

**Link related concepts (preserves case and dots):**

```bash
miku create-entities "UserPreferences" "preference"
miku create-entities "CLAUDE.md" "reference"
miku create-relations "project-x" "UserPreferences" "follows"
```

**Search (supports FTS5 and segment matching):**

```bash
miku search-nodes "tokio"           # finds "tokio", "tokio-util", stemmed variants
miku search-nodes "mobile"          # finds "ame:mobile-support:task-1" (segment match)
miku search-nodes "auth*"           # prefix: matches "auth", "authentication", "authorize"
miku search-nodes "async AND error" # both words must appear
miku search-nodes "deploy OR ship"  # either word
miku search-nodes "auth" --limit 25 # override the default top 100 matches
```

Use `read-graph` for full export. `search-nodes` is intentionally top-K by default so a broad term does not accidentally return the whole graph.

**End a session — persist state:**

```bash
miku delete-observations "my-project:session" "status: IN_PROGRESS"
miku add-observations "my-project:session" "status: DONE"
miku add-observations "my-project:session" "next: implement FTS5 index"
miku add-observations "my-project:session" "last-updated: 2026-05-21"
miku compact  # syncs graph → markdown files for durable backup
```

**Inspect the full graph:**

```bash
miku stats                                # Quick count of entities, relations, observations
miku read-graph | jq '.entities[] | select(.entityType == "session")'
```

**Backup, Restore, and Reset:**

```bash
miku export -o backup.json                # Export the entire graph to JSON
miku import backup.json                   # Import entities and relations from a JSON backup
miku reset                                # Interactively clear the entire graph (use --force to bypass)
```

**Manage truths (structured key-value attributes):**

```bash
miku add-truth "project-x" "language" "rust"
miku delete-truth "project-x" "language"
```

**Manage skills (reusable workflows and knowledge):**

```bash
miku skills install https://github.com/azusachino/miku-skills --all
miku skills
miku skills show my-skill
miku skills update
miku skills remove miku-skills
```


**Ingest Markdown into the document tier (optional):**

These commands require a binary built with `--features documents`:

```bash
miku ingest ./notes/             # directory of .md files
miku query "async cancellation"  # semantic + FTS search
```

---

## For agents

### Overview

Miku is a persistent, project-local knowledge graph. Agents use it to:

- **Persist** decisions, task state, and user preferences across sessions
- **Share** context with other agents working on the same project
- **Resume** work without re-deriving context from git history or code

All operations are CLI commands. No server to start. No authentication. Latency is <10ms for graph operations.

### Session protocol

**At session start:**

```bash
# Option A: load a specific entity
miku open-nodes "<project>:session"

# Option B: keyword search
miku search-nodes "session"

# Option C: full graph (small projects)
miku read-graph
```

**During session — record facts as you learn them:**

```bash
miku add-observations "<project>" "Decided to use WAL mode for concurrent agent access"
miku add-observations "<project>:session" "status: IN_PROGRESS"
```

**At session end:**

```bash
# Update volatile state
miku delete-observations "<project>:session" "<old status line>"
miku add-observations "<project>:session" "status: DONE"
miku add-observations "<project>:session" "completed: implemented FTS5 search"
miku add-observations "<project>:session" "next: add WAL mode and entity_name index"
miku add-observations "<project>:session" "last-updated: 2026-05-21"

# Archive to markdown (durable, re-indexed)
miku compact
```

**Full session reset (next agent starts clean):**

```bash
miku delete-entities "<project>:session"
# Next agent creates it fresh
miku create-entities "<project>:session" "session"
```

### Entity naming conventions

| Pattern             | Type         | Purpose                                      |
| ------------------- | ------------ | -------------------------------------------- |
| `<project>:session` | `session`    | Volatile task state — reset each session     |
| `<project>:tasks`   | `task`       | In-progress task tracking                    |
| `<project>`         | `project`    | Stable project facts, architecture decisions |
| `UserPreferences`   | `preference` | Cross-project user habits                    |
| `CodingStyle`       | `standard`   | Commit format, indentation, etc.             |
| `ToolPreferences`   | `preference` | Mise, make, rtk, etc.                         |

### Output format

Miku operates under a **lazy-read contract** to minimize token overhead.

`read-graph` and `search-nodes` return a lazy JSON structure (excluding `observations` and skill `body`, only providing `truths` and `observationCount`):

```json
{
  "entities": [
    {
      "name": "string",
      "entityType": "string",
      "truths": {
        "key": "value"
      },
      "observationCount": 12
    }
  ],
  "relations": [
    {
      "from": "string",
      "to": "string",
      "relationType": "string"
    }
  ]
}
```

`open-nodes` eagerly returns all `observations` and the skill `body` (if it's a skill entity):

```json
{
  "entities": [
    {
      "name": "string",
      "entityType": "string",
      "observations": ["string", ...],
      "truths": {
        "key": "value"
      },
      "observationCount": 12,
      "body": "string"
    }
  ],
  "relations": [
    {
      "from": "string",
      "to": "string",
      "relationType": "string"
    }
  ]
}
```

Mutation commands print a one-line confirmation: `Entity 'X' created.`, `Observation added.`, etc.

### Multi-agent context handoff

When Agent A finishes and Agent B picks up:

```bash
# Agent A (end of session)
miku add-observations "project-x:session" "status: BLOCKED"
miku add-observations "project-x:session" "next: Agent B should implement WAL mode in src/db.rs init_db()"
miku compact

# Agent B (start of session)
miku open-nodes "project-x:session"
# → reads: status BLOCKED, next action, last-updated
```

No files to pass, no state to reconstruct. The graph is the handoff.

### Search tips

`search-nodes` uses FTS5 with porter stemming. Practical implications:

- `search-nodes "run"` → finds entities with "running", "runner", "ran"
- `search-nodes "implement"` → finds "implementation", "implementing"
- `search-nodes "tokio async"` → finds entities with both words (ranked higher) or either word
- `search-nodes "UserPreferences"` → exact name match via LIKE fallback (entity has no observations)
- `search-nodes "AND AND"` → invalid FTS5 syntax, silently falls back to LIKE, returns empty
- `search-nodes "auth" --limit 500` → return more than the default top 100 matches

For exact entity retrieval, prefer `open-nodes` over `search-nodes`:

```bash
miku open-nodes "project-x:session" "UserPreferences"
```

### MCP server mode (optional)

If your agent framework supports MCP stdio servers:

```bash
# Register once
claude mcp add miku -- miku mcp

# Protocol: MCP 2024-11-05, 11 tools
# Tools: create_entities, create_relations, add_observations,
#        delete_entities, delete_observations, delete_relations,
#        add_truth, delete_truth,
#        read_graph, search_nodes, open_nodes
```

The MCP server uses the same storage as the CLI — data written via `miku mcp` is immediately readable via `miku read-graph` and vice versa.

`search_nodes` accepts an optional `limit` argument. Omit it for the default top 100 matches; set it explicitly for larger ranked exports.