Everything for phren lives here now.
This page is the full manual: install and first run, CLI and MCP reference, shell and VS Code workflows, team sharing, security, FAQ, contributing, and architecture. No split docs island, no separate community page to hunt through.
Install it, initialize your store, add a project, and get hooks and MCP working without guessing.
Daily UseCLI reference, MCP tool catalog, shell workflows, and VS Code integration are grouped in one place.
TeamsProfiles, syncing, RBAC, consolidation, and project ownership all fit into the same operating model.
Build on phrenDev setup, testing, style rules, PR expectations, and architecture notes are part of the same docs flow.
Getting Started
Install phren, create your first project, and start building persistent memory for your AI agents.
Installation #
Five steps from zero to working memory.
phren is published as @phren/cli on npm. Install it globally:
npm install -g @phren/cli
Node.js 20 or later. Check with node --version.
Run init to configure hooks and MCP for your agents:
phren init
Expected output:
phren init v0.0.47
Detected agents: Claude Code, Copilot
Created ~/.phren/
Registered MCP server in ~/.claude/settings.json
Registered hooks: SessionStart, UserPromptSubmit, PostToolUse, Stop
Wrote Copilot MCP config
Initialized git repo in ~/.phren
Done. Run 'phren verify' to check setup.
Init is idempotent: re-running it updates MCP config and hooks without clobbering your data.
Add your project directory:
# From inside your project directory
phren add
# Or specify a path
phren add ~/my-project
This creates ~/.phren/my-project/ with:
CLAUDE.md— project-specific agent instructionsFINDINGS.md— captured insights and patternstasks.md— task queue (active, queued, done)summary.md— project summary for context injection
Open your agent and start coding. phren works automatically in the background:
- Every session start pulls the latest state from git
- Every prompt gets relevant context injected from your knowledge store
- Every finding and task is persisted back to git after each response
Confirm everything is wired up:
phren verify
Expected output:
phren verify
Root: ~/.phren (shared mode)
Profile: main (3 projects)
Hooks: Claude Code (SessionStart, UserPromptSubmit, PostToolUse, Stop)
MCP: registered in ~/.claude/settings.json
Git: clean, remote configured
All checks passed.
Quickstart #
The fastest path from zero to working memory — combines all five steps above:
phren quickstart
This runs phren init followed by an interactive project scaffolding wizard.
How It Works #
phren operates on three paths during every prompt cycle:
- Retrieval — keyword extraction from your prompt, synonym expansion, FTS5 search, and snippet injection into agent context.
- Governance — citation validity checks, confidence decay, policy thresholds to filter low-quality memories.
- Persistence — MCP tools write findings/tasks, the Stop hook auto-commits and pushes to git.
Hooks run at lifecycle points:
SessionStart— git pull on~/.phren, project context injectionUserPromptSubmit— search + inject relevant context on every promptPostToolUse— queue review candidates and capture follow-up context after tool callsStop— auto-commit and push after every response
First-Run Lifecycle
flowchart LR
A["npm install -g
@phren/cli"] --> B["phren init"]
B --> C["Hooks wired"]
C --> D["First prompt"]
D --> E["SessionStart hook
git pull"]
E --> F["UserPromptSubmit hook
FTS5 search"]
F --> G["Context injected
into agent"]
G --> H["Stop hook
git commit + push"]
style A fill:#1a1a3e,stroke:#00E5FF,color:#E8E4D9
style B fill:#1a1a3e,stroke:#9B8DC8,color:#E8E4D9
style C fill:#1a1a3e,stroke:#28C840,color:#E8E4D9
style D fill:#1a1a3e,stroke:#00E5FF,color:#E8E4D9
style E fill:#1a1a3e,stroke:#9B8DC8,color:#E8E4D9
style F fill:#1a1a3e,stroke:#9B8DC8,color:#E8E4D9
style G fill:#1a1a3e,stroke:#28C840,color:#E8E4D9
style H fill:#1a1a3e,stroke:#FFBD2E,color:#E8E4D9
Multi-Repo Setup #
Add as many projects as you want. Each gets its own findings, tasks, and config:
phren add ~/frontend-app
phren add ~/backend-api
phren add ~/shared-lib
Projects support ownership modes:
owned— full read/write, hooks active (default)observed— read-only context injection, no writesarchived— excluded from active profile, data preserved
Profiles & Machines #
Profiles map sets of projects to machine roles:
# ~/.phren/profiles/work.yaml
projects:
- frontend-app
- backend-api
- shared-lib
# ~/.phren/profiles/personal.yaml
projects:
- side-project
- dotfiles
Map machines to profiles in ~/.phren/machines.yaml:
machines:
work-laptop: work
home-desktop: personal
server: work
Syncing Across Machines #
~/.phren is a git repo. Sync across machines:
# On your current machine
phren push_changes "sync from laptop"
# On a new machine
phren init # pulls from remote
The SessionStart hook automatically runs git pull at the start of every session.
Agent Setup #
phren init auto-configures all detected agents:
- Claude Code — MCP server + hooks for SessionStart, UserPromptSubmit, PostToolUse, Stop
- Copilot — MCP server config for chat mode
- Cursor — MCP settings for agent/composer mode
- Codex — MCP server registration
Verify with phren doctor --agents.
Troubleshooting #
Node.js Version Mismatch
phren requires Node.js 20+. If you see syntax errors:
node --version # must be v20.0.0 or later
nvm use 20 # if using nvm
Permission Errors
If npm install -g fails with EACCES:
mkdir -p ~/.npm-global
npm config set prefix '~/.npm-global'
# Add to ~/.bashrc or ~/.zshrc:
export PATH="$HOME/.npm-global/bin:$PATH"
Do not use sudo npm install -g. This creates root-owned files that cause permission issues later.
MCP Connection Failures
If your agent cannot connect to the phren MCP server:
# Quick fix: re-run init to regenerate MCP config
phren init
# Or run doctor with auto-fix
phren doctor --fix
Hooks Not Firing
# View hook status
phren hooks list
# Check for errors
phren hooks errors --limit 5
Concepts
The building blocks of how phren stores, ages, and surfaces project knowledge.
Findings #
A finding is a single unit of knowledge stored in FINDINGS.md. Each one carries a type tag, a lifecycle state, and a confidence score that decays over time.
Write a finding without a type prefix and phren auto-tags it. "We decided..." becomes [decision], "Watch out for..." becomes [pitfall].
Finding Types
Phren recognises seven finding types:
[decision] never decays. [observation] expires after 14 days. All other types follow the default decay curve.
Citations: Findings can carry optional citations linking them to source code. Findings with valid citations rank higher; findings with missing citations receive a 0.8x penalty.
Lifecycle States
Every finding moves through a lifecycle that determines its retrieval ranking:
stateDiagram-v2
[*] --> Active : add_finding
Active --> Superseded : supersede_finding
Active --> Contradicted : resolve_contradiction
Active --> Retracted : retract_finding
Active --> Stale : confidence decay
Stale --> Active : re-confirmed
Stale --> Pruned : maintain prune
Superseded --> Pruned : maintain prune
Retracted --> Pruned : maintain prune
Active --> InvalidCitation : citation check fails
state Active {
direction LR
}
| State | Retrieval Score | In FTS Index? |
|---|---|---|
active | 1.0x | Yes |
contradicted | 0.4x | Yes |
superseded | 0.25x | No |
retracted | 0.1x | No |
stale | Confidence-based | Yes |
invalid_citation | 0.5x | Yes |
Trust & Decay #
Every finding starts with full confidence (1.0). As it ages, confidence decays through a stepped schedule:
| Age | Multiplier | Effect |
|---|---|---|
| 0 -- 30 days | 1.0 | Full confidence |
| 30 -- 60 days | 0.9 | Slightly reduced |
| 60 -- 90 days | 0.75 | Moderate reduction |
| 90 -- 120 days | 0.5 | Low confidence |
| 120+ days | suppressed | Excluded from retrieval |
Findings repeatedly confirmed accumulate a decay-resistance boost and decay 3x slower. Pin permanent knowledge to truths.md using pin_memory.
Consolidation #
As FINDINGS.md grows, phren triggers consolidation. It deduplicates entries, archives older ones into collapsed <details> blocks, and promotes patterns appearing in 2+ projects to global/FINDINGS.md.
Automatic triggers:
- 25 entries added since the last consolidation marker, or
- 60 days have passed with at least 10 entries.
phren maintain consolidate my-app
phren maintain consolidate my-app --dry-run # preview
Fragment Knowledge Graph #
A fragment is a named concept that links across findings and docs. Fragments let you trace a topic across projects.
graph LR
subgraph "Project A"
F1["[pitfall] Auth runs
before rate limiting"]
F2["[decision] Use Zod
for validation"]
end
subgraph "Project B"
F3["[pattern] JWT refresh
token rotation"]
end
subgraph "Fragments"
FR1(("auth-flow"))
FR2(("input-validation"))
end
F1 -->|mentions| FR1
F3 -->|implements| FR1
F2 -->|mentions| FR2
style FR1 fill:#2a1a3e,stroke:#9B8DC8,color:#E8E4D9
style FR2 fill:#2a1a3e,stroke:#9B8DC8,color:#E8E4D9
style F1 fill:#1a1a3e,stroke:#FF8A90,color:#E8E4D9
style F2 fill:#1a1a3e,stroke:#00E5FF,color:#E8E4D9
style F3 fill:#1a1a3e,stroke:#00E5FF,color:#E8E4D9
Use cross_project_fragments() to discover which fragments span multiple projects — these often reveal shared dependencies or recurring pitfalls.
Session Continuity #
Sessions track continuity across agent restarts. When a session starts, phren provides the prior summary, recent findings, the active task, and pending review items.
sequenceDiagram
participant Agent
participant Phren
participant Files as ~/.phren
Agent->>Phren: session_start("my-app")
Phren->>Files: Read last session summary
Phren->>Files: Read recent findings
Phren->>Files: Read task checkpoints
Phren-->>Agent: Summary + findings + active task + hints
Note over Agent,Phren: Agent works...
Agent->>Phren: add_finding(...)
Agent->>Phren: complete_task(...)
Agent->>Phren: session_end("Implemented rate limiting")
Phren->>Files: Write session summary
Phren->>Files: Save task checkpoints
Task Checkpoints
Checkpoints record the state of in-progress work so agents can resume seamlessly. Each captures the task ID, edited files, failing tests, and next-step hints. Stored in .sessions/ and cleared on task completion.
Configuration
Environment variables, governance files, retention policy, workflow gates, proactivity, hooks, and feature flags.
Environment Variables #
phren reads environment variables for runtime behavior. Set them in your shell profile or ~/.phren/.env.
Core
| Variable | Default | Description |
|---|---|---|
PHREN_CONTEXT_TOKEN_BUDGET | 550 | Max tokens injected per hook-prompt call (180--10000) |
PHREN_CONTEXT_SNIPPET_LINES | 6 | Max lines per snippet (2--100) |
PHREN_CONTEXT_SNIPPET_CHARS | 520 | Max characters per snippet (120--10000) |
PHREN_MAX_INJECT_TOKENS | 2000 | Hard cap on total injected tokens (200--20000) |
PHREN_TASK_PRIORITY | high,medium | Priorities to include in hook context injection |
PHREN_MEMORY_TTL_DAYS | policy | Override memory TTL for trust filtering |
Semantic / Embedding
| Variable | Default | Description |
|---|---|---|
PHREN_OLLAMA_URL | http://localhost:11434 | Ollama base URL. Set to off to disable. |
PHREN_EMBEDDING_MODEL | nomic-embed-text | Embedding model for Ollama or API |
PHREN_EMBEDDING_API_URL | — | OpenAI-compatible embeddings endpoint |
PHREN_FEATURE_SEMANTIC_DEDUP | disabled | LLM-based semantic deduplication on add_finding |
PHREN_FEATURE_SEMANTIC_CONFLICT | disabled | LLM-based conflict detection on add_finding |
PHREN_LLM_MODEL | gpt-4o-mini | LLM model for dedup/conflict detection |
Feature Flags
| Variable | Default | Description |
|---|---|---|
PHREN_FEATURE_AUTO_EXTRACT | enabled | Auto memory extraction from project context on each prompt |
PHREN_FEATURE_AUTO_CAPTURE | disabled | Extract insights from transcripts at session end |
PHREN_FEATURE_GIT_CONTEXT_FILTER | disabled | Git-context file relevance filtering in search |
PHREN_FEATURE_PROGRESSIVE_DISCLOSURE | disabled | Compact memory index instead of full snippets |
PHREN_FEATURE_HYBRID_SEARCH | enabled | TF-IDF cosine fallback in search_knowledge |
Governance Files #
Policy is configured via JSON files in ~/.phren/.governance/. Use phren config subcommands to read and write these safely.
phren config policy get
phren config policy set memoryTTLDays=90 decayMultiplier=0.8
phren config workflow set taskMode=auto findingSensitivity=high
Hook Configuration #
Four built-in hooks fire automatically for Claude Code:
| Hook | When | What it does |
|---|---|---|
SessionStart | Session opens | git pull, project context injection |
UserPromptSubmit | Every prompt | FTS5 search, context injection, consolidation check |
PostToolUse | After tool calls | Queues review candidates and captures tool-level continuity hints |
Stop | After response | Auto-commit and push ~/.phren changes |
Manage hooks:
phren hooks list
phren hooks enable claude
phren hooks disable codex
phren hooks add-custom Stop "curl -s http://localhost:9090/notify"
Proactivity #
Controls how aggressively phren captures findings and tasks:
| Level | Behavior |
|---|---|
high | Always auto-capture findings and tasks |
medium | Capture only on explicit signals |
low | Fully manual — agent never captures on its own |
off | Passive MCP server only |
phren config workflow set proactivity=medium
CLI Reference
All phren CLI commands, organized by category. Run phren --help for a quick summary.
General #
Search #
$ phren search "authentication middleware"
[my-app] [pitfall] Auth middleware runs before rate limiting (0.92)
[backend] [decision] Use passport.js for all auth flows (0.87)
Tasks #
Findings #
truths.md. Always injected, never decays.Projects #
Skills #
Hooks #
Config #
Teams & Stores #
Maintenance #
Run prune and consolidate with --dry-run first.
MCP Tools
All 53 tools exposed by the phren MCP server. Every tool returns { ok, message, data?, error? }.
Search & Browse 10 tools #
search_knowledgeFTS5 search with synonym expansion
get_memory_detailFetch full content of a memory by id
get_project_summaryProject summary + file list
list_projectsAll projects in active profile
get_findingsRead recent findings without a search query
health_checkRun doctor checks and return health status including consolidation status
list_hook_errorsRecent hook errors
get_review_queueItems waiting for review
manage_review_itemApprove, reject, or edit a review queue item
doctor_fixRun doctor self-heal and apply fixes
Task Management 6 tools #
get_tasksRead tasks, or fetch a single item by ID/text
add_taskAdd one or more tasks to queue
complete_taskMove task(s) to done by text match
update_taskUpdate text, priority, context, section, pin, promote, work_next, or GitHub link
remove_taskRemove one or more tasks by matching text
tidy_done_tasksArchive completed tasks
Finding Capture 9 tools #
add_findingAppend one or more findings
supersede_findingMark a finding as superseded
retract_findingRetract with lifecycle reason
resolve_contradictionResolve contradiction between two findings
get_contradictionsList unresolved contradictions
edit_findingEdit in place preserving metadata
remove_findingRemove one or more findings by match
push_changesCommit and push phren changes
auto_extract_findingsExtract findings from text
Memory Quality 2 tools #
pin_memoryWrite canonical pinned memory entries
memory_feedbackRecord helpful/reprompt/regression outcomes
Data Management 4 tools #
add_projectBootstrap a directory into phren
export_projectExport project data as portable JSON
import_projectImport project from exported JSON
manage_projectArchive or restore a project
Fragment Graph 5 tools #
search_fragmentsFind fragments by name
get_related_docsDocs linked to a fragment
read_graphRead the fragment graph
link_findingsLink a finding to a fragment
cross_project_fragmentsFragments shared across projects
Session Management 4 tools #
session_startMark session start, returns context
session_endMark session end, save summary
session_contextCurrent session state
session_historyPast sessions or drill into one
Skills Management 5 tools #
list_skillsAll installed skills with metadata
read_skillFull skill file content + frontmatter
write_skillCreate or update a skill
remove_skillDelete a skill file
toggle_skillEnable or disable a skill
Hooks Management 4 tools #
list_hooksHook status for all tools + custom hooks
toggle_hooksEnable/disable hooks globally or per tool
add_custom_hookAdd a custom integration hook
remove_custom_hookRemove custom hooks by event/command
Configuration 2 tools #
get_configRead current governance config (all domains including topic)
set_configUpdate config for any domain
Store Management 1 tool #
store_listList registered stores and their sync status
Return Format #
{
"ok": true,
"message": "Found 3 results",
"data": { ... }
}
// On error:
{
"ok": false,
"error": "Project not found: foo"
}
Maintenance tools (phren config, phren maintain) are CLI-only and not exposed via MCP.
Skills Guide
Reusable instructions that agents invoke as slash commands. Write once, use everywhere.
What Are Skills #
A skill is a markdown file with YAML frontmatter that defines a reusable procedure. Type /skill-name in an agent session and the agent reads the skill file and follows its instructions.
- Portable — skills live in
~/.phrenand sync via git - Scoped — global skills apply everywhere; project skills override globals
- Versioned — full git history and rollback
- Agent-agnostic — any agent with MCP access can execute skills
Anatomy of a Skill #
---
name: deploy-staging
command: /deploy-staging
description: Deploy the current branch to staging
tags: [devops, deploy]
---
# Deploy to Staging
1. Run the test suite: `npm test`
2. Build the production bundle: `npm run build`
3. Deploy to staging: `./scripts/deploy.sh staging`
4. Verify the deployment at https://staging.example.com
5. Report the deployment status.
Frontmatter Format
| Field | Required | Description |
|---|---|---|
name | Yes | Unique identifier for the skill |
command | No | Slash command (defaults to /name) |
description | No | One-line description |
tags | No | Array of tags for categorization |
aliases | No | Alternative command names |
Global vs Project Skills #
Project always wins. Global skills live in ~/.phren/global/skills/. Project skills live in ~/.phren/<project>/skills/.
Resolution Order #
- Project skills —
~/.phren/<project>/skills/ - Global skills —
~/.phren/global/skills/
If a project skill has the same name as a global skill, the project skill wins.
Built-in Skills #
| Command | What it does |
|---|---|
/phren-sync | Pull/push ~/.phren across machines |
/phren-init | Scaffold a new project |
/phren-discover | Research gaps and opportunities |
/phren-consolidate | Find patterns across FINDINGS.md files |
Managing Skills #
phren skills list # List all
phren skills add my-project ./skill.md # Add to project
phren skills show deploy --project my-project # View content
phren skills resolve my-project # Print manifest
phren skills doctor my-project # Diagnose visibility
phren skills enable my-project deploy # Re-enable
phren skills disable my-project deploy # Disable
phren skills remove my-project deploy # Delete
Interactive Shell
A terminal UI for browsing and managing your entire project store. Launch with phren or phren shell.
Views #
The shell has eight views. Switch between them with single-key shortcuts or the : palette.
Projects p
The landing screen. Dashboard showing profile-wide counts for projects, tasks, findings, and sync state. All indexed projects listed with per-project workload counts.
Tasks b
Shows tasks.md parsed into Active, Queue, and Done sections. Use :work next to promote, :complete <id> to mark done, :tidy to archive.
Findings l
Lists entries from FINDINGS.md with dates, citations, and lifecycle states.
Review Queue m
Pending review items from review.md. Read-only for inspection.
Skills s
Global and project-local skills. Press t to toggle enabled/disabled.
Hooks k
Lifecycle hook status and custom hook configuration.
Health h
Doctor checks alongside runtime health data. Offers :run fix, :relink, :rerun hooks.
Keybindings #
Palette Commands #
| Command | Description |
|---|---|
:open <project> | Set active project context |
:add <task> | Add a task to Queue |
:complete <id> | Mark a task done |
:work next | Promote top Queue item to Active |
:tidy [keep] | Archive Done items |
:find add <text> | Add a finding |
:find remove <id> | Remove a finding |
:run fix | Run doctor --fix |
:help | Full keyboard map |
State Persistence #
The shell saves state to .runtime/shell-state.json: selected project, active filter, page, and rows per page. Use :reset to clear.
VS Code Extension
Browse, search, and manage phren knowledge directly from VS Code.
Overview #
- Activity bar tree view of projects, findings, tasks, skills, hooks, sessions
- Full-text search via quick pick (Ctrl+Shift+K)
- Interactive fragment graph webview
- Inline finding capture from editor selections
- Task management from the tree view
- Session overview panels
Installation #
npm install -g @phren/cli
phren init
# From marketplace
ext install alaarab.phren-vscode
# Or build from source
cd ~/phren/vscode-extension
npm install && npm run compile
VS Code's Electron binary cannot run the MCP server. Set phren.nodePath to your system Node.js path (e.g. /usr/bin/node).
Tree View #
The activity bar icon opens a hierarchical view: Projects, Findings, Tasks, Skills, Hooks, Sessions, and Review Queue. Title bar buttons provide Search, Graph, Refresh, and Sync.
Search #
Press Ctrl+Shift+K to search across all indexed content. Also available from the command palette: Phren: Search Knowledge.
Findings #
Capture findings from editor selections (right-click), the command palette, or the tree view. Right-click findings for lifecycle actions: remove, supersede, retract, resolve contradictions.
Tasks #
Add, complete, update, pin, and remove tasks from the tree view. Right-click for GitHub integration: link issues or create new ones from tasks.
Settings #
| Setting | Default | Description |
|---|---|---|
phren.mcpServerPath | auto-detect | Path to phren MCP server index.js |
phren.nodePath | node | Path to Node.js binary (must be real node, not Electron) |
phren.findingSensitivity | balanced | Capture aggressiveness: minimal, conservative, balanced, aggressive |
phren.proactivity | high | Global proactivity: high, medium, low |
phren.taskMode | auto | Task mode: off, manual, suggest, auto |
phren.hooksEnabled | true | Master switch for phren hooks |
All Commands #
All commands accessible via Ctrl+Shift+P by typing "Phren":
| Command | Description |
|---|---|
Phren: Search Knowledge | FTS5 search quick pick |
Phren: Show Fragment Graph | Interactive graph webview |
Phren: Add Finding | Capture a new finding |
Phren: Add Task | Add a task to queue |
Phren: Complete Task | Mark a task done |
Phren: Sync | Commit and push changes |
Phren: Doctor | Run health checks |
Phren: Toggle Hooks | Global hooks enable/disable |
Phren: Set Active Project | Switch project context |
Phren: Project Config | Per-project configuration panel |
Architecture
Data flow, retrieval pipeline, governance, persistence, hook lifecycle, and MCP integration.
System Overview #
phren operates on three paths during every prompt cycle:
- Retrieval — keyword extraction, synonym expansion, FTS5 search, snippet injection
- Governance — citation validity, confidence decay, policy thresholds
- Persistence — MCP writes + Stop hook git commit/push
flowchart TB
subgraph "Agent Session"
A["User Prompt"] --> B["SessionStart Hook"]
B --> C["git pull ~/.phren"]
C --> D["UserPromptSubmit Hook"]
D --> E["Keyword Extraction"]
E --> F["FTS5 Search + Synonyms"]
F --> G["Trust Scoring"]
G --> H["Context Injection"]
end
subgraph "MCP Tools"
I["add_finding"] --> J["~/.phren/project/FINDINGS.md"]
K["add_task"] --> L["~/.phren/project/tasks.md"]
M["search_knowledge"] --> N["FTS5 Index"]
end
subgraph "Persistence"
O["Stop Hook"] --> P["git add + commit"]
P --> Q["git push"]
end
H --> I
H --> K
H --> M
J --> O
L --> O
style A fill:#1a1a3e,stroke:#00E5FF,color:#E8E4D9
style D fill:#1a1a3e,stroke:#9B8DC8,color:#E8E4D9
style H fill:#1a1a3e,stroke:#28C840,color:#E8E4D9
style O fill:#1a1a3e,stroke:#FFBD2E,color:#E8E4D9
Retrieval Pipeline #
On every UserPromptSubmit, phren extracts keywords from the user's prompt, expands them with learned synonyms, and runs an FTS5 query across all indexed content. Results are trust-scored, filtered by confidence thresholds, and injected into the agent's context window within the configured token budget.
Search ranking factors
- FTS5 relevance score (BM25)
- Age-based confidence decay
- Citation validity (valid = boost, missing = 0.8x penalty)
- Finding lifecycle state (active = 1.0x, superseded = 0.25x, retracted = 0.1x)
- Low-value pattern filtering
- Git context boost (when enabled)
Governance #
Governance ensures memory quality through policy-driven checks:
- Retention policy — TTLs, decay multipliers, prune thresholds
- Workflow policy — approval gates for risky operations, finding sensitivity
- Access control — RBAC via
PHREN_ACTORand access-control files - Audit log — all mutations logged to
.runtime/audit.log
Hook Lifecycle #
sequenceDiagram
participant Agent
participant Hooks
participant Phren as ~/.phren
participant Git
Agent->>Hooks: SessionStart
Hooks->>Git: git pull
Hooks->>Agent: Project context
Agent->>Hooks: UserPromptSubmit (every prompt)
Hooks->>Phren: Extract keywords
Hooks->>Phren: FTS5 search
Hooks->>Agent: Inject context (token-budgeted)
Note over Agent: Agent responds, calls MCP tools
Agent->>Hooks: Stop (after every response)
Hooks->>Git: git add + commit + push
Directory Structure #
| Path | Contents |
|---|---|
~/.phren/ | Root store (git repo) |
~/.phren/global/ | Global skills, CLAUDE.md, FINDINGS.md |
~/.phren/<project>/ | Per-project CLAUDE.md, FINDINGS.md, tasks.md, summary.md, skills/ |
~/.phren/profiles/ | YAML files mapping project sets to profiles |
~/.phren/machines.yaml | Machine-to-profile mapping |
~/.phren/.governance/ | Policy JSON, access control, install preferences |
~/.phren/.runtime/ | Audit log, debug log, telemetry, search history, locks |
~/.phren/.sessions/ | Session markers, extraction markers |
FTS5 Indexing #
phren builds an in-memory FTS5 index on startup from all markdown files in the store. Key behaviors:
@import shared/file.mdresolves toglobal/dir, with cycle detection and depth capreference/subdirectories classified as reference type- Task Done sections stripped to reduce noise
- Archived findings (inside
<details>blocks) stripped from index - Configurable include/exclude globs via
phren config index
Key Patterns #
- Starter bundled in npm package, not a separate repo
- Path traversal prevention via
isValidProjectName+safeProjectPath - Init is idempotent: re-running updates MCP + hooks without clobbering data
- Node resolved-path in hooks (not npx) avoids cold-start timeout
- Hook detection uses path segments (not substring) to avoid false positives
- Stop hook fires after every response including subagents
- File locking prevents concurrent writes to FINDINGS.md and tasks.md
Contributing
How to set up, build, test, and submit changes to phren.
Dev Setup #
Clone, build, and test in under a minute.
git clone https://github.com/alaarab/phren.git
cd phren
npm install
npm run build
npm test
The build compiles TypeScript from mcp/src/ into mcp/dist/ and marks the entry point executable.
Prerequisites
- Node.js 20+
- npm 9+
Project Structure #
Key files and what they do.
| Path | What it does |
|---|---|
mcp/src/index.ts | CLI routing + MCP server bootstrap (53 public tools across 12 modules) |
mcp/src/shared.ts | Shared path/runtime helpers and core exports |
mcp/src/cli.ts | CLI subcommands (search, doctor, shell, etc.) |
mcp/src/utils.ts | FTS5 sanitization, synonym expansion, keyword extraction |
mcp/src/init.ts | phren init: configures MCP + hooks |
mcp/src/link.ts | Profile sync, symlinks, hooks, context |
mcp/src/data-access.ts | Task CRUD, machine/profile listing, learning management |
mcp/src/mcp-*.ts | MCP tool modules (search/tasks/finding/memory/data/graph/session/ops/skills/hooks/extract/config) |
mcp/src/skill-registry.ts | Skill precedence, alias collision handling, visibility gating |
mcp/src/governance-policy.ts | RBAC, policy files, actor resolution |
mcp/src/memory-ui-server.ts | Web UI server, auth/CSRF/CSP/loopback security |
mcp/src/telemetry.ts | Opt-in local telemetry collection and summaries |
starter/ | Template files copied to ~/.phren on init |
docs/ | GitHub Pages site and documentation |
skills/ | Phren slash command definitions |
Testing #
Running the test suite and filtering by pattern.
npm test # run all tests
npm test -- --grep "pattern" # filter by test name
npm test -- mcp/src/data-access.test # run one file
npx vitest --watch # watch mode
Test files live as *.test.ts in mcp/src/. When adding a new feature, add tests in the same directory as the source file.
Code Style #
Read CLAUDE.md for the full set of conventions. The highlights:
AI voice: "robust", "seamless", "leverage", "comprehensive"
Write like a person. Be direct.
Em dashes, filler comments, over-documentation
Colons, commas, or just rewrite the sentence. Comment only where logic is not self-evident.
Premature abstractions for one-time operations
Three similar lines beat a premature helper function
Making Changes #
- Create a feature branch from
main - Make your changes with tests
- Run
npm run build && npm testand make sure everything passes - Keep commits focused: one logical change per commit
- Write commit messages that explain why, not just what
Pull Requests #
Keep PRs small and focused. One feature or fix per PR.
- Include a short description of what changed and why
- If your PR changes user-facing behavior, update the README
- If your PR adds or changes MCP tools, update
docs/api-reference.md,docs/llms-install.md, anddocs/llms-full.txt - If your PR changes finding lifecycle, session checkpoints, web-ui security, RBAC, or telemetry, update the matching docs in the same PR
- Make sure CI passes before requesting review
Commit Conventions
Use conventional commits.
feat: add synonym expansion for search queries
fix: FTS5 sanitizer stripping valid URLs
docs: update API reference with bulk tools
test: add coverage for session checkpoint edge cases
refactor: extract keyword logic from hook-prompt
Prefixes: feat:, fix:, docs:, test:, refactor:
Adding a New MCP Tool #
Five steps to ship a new tool.
- Add the tool definition in the correct module (
mcp/src/mcp-<domain>.ts) following the existingserver.registerTool()pattern - Implement the handler: call data-access functions, return
{ ok, message, data } - Register or verify the module from
mcp/src/index.tsif you created a new module - Add tests in the relevant
*.test.tsfile - Update docs:
docs/api-reference.md,docs/llms-install.md,docs/llms-full.txt, and integration/security/governance docs when behavior affects hooks, skills, RBAC, web UI, or telemetry
Adding a Global Skill
- Create a markdown file in
global/skills/your-skill.md - Follow the existing skill format: name, description, steps
- Test locally by running
phren initand invoking/your-skillin a Claude Code session
Reporting Bugs
Open an issue with:
- What you expected to happen
- What actually happened
- Steps to reproduce
- Your Node.js version and OS
Open a discussion or issue.
Security
Phren is local-first. Your data never leaves your machine unless you push it.
All data lives in ~/.phren as plain markdown and JSON files. No external database, no cloud sync by default.
Phren never stores API keys, tokens, or passwords. All credentials come from environment variables at runtime.
All file operations validate project names and paths to prevent directory traversal attacks.
Search queries are sanitized to prevent FTS5 injection. Known column prefixes are stripped, URLs preserved.
Data Storage #
Phren stores all state as local files under ~/.phren (shared mode) or <repo>/.phren (project-local mode). The data is:
- Plain text: markdown files for findings, tasks, summaries, and skills
- Structured JSON: governance policies, session data, runtime state
- Git-backed: changes are committed locally and optionally pushed to a remote you control
Phren works entirely offline. Git push is optional and goes to your own remote.
Credential Handling
Phren reads credentials exclusively from environment variables. It never writes secrets to disk.
| Variable | Purpose |
|---|---|
PHREN_EMBEDDING_API_KEY | Bearer token for external embedding endpoint |
PHREN_LLM_KEY | API key for semantic dedup/conflict LLM |
OPENAI_API_KEY | Fallback for embedding and LLM calls |
ANTHROPIC_API_KEY | Fallback for LLM calls (Claude models) |
GITHUB_TOKEN | Used by phren maintain extract for GitHub API |
Secret Scanning
The finding quality filter rejects entries that match common secret patterns:
- API keys and tokens (common prefixes like
sk-,ghp_,Bearer) - Connection strings with embedded credentials
- PII patterns (emails, phone numbers in certain formats)
Secret scanning is a heuristic filter, not a guarantee. Do not rely on it as your only protection. Use .gitignore and environment variables.
Access Control #
RBAC and authentication for shared environments and the web UI.
Role-Based Access Control
Identity is resolved from PHREN_ACTOR (in trusted/test contexts) or the OS user identity.
| Role | Permissions |
|---|---|
admin | Full access: read, write, delete, policy changes |
maintainer | Read, write, delete. No policy changes. |
contributor | Read and write. No delete or policy changes. |
viewer | Read only |
All write, policy, and delete operations are checked against RBAC before mutation. Unauthorized attempts are logged in .runtime/audit.log.
Web UI Security
The memory web UI (phren web-ui) applies layered security:
- Loopback binding: listens only on
127.0.0.1, not on network interfaces - Auth token: random per-run token required for all requests
- CSRF protection: mutating routes require a single-use CSRF token with TTL
- Security headers:
Content-Security-Policy,X-Frame-Options: DENY,X-Content-Type-Options: nosniff
Network Activity #
Phren makes no network calls by default. All external calls are opt-in.
| Feature | Network call | Controlled by |
|---|---|---|
| Core operation | None | Always local |
| Git sync | git push/pull to your remote | Stop hook (only if remote configured) |
| Embeddings (Ollama) | localhost:11434 | PHREN_OLLAMA_URL |
| Embeddings (API) | Your configured endpoint | PHREN_EMBEDDING_API_URL |
| Semantic dedup/conflict | Your configured LLM endpoint | PHREN_LLM_ENDPOINT |
| GitHub extraction | api.github.com | phren maintain extract (manual) |
Auto-Extract Privacy
When PHREN_FEATURE_AUTO_EXTRACT is enabled, phren extracts insights from project context on each prompt. The extraction:
- Runs entirely locally using the configured model
- Respects a per-session cooldown (
PHREN_AUTOCAPTURE_COOLDOWN_MS, default 30s) - Caps findings per session (
PHREN_AUTOCAPTURE_SESSION_CAP, default 10) - Applies the same quality filter that rejects secrets and PII
- Tags extracted findings with
source: extractprovenance for auditability
Telemetry
Opt-in, local-only usage tracking. Disabled by default. Enable with phren config telemetry on. Data is stored in .runtime/telemetry.json and never sent anywhere.
Reporting a Vulnerability #
If you find a security issue, report it privately. Do not open a public issue.
Include: a description of the vulnerability, steps to reproduce, the impact, and your suggested fix.
What Counts as a Security Issue
- Path traversal: reading or writing files outside the phren directory
- Arbitrary code execution through MCP tool inputs
- Information disclosure: leaking data from other projects or profiles
- Injection attacks through FTS5 queries or CLI arguments
- Bypass of memory access controls or role-based permissions
Response Timeline
| Stage | Timeline |
|---|---|
| Acknowledgment | Within 48 hours |
| Initial assessment | Within 1 week |
| Fix or mitigation | 30 days for critical issues |
Security fixes are applied to the latest release only. We follow coordinated disclosure and credit reporters in the changelog unless they prefer anonymity.
Frequently Asked Questions
Common questions about phren, answered.
How is this different from just using CLAUDE.md? #
CLAUDE.md loads the entire file on every prompt. If your file is 2,000 tokens, you pay 2,000 tokens every single time, whether the content is relevant or not. With five agents running in parallel, that is 10,000 tokens of context before anyone types a word.
Phren searches what you wrote and injects only what matches the current prompt. By default it targets roughly 550 tokens with PHREN_CONTEXT_TOKEN_BUDGET, regardless of how large your knowledge base grows.
CLAUDE.md is also static. Phren learns as you work. Every bug traced, every decision made, every pattern discovered gets saved automatically. The next session starts with that knowledge already in context.
Does this slow down my prompts? #
Usually not on a warm local repo. The hook runs locally: keyword extraction, FTS5 search, and context injection all happen against a local SQLite index with no network calls in the default path.
The main exceptions are the first prompt in a session (where SessionStart pulls the repo from git) and very large or slow filesystems. On a fast connection the pull is often under a second.
What happens when I run multiple agents at the same time? #
They all read and write the same ~/.phren directory. Concurrent reads are safe. Writes are serialized within a process by file locks; cross-process synchronization happens at the git layer.
In practice: an agent on Codex hits a pitfall and saves a finding. On the next git pull cycle, a Claude Code session on a different machine has it in context. No coordination code, no message passing, just a shared git repo.
What failure modes should I expect? #
- No remote configured: auto-save still commits locally, but nothing syncs across machines until you add a remote.
- Push failed: the commit stays local and phren records the error so
phren statuscan show it. - Hooks disabled or stale: retrieval stops, but your files are still there; rerun
phren init. - Stale index: search quality drops until the next rebuild;
phren doctorwill flag index trouble. - Governance lockout: if access control blocks a write, nothing is silently discarded; check
.governance/access-control.json.
How does trust decay work? #
Every finding has a confidence score. The score degrades over time:
| Age | Cited entry | Uncited entry |
|---|---|---|
| 0-30 days | 1.00 | 0.80 |
| 31-60 days | 1.00 | 0.80 |
| 61-90 days | 0.85 | 0.68 |
| 91-120 days | 0.65 | 0.52 |
| 120+ days | 0.45 | 0.36 |
Entries below 0.35 are suppressed and move to the review queue. You can pin a truth with pin_memory to make it never decay.
What gets saved automatically vs manually? #
Automatic
- Findings added via
add_findingMCP tool - Task items via
add_task - Session state committed and pushed by the Stop hook after every response
Manual
- Running
/phren-consolidatewhen findings pile up - Running
phren maintain governto queue low-value entries for review - Pinning findings that should never decay
How do I add a new project? #
cd ~/code/my-project
phren add
Phren bootstraps ~/.phren/my-project/ and adds it to your active profile. For a brand-new scaffold: /phren-init my-project
Does phren require MCP? #
No. MCP is recommended for the full 51-tool experience, but phren also works in hooks-only mode where context injection still happens automatically via the prompt hook.
phren init --mcp off # Install without MCP
phren mcp-mode on # Toggle anytime
Which agents are supported? #
Claude Code, GitHub Copilot CLI, Cursor, VS Code Copilot, and OpenAI Codex. Claude gets full native lifecycle hooks plus MCP. The others get generated hook configs plus session wrappers.
Platforms #
Linux is the primary validation path. macOS and Windows are supported, with explicit config-path handling for their user-home layouts.
Web UI #
phren web-ui
Opens a browser-based interface at localhost:3499. The review queue is read-only there. Filter by machine, model, and project. Loopback-only bind, random per-run auth token, CSRF protection, and CSP headers.
Telemetry #
No, telemetry is not on by default. It is opt-in and local-only. phren config telemetry on
Uninstall #
phren uninstall removes the active install. Shared mode removes config, hooks, and the active phren root. Project-local mode removes <repo>/.phren and workspace MCP entry. Export or back up before uninstalling.
Sharing & Teams
Sync phren knowledge across machines, manage access with RBAC, and collaborate across projects.
Profiles #
A profile defines which projects a machine should have access to. Profiles live as YAML files in ~/.phren/profiles/.
# ~/.phren/profiles/work.yaml
name: work
projects:
- global
- web-app
- api-server
- shared-lib
Each profile lists the project directories that should be synced and linked. The global entry is special: it contains skills and config that apply everywhere.
phren config profiles # List all profiles
:profile add-project work my-new-project # Add a project
:profile remove-project work old-project # Remove a project
Machines #
The machines.yaml file maps hostnames to profiles. When phren init runs on a new machine, it reads the current hostname, applies the mapped profile, and refreshes local integration config.
# ~/.phren/machines.yaml
work-desktop: work
home-laptop: personal
ci-server: minimal
Syncing via Git #
The ~/.phren directory is a git repository. Syncing is plain git, automated through hooks:
- The SessionStart hook runs
git pullon~/.phrenat the beginning of every session - The Stop hook auto-commits and pushes
~/.phrenchanges after every response
Findings, tasks, and skills sync automatically as you work. Use profiles plus machines.yaml to scope which projects are active on each machine, then run phren init after profile changes to refresh local config.
Machine Setup
phren init wires everything together on a machine. It detects the current install mode, configures MCP settings for supported agents, registers lifecycle hooks, applies machine/profile defaults, and refreshes generated assets.
Consolidation #
As findings accumulate, phren detects when they need consolidation. Thresholds: 25 entries since last consolidation marker, or 60 days + 10 entries. Consolidation archives old entries, deduplicates, and promotes patterns that appear in 2+ projects to global scope.
phren consolidation-status
phren maintain consolidate my-project
Fragment Graph
Fragments are named concepts that connect findings across projects. Use cross_project_fragments to find fragments shared across multiple projects.
phren graph
phren graph link web-app "Turbo builds avoid dist races" "build-system"
Cross-Project Search
The search_knowledge MCP tool searches across all indexed projects by default. Cross-project findings from global/FINDINGS.md are included in all searches.
RBAC Roles #
Phren supports four role levels. The actor is identified by PHREN_ACTOR (defaults to $USER).
| Role | Permissions |
|---|---|
admin | Full access. Can modify governance, access control, workflow policies, and all project data. |
maintainer | Can add/edit/remove findings, tasks, and skills. Cannot modify governance or access control. |
contributor | Can add findings and tasks. Cannot remove or edit existing entries. |
viewer | Read-only access. |
Access control is configured in ~/.phren/.governance/access-control.json. If no file exists, all users have full access.
Audit Log
All mutations are recorded in ~/.phren/.runtime/audit.log. Each entry includes the actor, action, timestamp, and relevant parameters.
Team Workflows #
For teams sharing a phren repository:
- Create a shared git remote for
~/.phren - Define profiles per team role (e.g.
frontend.yaml,backend.yaml) - Register each machine in
machines.yaml, then runphren init - Set up RBAC so team leads are admins, developers are maintainers or contributors
Example: Two-Person Team
# Alice's laptop
phren init # machine: alice-mbp, profile: fullstack
# Bob's desktop
git clone <phren-remote> ~/.phren
phren init # machine: bob-desktop, profile: fullstack
# Both work independently; Stop hook syncs after each response
# Weekly: run /phren-consolidate to merge insights
Team Stores #
A team store is a shared git repository structured like a phren store. Each team member clones it locally, and phren routes reads and writes automatically based on project claims in the store registry.
Your primary store (~/.phren) remains private. Team stores are separate repositories that sit alongside it. Findings only reach a team store when a project is explicitly claimed by that store.
How It Works
Phren maintains a store registry at ~/.phren/stores.yaml that lists every store the user has access to. Each store has a role:
| Role | Read | Write | Git Sync | Use Case |
|---|---|---|---|---|
primary | Yes | Yes | Full | Your personal store (default write target) |
team | Yes | Yes | Full | Shared team store |
readonly | Yes | No | Pull only | Reference store (company-wide knowledge) |
CLI Commands
.phren-team.yaml bootstrap file and registers it locally..phren-team.yaml, and adds it to your store registry.Write Routing
When you add a finding or task, phren resolves which store receives the write:
- If store-qualified (e.g.
arc-team/arc) — use the explicit store - If a team store claims the project in its registry — route to that store
- Otherwise — default to the primary (personal) store
# Finding goes to arc-team store (project claimed)
phren add-finding arc "Always validate JWT expiry"
# Explicit store target
phren add-finding arc-team/arc "Always validate JWT expiry"
# Unclaimed project → personal store
phren add-finding my-side-project "Use pnpm for this one"
Git Sync
Sync happens automatically at session boundaries:
- Session start:
git pullon all stores (team, readonly, primary) - Stop hook: for each writable store,
git add+commit+push
Team stores use an append-only journal format (journal/YYYY-MM-DD-actor.md) to avoid merge conflicts. Each team member writes to their own file, so concurrent pushes merge cleanly.
Example: Setting Up a Team
# Alice creates the team store
phren team init arc-team --remote git@github.com:qualus/phren-arc.git
phren team add-project arc-team arc
phren team add-project arc-team arc-api
# Bob joins
phren team join git@github.com:qualus/phren-arc.git
# Both now share findings for arc and arc-api
# Personal findings for other projects stay in ~/.phren
Project Ownership
| Mode | Behavior |
|---|---|
phren-managed | Default. phren symlinks CLAUDE.md, FINDINGS.md, skills into the project directory. |
repo-owned | The project's repo owns its own CLAUDE.md. phren stores findings and tasks but does not symlink. |
read-only | phren indexes and searches the project but does not write to it. |