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.

01
Install

phren is published as @phren/cli on npm. Install it globally:

npm install -g @phren/cli
Requires

Node.js 20 or later. Check with node --version.

02
Initialize

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.

03
Add a Project

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 instructions
  • FINDINGS.md — captured insights and patterns
  • tasks.md — task queue (active, queued, done)
  • summary.md — project summary for context injection
04
Start Working

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
05
Verify

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:

  1. Retrieval — keyword extraction from your prompt, synonym expansion, FTS5 search, and snippet injection into agent context.
  2. Governance — citation validity checks, confidence decay, policy thresholds to filter low-quality memories.
  3. 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 injection
  • UserPromptSubmit — search + inject relevant context on every prompt
  • PostToolUse — queue review candidates and capture follow-up context after tool calls
  • Stop — 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 writes
  • archived — 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"
Warning

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.

Tip

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] [pattern] [pitfall] [observation] [tradeoff] [architecture] [bug]

[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
    }
        
StateRetrieval ScoreIn FTS Index?
active1.0xYes
contradicted0.4xYes
superseded0.25xNo
retracted0.1xNo
staleConfidence-basedYes
invalid_citation0.5xYes

Trust & Decay #

Every finding starts with full confidence (1.0). As it ages, confidence decays through a stepped schedule:

AgeMultiplierEffect
0 -- 30 days1.0Full confidence
30 -- 60 days0.9Slightly reduced
60 -- 90 days0.75Moderate reduction
90 -- 120 days0.5Low confidence
120+ dayssuppressedExcluded from retrieval
Confidence Days 1.0 0.75 0.50 0.25 0.0 0 30 60 90 120+ 0.8x citation penalty Default decay Confirmed (3x slower) [decision] (never decays)

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

VariableDefaultDescription
PHREN_CONTEXT_TOKEN_BUDGET550Max tokens injected per hook-prompt call (180--10000)
PHREN_CONTEXT_SNIPPET_LINES6Max lines per snippet (2--100)
PHREN_CONTEXT_SNIPPET_CHARS520Max characters per snippet (120--10000)
PHREN_MAX_INJECT_TOKENS2000Hard cap on total injected tokens (200--20000)
PHREN_TASK_PRIORITYhigh,mediumPriorities to include in hook context injection
PHREN_MEMORY_TTL_DAYSpolicyOverride memory TTL for trust filtering

Semantic / Embedding

VariableDefaultDescription
PHREN_OLLAMA_URLhttp://localhost:11434Ollama base URL. Set to off to disable.
PHREN_EMBEDDING_MODELnomic-embed-textEmbedding model for Ollama or API
PHREN_EMBEDDING_API_URLOpenAI-compatible embeddings endpoint
PHREN_FEATURE_SEMANTIC_DEDUPdisabledLLM-based semantic deduplication on add_finding
PHREN_FEATURE_SEMANTIC_CONFLICTdisabledLLM-based conflict detection on add_finding
PHREN_LLM_MODELgpt-4o-miniLLM model for dedup/conflict detection

Feature Flags

VariableDefaultDescription
PHREN_FEATURE_AUTO_EXTRACTenabledAuto memory extraction from project context on each prompt
PHREN_FEATURE_AUTO_CAPTUREdisabledExtract insights from transcripts at session end
PHREN_FEATURE_GIT_CONTEXT_FILTERdisabledGit-context file relevance filtering in search
PHREN_FEATURE_PROGRESSIVE_DISCLOSUREdisabledCompact memory index instead of full snippets
PHREN_FEATURE_HYBRID_SEARCHenabledTF-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:

HookWhenWhat it does
SessionStartSession opensgit pull, project context injection
UserPromptSubmitEvery promptFTS5 search, context injection, consolidation check
PostToolUseAfter tool callsQueues review candidates and captures tool-level continuity hints
StopAfter responseAuto-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:

LevelBehavior
highAlways auto-capture findings and tasks
mediumCapture only on explicit signals
lowFully manual — agent never captures on its own
offPassive 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 #

phren
Launch the interactive shell.
phren quickstart
Quick setup: runs init + scaffolds your first project in one step.
phren status
Health, project, and stats overview.
phren doctor [--fix] [--agents]
Health check and self-heal. Validates hooks, MCP config, project integrity.
phren verify
Post-init verification checks.
phren web-ui [--port=3499]
Launch the memory web UI.
phren search <query> [--project <n>]
FTS5 search with synonym expansion.
$ 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)
phren graph [--project <n>]
Show the fragment knowledge graph.

Tasks #

phren tasks
Cross-project task view. Shows all active and queued tasks.
phren task add <project> "..."
Add a task to a project's queue.
phren task complete <project> "..."
Complete a task by matching its text.
phren task next [project]
Pick the next highest-priority task.
phren task promote <project> "..." [--active]
Promote a task to a higher priority section.
phren task tidy [project] [--keep=<n>]
Archive completed tasks.
phren task create-issue <project> "..." [--repo <owner/name>]
Create a GitHub issue from a task and link it back.

Findings #

phren add-finding <project> "..."
Save an insight to a project's FINDINGS.md.
phren pin <project> "..."
Pin canonical memory to truths.md. Always injected, never decays.
phren finding supersede <project> "..." --by "..."
Mark a finding as superseded by a newer one (0.25x score).
phren finding retract <project> "..." --reason "..."
Retract a finding with a lifecycle reason (0.1x score).
phren finding contradictions [project]
List all unresolved contradicted findings.

Projects #

phren add [path] [--ownership <mode>]
Add current or specified directory as a project.
phren projects list
List all projects in the active profile.

Skills #

phren skills list
List all installed skills with metadata.
phren skills resolve <project|global>
Print the resolved skill manifest (effective skills after inheritance).

Hooks #

phren hooks list [--project <name>]
Show hook enable/disable status per tool.
phren hooks add-custom <event> <cmd>
Add a custom integration hook for a lifecycle event.

Config #

phren config policy [get|set ...]
Manage retention policy: TTL, confidence, decay settings.
phren config workflow [get|set ...]
Manage workflow: approval gates, risky thresholds.
phren config synonyms [list|add|remove] ...
Manage learned synonyms for search expansion.

Teams & Stores #

phren team init <name> [--remote <url>]
Create a new team store and register it locally.
phren team join <git-url> [--name <name>]
Join an existing team store by cloning its repo.
phren team add-project <store> <project>
Claim a project for a team store. Writes route there automatically.
phren team list
List team stores and their sync status.
phren store list
List all registered stores (personal, team, readonly).
phren store add <name> --remote <url>
Add a store by cloning a remote git repo.
phren store remove <name>
Remove a store from the local registry.
phren store sync
Pull all stores to get the latest changes.
phren store subscribe <name> <project...>
Subscribe to specific projects in a store. Unsubscribed projects won't appear in search or UI.
phren store unsubscribe <name> <project...>
Unsubscribe from projects in a store.

Maintenance #

Warning

Run prune and consolidate with --dry-run first.

phren maintain govern [project]
Queue stale memories for review based on retention policy.
phren maintain prune [project]
Delete expired entries that have passed their TTL.
phren maintain consolidate [project]
Deduplicate FINDINGS.md: archive old entries, write consolidation markers, promote cross-project patterns.
phren maintain extract [project]
Mine git and GitHub signals to extract memories automatically.

MCP Tools

All 53 tools exposed by the phren MCP server. Every tool returns { ok, message, data?, error? }.

search_knowledgeFTS5 search with synonym expansion
(query, type?, limit?, project?)
get_memory_detailFetch full content of a memory by id
(id)
get_project_summaryProject summary + file list
(name)
list_projectsAll projects in active profile
()
get_findingsRead recent findings without a search query
(project, limit?)
health_checkRun doctor checks and return health status including consolidation status
(include_consolidation?)
list_hook_errorsRecent hook errors
()
get_review_queueItems waiting for review
(project?)
manage_review_itemApprove, reject, or edit a review queue item
(project, line, action, new_text?)
doctor_fixRun doctor self-heal and apply fixes
()

Task Management 6 tools #

get_tasksRead tasks, or fetch a single item by ID/text
(project?, id?, item?)
add_taskAdd one or more tasks to queue
(project, item: string | string[])
complete_taskMove task(s) to done by text match
(project, item: string | string[])
update_taskUpdate text, priority, context, section, pin, promote, work_next, or GitHub link
(project, item?, updates)
remove_taskRemove one or more tasks by matching text
(project, item: string | string[])
tidy_done_tasksArchive completed tasks
(project?)

Finding Capture 9 tools #

add_findingAppend one or more findings
(project, finding: string | string[], citation?)
supersede_findingMark a finding as superseded
(project, finding_text, superseded_by)
retract_findingRetract with lifecycle reason
(project, finding_text, reason)
resolve_contradictionResolve contradiction between two findings
(project, finding_text, finding_text_other, resolution)
get_contradictionsList unresolved contradictions
(project?, finding_text?)
edit_findingEdit in place preserving metadata
(project, old_text, new_text)
remove_findingRemove one or more findings by match
(project, finding: string | string[])
push_changesCommit and push phren changes
(message?)
auto_extract_findingsExtract findings from text
(project, text, model?, dryRun?)

Memory Quality 2 tools #

pin_memoryWrite canonical pinned memory entries
(project, memory)
memory_feedbackRecord helpful/reprompt/regression outcomes
(key, feedback)

Data Management 4 tools #

add_projectBootstrap a directory into phren
(path, profile?)
export_projectExport project data as portable JSON
(project)
import_projectImport project from exported JSON
(data)
manage_projectArchive or restore a project
(project, action: "archive"|"unarchive")

Fragment Graph 5 tools #

search_fragmentsFind fragments by name
(name)
get_related_docsDocs linked to a fragment
(fragment)
read_graphRead the fragment graph
(project?)
link_findingsLink a finding to a fragment
(project, finding_text, fragment, relation?)
cross_project_fragmentsFragments shared across projects
()

Session Management 4 tools #

session_startMark session start, returns context
(project?)
session_endMark session end, save summary
(summary?)
session_contextCurrent session state
()
session_historyPast sessions or drill into one
(limit?, sessionId?, project?)

Skills Management 5 tools #

list_skillsAll installed skills with metadata
(project?)
read_skillFull skill file content + frontmatter
(name, project?)
write_skillCreate or update a skill
(name, content, scope)
remove_skillDelete a skill file
(name, project?)
toggle_skillEnable or disable a skill
(name, enabled, project)

Hooks Management 4 tools #

list_hooksHook status for all tools + custom hooks
(project?)
toggle_hooksEnable/disable hooks globally or per tool
(enabled, tool?, project?, event?)
add_custom_hookAdd a custom integration hook
(event, command, timeout?)
remove_custom_hookRemove custom hooks by event/command
(event, command?)

Configuration 2 tools #

get_configRead current governance config (all domains including topic)
(domain?, project?)
set_configUpdate config for any domain
(domain, settings, project?)

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 ~/.phren and 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

FieldRequiredDescription
nameYesUnique identifier for the skill
commandNoSlash command (defaults to /name)
descriptionNoOne-line description
tagsNoArray of tags for categorization
aliasesNoAlternative 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 #

  1. Project skills~/.phren/<project>/skills/
  2. Global skills~/.phren/global/skills/

If a project skill has the same name as a global skill, the project skill wins.

Built-in Skills #

CommandWhat it does
/phren-syncPull/push ~/.phren across machines
/phren-initScaffold a new project
/phren-discoverResearch gaps and opportunities
/phren-consolidateFind 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 #

p Projects
b Tasks
l Findings
m Review Queue
s Skills
k Hooks
h Health
q Quit
/ Filter
: Palette

Palette Commands #

CommandDescription
:open <project>Set active project context
:add <task>Add a task to Queue
:complete <id>Mark a task done
:work nextPromote top Queue item to Active
:tidy [keep]Archive Done items
:find add <text>Add a finding
:find remove <id>Remove a finding
:run fixRun doctor --fix
:helpFull 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
Important

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.

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 #

SettingDefaultDescription
phren.mcpServerPathauto-detectPath to phren MCP server index.js
phren.nodePathnodePath to Node.js binary (must be real node, not Electron)
phren.findingSensitivitybalancedCapture aggressiveness: minimal, conservative, balanced, aggressive
phren.proactivityhighGlobal proactivity: high, medium, low
phren.taskModeautoTask mode: off, manual, suggest, auto
phren.hooksEnabledtrueMaster switch for phren hooks

All Commands #

All commands accessible via Ctrl+Shift+P by typing "Phren":

CommandDescription
Phren: Search KnowledgeFTS5 search quick pick
Phren: Show Fragment GraphInteractive graph webview
Phren: Add FindingCapture a new finding
Phren: Add TaskAdd a task to queue
Phren: Complete TaskMark a task done
Phren: SyncCommit and push changes
Phren: DoctorRun health checks
Phren: Toggle HooksGlobal hooks enable/disable
Phren: Set Active ProjectSwitch project context
Phren: Project ConfigPer-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:

  1. Retrieval — keyword extraction, synonym expansion, FTS5 search, snippet injection
  2. Governance — citation validity, confidence decay, policy thresholds
  3. 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_ACTOR and 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 #

PathContents
~/.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.yamlMachine-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.md resolves to global/ dir, with cycle detection and depth cap
  • reference/ 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.

PathWhat it does
mcp/src/index.tsCLI routing + MCP server bootstrap (53 public tools across 12 modules)
mcp/src/shared.tsShared path/runtime helpers and core exports
mcp/src/cli.tsCLI subcommands (search, doctor, shell, etc.)
mcp/src/utils.tsFTS5 sanitization, synonym expansion, keyword extraction
mcp/src/init.tsphren init: configures MCP + hooks
mcp/src/link.tsProfile sync, symlinks, hooks, context
mcp/src/data-access.tsTask CRUD, machine/profile listing, learning management
mcp/src/mcp-*.tsMCP tool modules (search/tasks/finding/memory/data/graph/session/ops/skills/hooks/extract/config)
mcp/src/skill-registry.tsSkill precedence, alias collision handling, visibility gating
mcp/src/governance-policy.tsRBAC, policy files, actor resolution
mcp/src/memory-ui-server.tsWeb UI server, auth/CSRF/CSP/loopback security
mcp/src/telemetry.tsOpt-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:

Don't

AI voice: "robust", "seamless", "leverage", "comprehensive"

Do

Write like a person. Be direct.

Don't

Em dashes, filler comments, over-documentation

Do

Colons, commas, or just rewrite the sentence. Comment only where logic is not self-evident.

Don't

Premature abstractions for one-time operations

Do

Three similar lines beat a premature helper function

Making Changes #

  1. Create a feature branch from main
  2. Make your changes with tests
  3. Run npm run build && npm test and make sure everything passes
  4. Keep commits focused: one logical change per commit
  5. 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, and docs/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.

  1. Add the tool definition in the correct module (mcp/src/mcp-<domain>.ts) following the existing server.registerTool() pattern
  2. Implement the handler: call data-access functions, return { ok, message, data }
  3. Register or verify the module from mcp/src/index.ts if you created a new module
  4. Add tests in the relevant *.test.ts file
  5. 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

  1. Create a markdown file in global/skills/your-skill.md
  2. Follow the existing skill format: name, description, steps
  3. Test locally by running phren init and invoking /your-skill in 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
Questions?

Open a discussion or issue.

Security

Phren is local-first. Your data never leaves your machine unless you push it.

🔒
Local-First Storage

All data lives in ~/.phren as plain markdown and JSON files. No external database, no cloud sync by default.

🔑
No Credentials Stored

Phren never stores API keys, tokens, or passwords. All credentials come from environment variables at runtime.

🛡
Path Traversal Prevention

All file operations validate project names and paths to prevent directory traversal attacks.

🔍
FTS5 Input Sanitization

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
No cloud dependency

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.

VariablePurpose
PHREN_EMBEDDING_API_KEYBearer token for external embedding endpoint
PHREN_LLM_KEYAPI key for semantic dedup/conflict LLM
OPENAI_API_KEYFallback for embedding and LLM calls
ANTHROPIC_API_KEYFallback for LLM calls (Claude models)
GITHUB_TOKENUsed 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)
Defense in depth

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.

RolePermissions
adminFull access: read, write, delete, policy changes
maintainerRead, write, delete. No policy changes.
contributorRead and write. No delete or policy changes.
viewerRead 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.

FeatureNetwork callControlled by
Core operationNoneAlways local
Git syncgit push/pull to your remoteStop hook (only if remote configured)
Embeddings (Ollama)localhost:11434PHREN_OLLAMA_URL
Embeddings (API)Your configured endpointPHREN_EMBEDDING_API_URL
Semantic dedup/conflictYour configured LLM endpointPHREN_LLM_ENDPOINT
GitHub extractionapi.github.comphren 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: extract provenance 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

StageTimeline
AcknowledgmentWithin 48 hours
Initial assessmentWithin 1 week
Fix or mitigation30 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 status can 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 doctor will 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:

AgeCited entryUncited entry
0-30 days1.000.80
31-60 days1.000.80
61-90 days0.850.68
91-120 days0.650.52
120+ days0.450.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_finding MCP tool
  • Task items via add_task
  • Session state committed and pushed by the Stop hook after every response

Manual

  • Running /phren-consolidate when findings pile up
  • Running phren maintain govern to 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 pull on ~/.phren at the beginning of every session
  • The Stop hook auto-commits and pushes ~/.phren changes 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"

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).

RolePermissions
adminFull access. Can modify governance, access control, workflow policies, and all project data.
maintainerCan add/edit/remove findings, tasks, and skills. Cannot modify governance or access control.
contributorCan add findings and tasks. Cannot remove or edit existing entries.
viewerRead-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:

  1. Create a shared git remote for ~/.phren
  2. Define profiles per team role (e.g. frontend.yaml, backend.yaml)
  3. Register each machine in machines.yaml, then run phren init
  4. 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.

Personal stays personal

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:

RoleReadWriteGit SyncUse Case
primaryYesYesFullYour personal store (default write target)
teamYesYesFullShared team store
readonlyYesNoPull onlyReference store (company-wide knowledge)

CLI Commands

phren team init <name> [--remote <url>]
Create a new team store. Generates a store with a .phren-team.yaml bootstrap file and registers it locally.
phren team join <git-url> [--name <name>]
Join an existing team store. Clones the repo, reads .phren-team.yaml, and adds it to your store registry.
phren team add-project <store> <project>
Claim a project for a team store. Writes to that store route through the team repo automatically.
phren team list
List all team stores and their sync status.

Write Routing

When you add a finding or task, phren resolves which store receives the write:

  1. If store-qualified (e.g. arc-team/arc) — use the explicit store
  2. If a team store claims the project in its registry — route to that store
  3. 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 pull on 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

ModeBehavior
phren-managedDefault. phren symlinks CLAUDE.md, FINDINGS.md, skills into the project directory.
repo-ownedThe project's repo owns its own CLAUDE.md. phren stores findings and tasks but does not symlink.
read-onlyphren indexes and searches the project but does not write to it.