Doramagic Project Pack · Human Manual

oc-piloci

piLoci bridges the gap between ephemeral AI coding sessions and persistent knowledge storage. When developers use AI assistants like Claude Code or OpenCode, piLoci captures session contex...

Introduction to piLoci

Related topics: System Architecture, Getting Started, Technology Stack

Section Related Pages

Continue reading this section for the full explanation and source context.

Section Core Value Proposition

Continue reading this section for the full explanation and source context.

Section Design Philosophy

Continue reading this section for the full explanation and source context.

Section System Components

Continue reading this section for the full explanation and source context.

Related topics: System Architecture, Getting Started, Technology Stack

Introduction to piLoci

piLoci is a lightweight, self-hosted memory curation system designed for AI coding assistants. It acts as a "quiet automatic memory curator" — silently capturing, organizing, and surfacing context from coding sessions to enhance productivity across projects. The system runs on Raspberry Pi 5 or any server, providing privacy-first memory management without relying on external cloud services.

Overview

piLoci bridges the gap between ephemeral AI coding sessions and persistent knowledge storage. When developers use AI assistants like Claude Code or OpenCode, piLoci captures session context, extracts actionable memories, and stores them in a searchable vector database. This enables developers to build a cumulative knowledge base that improves over time.

Core Value Proposition

AspectDescription
PrivacySelf-hosted on local hardware; no data leaves your network
AutomaticSilent capture of sessions without manual intervention
Project-scopedMemories organized by project for clean isolation
MCP-enabledNative integration with Model Context Protocol tools

Sources: README.md

Design Philosophy

piLoci embodies the metaphor of a "behind-the-scenes assistant quietly organizing notes" (뒤에서 조용히 돕는 자동 기억 큐레이터). The design direction emphasizes:

  • Curation over collection — Not just storing everything, but organizing meaningful insights
  • Graph/workspace representation — Visualizing relationships between memories and sessions
  • Minimal friction — One-line pairing, automatic capture, zero-token exposure

Sources: CLAUDE.md

Architecture

System Components

graph TD
    subgraph Client["Client Side"]
        ClaudeCode[Claude Code]
        OpenCode[OpenCode]
        Cursor[Cursor IDE]
    end

    subgraph MCP["MCP Layer"]
        Memory[MCP: memory]
        Recall[MCP: recall]
        Recommend[MCP: recommend]
    end

    subgraph Server["piLoci Server"]
        API[Python API Server]
        SQLite[(SQLite<br/>Identity Data)]
        LanceDB[(LanceDB<br/>Vector Store)]
        Redis[(Redis<br/>Sessions)]
        Embed[FastEmbed/ONNX]
    end

    subgraph WebUI["Web Frontend"]
        Dashboard[Dashboard]
        Projects[Project Workspace]
        Admin[Admin Console]
    end

    ClaudeCode <--> MCP
    OpenCode <--> MCP
    Cursor <--> MCP
    MCP <--> API
    API <--> SQLite
    API <--> LanceDB
    API <--> Redis
    API <--> Embed
    API <--> WebUI

Technology Stack

ComponentTechnologyPurpose
BackendPythonMCP-enabled API server
Identity DBSQLiteUser accounts, projects, sessions
Vector StoreLanceDBEmbedded memory storage
Session CacheRedisSession state management
EmbeddingsFastEmbed (ONNX)Fast on-device inference
FrontendNext.jsWeb UI, dashboard, settings

Sources: README.md

Web Frontend Structure

The web application follows a consistent page pattern defined in web/DESIGN-HARNESS.md:

<AppShell>
  <div className="pi-page">
    <section className="pi-page-hero">
      <p className="pi-eyebrow">Area label</p>
      <h1 className="pi-title mt-2">Page title</h1>
      <p className="pi-subtitle">One sentence explaining the page.</p>
    </section>

    <section className="grid gap-3 sm:grid-cols-3">
      <div className="pi-metric-card">...</div>
    </section>

    <section className="pi-panel p-3">...</section>
  </div>
</AppShell>

#### Baseline Pages

PageComponentPurpose
Dashboardapp/dashboard/page.tsx + DashboardSummaryPanels.tsxUser overview with metrics
Admin Consoleapp/admin/users/page.tsxUser management
Project Workspaceapp/projects/page.tsx + ProjectListView.tsxProject-level memory access
Privacyapp/privacy/page.tsxPrivacy policy
Termsapp/terms/page.tsxTerms of service

Sources: DESIGN-HARNESS.md

Client Connection Flow

Supported Clients

piLoci integrates with multiple AI coding assistants through MCP:

ClientSession CaptureMCP Tools
Claude CodeSessionStart/Stop hooksmemory, recall, recommend
Claude DesktopStatic configmemory, recall, recommend
OpenCodeStatic config onlymemory, recall, recommend
CursorStatic configmemory, recall, recommend

Sources: web/components/TokenManager.tsx

Connection Process

sequenceDiagram
    participant User
    participant CLI
    participant WebUI
    participant Server

    User->>CLI: piloci login
    CLI->>Server: OAuth or install code request
    Server->>WebUI: Redirect to /device
    User->>WebUI: Login + approve
    WebUI->>CLI: Token ready
    CLI->>Server: Poll and receive token
    Server->>CLI: Token + URLs
    CLI->>User: Configuration complete

    User->>CLI: piloci install
    CLI->>Server: Download MCP server config
    Server->>CLI: .mcp.json + hooks
    CLI->>User: MCP tools available

What Connection Establishes

The pairing process creates the following artifacts:

~/.config/piloci/
├── config.json     # Token + ingest/analyze URLs (mode 0600)
├── hook.py         # SessionStart catch-up (Claude only)
└── stop-hook.sh    # Stop live push (Claude only)

~/.claude.json              # MCP server entry (Claude only)
~/.claude/settings.json     # SessionStart + Stop hooks (Claude only)
~/.config/opencode/         # MCP server entry (OpenCode)

Sources: README.ko.md

CLI Commands

The piloci CLI provides complete installation and management capabilities:

CommandDescription
piloci loginAuthenticate with the server (OAuth or install code)
piloci installInstall MCP server and hooks for AI clients
piloci uninstallRemove all piLoci artifacts, optionally restore backups
piloci restoreRestore client configs from .piloci-bak snapshots
piloci backfill-cwdFix legacy slug-collision bug in session data

Install Command Options

FlagPurpose
--serverOverride server URL when only install code is provided
--tokenUse token directly instead of resolving URL
--forceWipe existing plugin folders and reinstall fresh

Uninstall Command Options

FlagPurpose
--yesSkip confirmation prompt
--no-restoreRemove entries surgically instead of restoring backups

Sources: src/piloci/cli.py

Plugin Installation Structure

For Claude Code, piLoci installs as a Claude plugin with hooks:

piloci/
├── .claude-plugin/
│   └── plugin.json          # Manifest with name, version, description
├── hooks/
│   ├── hooks.json           # SessionStart + Stop wired to scripts
│   ├── hook.py              # Downloaded from /api/hook/script
│   └── stop-hook.sh         # Downloaded from /api/hook/stop-script
└── .mcp.json                # MCP server config for memory/recall/recommend

Sources: src/piloci/installer.py

Data Models

API Client Functions

The frontend communicates with the backend through typed API functions:

// Project operations
getProjects: () => request<Project[]>("api/projects")
getProjectBySlug: (slug: string) => request<Project>(`api/projects/slug/${slug}`)
createProject: (body) => request<Project>("api/projects", { method: "POST", body })
getProjectFreshness: (projectId) => request<ProjectFreshness>(`api/projects/${projectId}/freshness`)

// Session operations
getSessions: () => request<Session[]>("api/sessions")

// Memory operations
createMemory: (projectId, body) => request<Memory>(`api/memories`, { method: "POST", body })

// Distillation operations
runDistillationNow: () => request<{ woken: boolean; note: string }>("/api/distillation/run-now", { method: "POST" })
getDistillationPreferences: () => request<DistillationPreferences>("api/preferences")
updateDistillationPreferences: (body) => request<DistillationPreferences>("api/preferences", { method: "PATCH", body })

// Budget operations
budgetUsage: () => request<BudgetUsage>("api/budget/usage")

Sources: web/lib/api.ts

Project Sessions Panel

The session viewer displays captured coding sessions:

FieldDescription
ingest_idUnique session identifier
clientAI client used (Claude Code, OpenCode, etc.)
project_slugAssociated project
project_nameHuman-readable project name
created_atSession start timestamp
processed_atWhen distillation completed
memories_extractedNumber of memories extracted
errorAny processing errors
transcriptFull session transcript (expandable)

Sources: web/components/ProjectSessionsPanel.tsx

Instincts (Top Knacks)

Instincts are triggered memory patterns:

FieldDescription
instinct_idUnique instinct identifier
triggerCondition pattern ("when...")
actionSuggested action ("→...")
project_slugAssociated project
domainKnowledge domain
instinct_countNumber of times triggered

Sources: web/components/DashboardSummaryPanels.tsx

Usage Scenarios

Scenario A — Team Project Memory Hub

A small team sets up one piLoci on a shared Raspberry Pi 5. Each member creates an account, joins shared projects, and stores memories via MCP tools. Everyone benefits from the same knowledge base while project isolation keeps unrelated work separate.

Scenario B — Multi-Project Workspace

A solo developer runs several projects (e.g., "thesis research", "side project", "client work") on one piLoci. Each project's memories stay isolated, and the workspace viewer shows notes and relationships per project.

Scenario C — Obsidian Export

Generate workspace notes and export to an Obsidian vault:

curl -sS http://localhost:8314/api/projects/slug/my-project/workspace

Or download a ready-made archive:

curl -OJ http://localhost:8314/api/vault/my-project/export

Sources: README.md

Deployment Configuration

Environment Variables

When running behind a reverse proxy, the BASE_URL environment variable is required:

BASE_URL=https://piloci.example.com

This ensures Google OAuth redirect URIs match exactly:

https://piloci.example.com/auth/google/callback

Without BASE_URL, the backend may generate callbacks based on internal request hosts, causing redirect_uri_mismatch errors.

Port Configuration

The default port is 8314. When exposing via reverse proxy or tunnel (Cloudflare Tunnel, Caddy, nginx), proxy external traffic to http://127.0.0.1:8314.

Sources: README.ko.md

Version Management

piLoci uses a single-source version system:

RuleDescription
Sourcepyproject.toml[project].version
Default bump+0.0.1 patch only
Major/MinorRequires explicit approval
Release triggerGit tag push: git tag v{version} && git push origin main v{version}
Tag formatMust match: v0.2.00.2.0

Pre-release Checklist

Before tagging:

  1. Update version in pyproject.toml
  2. Run tests: pytest tests/ -v
  3. Build package: uv build
  4. Build web (if changed): pnpm build in web/

GitHub Actions Pipeline

The publish.yml workflow handles:

  • Version guard (tag matches pyproject.toml)
  • Test gate
  • Web build artifact
  • Multi-arch Docker image publish
  • GitHub Release creation
  • PyPI publish as oc-piloci

Sources: CLAUDE.md

Development Workflow

Starting an Implementation Session

  1. Begin each session at PLAN.md
  2. Check ## 현재 상태 (Current Status) for incomplete items
  3. Implement the next pending item
  4. Document completion in PLAN.md

Current Development Focus

Based on recent changes documented in MEMORY.md:

  • Memory creation UI speed — Narrow v0.3 slice for faster memory creation
  • Graph UI direction — Planning for React Flow-based interactive memory visualization
  • Copy style — Landing page emphasizes "quiet automatic memory curator" metaphor
  • Vault caching — Tests added for tests/test_vault_cache.py

Sources: MEMORY.md

Design Guidelines for Frontend

Key principles from CLAUDE.md:

  • Avoid dash-heavy feature lists — Use paragraph-based Korean/English copy
  • Translate optimizations to UX — Don't just list technical features
  • Maintain metaphor — "뒤에서 조용히 돕는 자동 기억 큐레이터" (behind-the-scenes quiet assistant)
  • Graph direction — Visual metaphor of a curator organizing post-it notes

Sources: README.md

Getting Started

Related topics: Introduction to piLoci

Section Related Pages

Continue reading this section for the full explanation and source context.

Section Hardware Requirements

Continue reading this section for the full explanation and source context.

Section Software Requirements

Continue reading this section for the full explanation and source context.

Section Step 1: Clone the Repository

Continue reading this section for the full explanation and source context.

Related topics: Introduction to piLoci

Getting Started

piLoci is a personal memory hub designed for AI coding assistants. It runs on a local server (typically Raspberry Pi 5) and captures, stores, and retrieves contextual memories from AI-assisted coding sessions. This guide walks you through the complete setup process from hardware prerequisites to first login.

Prerequisites

Hardware Requirements

ComponentMinimumRecommended
DeviceRaspberry Pi 5 (4GB+)Raspberry Pi 5 (8GB)
Storage32GB SD card64GB+ SSD via USB
NetworkEthernet or WiFiEthernet
OSRaspberry Pi OS (64-bit)Raspberry Pi OS (64-bit)

Sources: README.md

Software Requirements

  • Docker and Docker Compose installed on the host
  • Google OAuth credentials (for authentication)
  • A domain name (optional, for remote access via Cloudflare Tunnel)

Installation

Step 1: Clone the Repository

git clone https://github.com/jshsakura/oc-piloci.git
cd oc-piloci

Step 2: Configure Environment Variables

Copy the example environment file and configure it:

cp .env.example .env

Edit .env with your specific settings:

# Required: Set your external HTTPS domain if behind a reverse proxy
BASE_URL=https://piloci.example.com

# Google OAuth credentials (required for authentication)
GOOGLE_CLIENT_ID=your_client_id_here
GOOGLE_CLIENT_SECRET=your_client_secret_here

# Secret key for session encryption
SECRET_KEY=your_random_secret_key_here
Important: When deploying behind a reverse proxy, you MUST set BASE_URL to your external HTTPS domain. Without it, Google OAuth redirect URIs will fail with redirect_uri_mismatch. Sources: README.ko.md

#### Google OAuth Setup

  1. Go to Google Cloud Console
  2. Create a new project or select an existing one
  3. Navigate to APIs & ServicesCredentials
  4. Create an OAuth 2.0 Client ID (Web application type)
  5. Add the following authorized redirect URI (replace with your domain):
https://piloci.example.com/auth/google/callback

The callback URI must match exactly, including trailing slashes. Sources: README.ko.md

Step 3: Deploy with Docker Compose

The project uses Docker Compose for container orchestration:

docker compose up -d

This starts the following services:

ServicePortPurpose
web8314Next.js frontend + API server
redis6379Session storage
worker-Background distillation worker

Sources: docker-compose.yml

Step 4: Verify Deployment

Check the health status:

curl http://localhost:8314/healthz

A successful response indicates the application is running correctly.

Architecture Overview

graph TB
    subgraph "Client Side"
        CC[Claude Code / Claude Desktop]
        OC[OpenCode]
        CU[Cursor]
    end
    
    subgraph "piLoci Server"
        WEB[Web App :8314]
        REDIS[(Redis<br/>Sessions)]
        WORKER[Distillation<br/>Worker]
        DB[(LanceDB<br/>Memories)]
    end
    
    subgraph "AI Clients → piLoci"
        CC --> MCP[MCP Server]
        OC --> MCP
        CU --> MCP
    end
    
    MCP -->|Ingest| WEB
    WEB --> REDIS
    WEB --> DB
    WORKER --> DB
    WORKER -->|Distill| CC

Sources: README.md

Client Connection

Claude Code Setup

  1. Navigate to Settings → Tokens in the web UI
  2. Generate an install code
  3. Run the pairing command:
piloci login --pair <install_code>
piloci install

Or use the one-liner:

curl -sSL https://piloci.example.com/install/<install_code> | bash

This automatically:

Sources: README.ko.md

What Gets Installed

~/.config/piloci/
├── config.json     # Token + ingest/analyze URLs (mode 0600)
├── hook.py         # SessionStart catch-up hook (Claude Code only)
└── stop-hook.sh    # Stop live push (Claude Code only)

~/.claude.json              # MCP server entry (Claude Code only)
~/.claude/settings.json     # SessionStart + Stop hooks (Claude Code only)

Sources: README.ko.md

Remote Access

Exposing Port 8314

Configure your reverse proxy or tunnel to expose port 8314:

Proxy/TunnelConfiguration
Cloudflare TunnelPoint to http://127.0.0.1:8314
CaddyProxy to localhost:8314
nginxProxy pass to 127.0.0.1:8314

Cloudflare Tunnel Setup

cloudflared tunnel --url http://localhost:8314

Sources: README.ko.md

Configuration Reference

Environment Variables

VariableRequiredDefaultDescription
BASE_URLYes (remote)http://localhost:8314External HTTPS URL when behind proxy
GOOGLE_CLIENT_IDYes-Google OAuth Client ID
GOOGLE_CLIENT_SECRETYes-Google OAuth Client Secret
SECRET_KEYYes-Session encryption key
DATA_DIRNo./dataData persistence directory
REDIS_URLNoredis://redis:6379Redis connection URL

Sources: src/piloci/config.py

Data Storage

The application stores data in:

  • SQLite: User identity and authentication data
  • LanceDB: Embedded vector storage for memories
  • Redis: Session data and real-time state

Sources: README.md

Development Mode

Local Stack Development

# Start backend with hot reload
uv run uvicorn src.piloci.main:app --reload --port 8314

# In another terminal, start worker
uv run python -m piloci.worker.distillation

Web Frontend Development

cd web
pnpm install --frozen-lockfile
pnpm dev

Sources: README.md

Next Steps

After successful installation:

  1. Create an account via the web UI at http://localhost:8314/signup
  2. Connect your AI client using the pairing flow
  3. Create projects to organize your memories
  4. Explore the dashboard to view session history and extracted memories

For troubleshooting, check the logs:

docker compose logs -f web
docker compose logs -f worker

Sources: README.md

System Architecture

Related topics: Introduction to piLoci, Technology Stack, Storage Layer, MCP Server Implementation

Section Related Pages

Continue reading this section for the full explanation and source context.

Section Embedding Infrastructure

Continue reading this section for the full explanation and source context.

Section Page Structure Pattern

Continue reading this section for the full explanation and source context.

Section Key Frontend Components

Continue reading this section for the full explanation and source context.

Related topics: Introduction to piLoci, Technology Stack, Storage Layer, MCP Server Implementation

System Architecture

piLoci is a self-hosted memory curation system designed for AI-assisted development workflows. It operates as a client-server architecture where a Raspberry Pi (or any server) acts as a central hub for capturing, processing, and retrieving contextual memories from AI coding sessions. The system bridges the gap between ephemeral AI conversations and persistent, searchable knowledge bases.

High-Level Architecture Overview

piLoci follows a layered architecture pattern comprising four primary tiers: a frontend presentation layer, a backend API layer, a storage abstraction layer, and a client integration layer. Each tier is independently deployable and communicates through well-defined interfaces, enabling flexibility in deployment scenarios.

The backend is built with Python and leverages the Model Context Protocol (MCP) to expose memory management tools to AI clients such as Claude Code and OpenCode. The frontend is a Next.js application that provides both user-facing interfaces and administrative capabilities. The storage layer abstracts away the complexity of handling different database technologies, providing a unified API for memory operations.

graph TD
    subgraph Client["Client Layer"]
        ClaudeCode["Claude Code"]
        OpenCode["OpenCode"]
        Cursor["Cursor IDE"]
    end

    subgraph Server["piLoci Server"]
        API["FastAPI Server<br/>(Port 8314)"]
        MCP["MCP Tools<br/>memory/recall/recommend"]
    end

    subgraph Storage["Storage Layer"]
        SQLite["SQLite<br/>(Identity)"]
        LanceDB["LanceDB<br/>(Vectors)"]
        Redis["Redis<br/>(Sessions)"]
    end

    subgraph Frontend["Frontend Layer"]
        NextJS["Next.js App<br/>(Web UI)"]
        Admin["Admin Console"]
        Dashboard["User Dashboard"]
    end

    Client -->|HTTP/MCP| Server
    NextJS -->|REST API| API
    API --> Storage
    API --> MCP

Sources: README.md:1-50

Technology Stack

piLoci's architecture leverages a carefully selected technology stack optimized for self-hosted deployment on resource-constrained hardware like the Raspberry Pi 5. Each component serves a specific purpose in the overall system.

ComponentTechnologyPurposeLocation
Backend APIFastAPIREST API + MCP serversrc/piloci/
Vector StorageLanceDBEmbedded memory storage with vector searchsrc/piloci/storage/
Identity DBSQLiteUser/project identity and metadatasrc/piloci/db/
Session CacheRedisTemporary session data cachingdocker-compose.yml
Embeddingsfastembed (ONNX)Local CPU-based embedding inferencesrc/piloci/storage/
FrontendNext.js 14React-based web applicationweb/
StylingTailwind CSSUtility-first design systemweb/
ContainerDockerSelf-contained deploymentdocker-compose.yml

Sources: README.md:85-95

Embedding Infrastructure

The system uses fastembed for ONNX-based embeddings, enabling fast, on-device inference without requiring GPU resources. This design choice is critical for the target deployment environment of Raspberry Pi devices where power efficiency and thermal constraints are primary concerns.

The embedding service processes text content and generates vector representations that capture semantic meaning. These vectors are stored in LanceDB, which provides efficient similarity search capabilities essential for the recall and recommendation features.

Sources: README.md:90

Frontend Architecture

The Next.js frontend follows a component-driven architecture with clear separation between presentation components, data fetching logic, and layout structures. The application is organized around a shell-based layout pattern that provides consistent navigation and authentication state across all pages.

Page Structure Pattern

All application pages follow a standardized layout defined in AppShell.tsx with specific section patterns for different content types.

graph TD
    AppShell["AppShell Component<br/>(web/components/AppShell.tsx)"]
    Hero["pi-page-hero<br/>(Title + Subtitle)"]
    Metrics["pi-metric-card<br/>(Data Cards)"]
    Panel["pi-panel<br/>(Content Sections)"]

    AppShell --> Hero
    AppShell --> Metrics
    AppShell --> Panel

The component hierarchy follows this pattern:

AppShell
└── div.pi-page
    ├── section.pi-page-hero
    │   ├── p.pi-eyebrow
    │   ├── h1.pi-title
    │   └── p.pi-subtitle
    ├── section.pi-page (metrics grid)
    │   └── div.pi-metric-card
    └── section.pi-panel (content areas)

Sources: web/DESIGN-HARNESS.md:10-30

Key Frontend Components

ComponentFile PathResponsibility
AppShellweb/components/AppShell.tsxAuthenticated shell with glass navigation
DashboardSummaryPanelsweb/components/DashboardSummaryPanels.tsxUser dashboard with metrics and session lists
ProjectSessionsPanelweb/components/ProjectSessionsPanel.tsxProject-specific session viewer with transcripts
TokenManagerweb/components/TokenManager.tsxInstallation token generation and display
DistillationSettingsweb/components/DistillationSettingsPanel.tsxMemory processing configuration

Sources: web/components/DashboardSummaryPanels.tsx:1-80

API Client Layer

The frontend communicates with the backend through a typed API client defined in web/lib/api.ts. This module provides a centralized request function that handles authentication, error handling, and response typing.

// Simplified API client structure
const api = {
  projects: {
    list: () => request<Project[]>("/api/projects"),
    create: (body) => request<Project>("/api/projects", { method: "POST", body }),
    getBySlug: (slug) => request<Project>(`/api/projects/slug/${slug}`),
  },
  memories: {
    create: (projectId, body) => request<Memory>(`/api/projects/${projectId}/memories`, { method: "POST", body }),
    list: (projectId) => request<Memory[]>(`/api/projects/${projectId}/memories`),
  },
  distillation: {
    runNow: () => request<{ woken: boolean; note: string }>("/api/distillation/run-now", { method: "POST" }),
    getPreferences: () => request<DistillationPreferences>("/api/preferences"),
    updatePreferences: (body) => request<DistillationPreferences>("/api/preferences", { method: "PATCH", body }),
  },
};

Sources: web/lib/api.ts:1-50

Landing Page Architecture

The landing page (web/app/page.tsx) serves as the public-facing entry point for unauthenticated users and implements a conversion-focused design with feature highlights and installation guidance.

graph LR
    Hero["Hero Section<br/>(CTA: Signup/Dashboard)"]
    Features["Features Grid<br/>(4-column)"]
    Install["Installation Guide<br/>(CLI + bash options)"]
    Uninstall["Uninstall Note<br/>(Removal instructions)"]

    Hero --> Features
    Features --> Install
    Install --> Uninstall

Sources: web/app/page.tsx:1-60

Backend Architecture

The Python backend implements a FastAPI application that serves both REST API endpoints and MCP tool interfaces. The architecture emphasizes separation of concerns through distinct modules for API routes, database operations, and storage abstraction.

Application Entry Point

The main application module (src/piloci/main.py) initializes the FastAPI server with middleware configuration, CORS settings, and route registration. The application listens on port 8314 by default and supports configuration through environment variables.

Key configuration parameters:

ParameterDefaultPurpose
BASE_URL(auto-detected)External HTTPS domain for OAuth callbacks
DATABASE_URL(local path)SQLite database location
REDIS_URL(local)Redis connection for session caching
PORT8314HTTP server port

Sources: README.ko.md:1-30

Database Architecture

The system uses three distinct storage mechanisms, each optimized for specific data access patterns.

graph TD
    API["FastAPI Server"]
    Session["Session Management"]
    Identity["SQLite<br/>(Identity Data)"]
    Vectors["LanceDB<br/>(Memory Vectors)"]
    Cache["Redis<br/>(Session Cache)"]

    API --> Session
    Session --> Identity
    Session --> Vectors
    Session --> Cache

#### Identity Database (SQLite)

SQLite handles persistent identity data including user accounts, project metadata, and session records. The session module (src/piloci/db/session.py) provides an abstraction layer for database operations.

# Session database schema concept
class Session:
    id: str
    user_id: str
    project_id: str
    client: str  # "claude-code" | "opencode" | "cursor"
    ingest_id: str
    created_at: datetime
    processed_at: Optional[datetime]
    memories_extracted: int
    error: Optional[str]

Sources: web/components/DashboardSummaryPanels.tsx:30-50

#### Vector Storage (LanceDB)

LanceDB stores embedded memory content with vector representations for semantic search. The storage module provides CRUD operations for memories and supports similarity-based retrieval for the recall and recommendation features.

#### Session Cache (Redis)

Redis provides low-latency caching for active sessions and real-time processing state. The distillation worker uses Redis for queue management and processing state tracking.

Sources: README.md:85-90

API Route Organization

API routes are organized by resource type and follow RESTful conventions:

Route PrefixHandlerPurpose
/api/auth/*AuthenticationOAuth flows, session management
/api/projects/*Project managementCRUD, slug lookup, freshness
/api/memories/*Memory operationsCreate, list, vector search
/api/budget/*Budget trackingUsage reporting
/api/preferencesUser settingsDistillation configuration
/api/distillation/*Worker controlManual trigger, status

Sources: web/lib/api.ts:1-40

Installer Architecture

The installer module (src/piloci/installer.py) handles client-side setup by creating configuration files and registering MCP servers with supported AI clients. It follows a plugin-based architecture for each supported client type.

Claude Code Installer Layout

graph TD
    Plugin["Claude Plugin<br/>~/.claude/plugins/piloci/"]
    PluginManifest[".claude-plugin/plugin.json"]
    Hooks["hooks/hooks.json"]
    Scripts["hooks/hook.py<br/>hooks/stop-hook.sh"]
    MCP[".mcp.json<br/>(MCP Server Config)"]

    Plugin --> PluginManifest
    Plugin --> Hooks
    Plugin --> Scripts
    Plugin --> MCP

Sources: src/piloci/installer.py:20-50

Installation Workflow

  1. Manifest Creation: Generates plugin.json with version, description, and author metadata
  2. Hook Configuration: Creates hooks.json linking SessionStart and Stop events to plugin scripts
  3. Script Download: Fetches hook.py and stop-hook.sh from the server's /api/hook/ endpoints
  4. MCP Registration: Creates .mcp.json exposing memory, recall, and recommend tools

Sources: src/piloci/installer.py:50-80

Deployment Architecture

piLoci is designed for self-hosted deployment, typically on a Raspberry Pi 5 within the user's local network. The system supports exposure through reverse proxies or tunnels for remote access.

Docker Deployment

The recommended deployment uses Docker Compose with the following service structure:

services:
  piloci:
    image: ghcr.io/jshsakura/oc-piloci:latest
    ports:
      - "8314:8314"
    volumes:
      - ./data:/data
    environment:
      - BASE_URL=https://piloci.example.com
      - DATABASE_URL=sqlite:///data/piloci.db

Sources: docker-compose.yml

Reverse Proxy Configuration

When deploying behind a reverse proxy (Cloudflare Tunnel, Caddy, nginx), port 8314 should be exposed externally. The BASE_URL environment variable must be set to the external HTTPS domain for proper OAuth callback URL generation.

Google OAuth requires exact callback URI matching:

https://piloci.opencourse.kr/auth/google/callback

Sources: README.ko.md:25-40

Client Connection Flow

The system supports multiple AI clients through standardized MCP interfaces. Each client has specific integration requirements.

sequenceDiagram
    participant User
    participant CLI as piloci CLI
    participant Browser
    participant Server as piLoci Server
    participant Claude as Claude Code

    User->>CLI: piloci login
    CLI->>Browser: Opens /device page
    User->>Browser: Login + Approve
    Browser->>Server: Token exchange
    Server->>CLI: Token + URLs
    CLI->>CLI: Write ~/.config/piloci/config.json
    CLI->>Server: Register MCP server
    User->>Claude: Start session
    Claude->>CLI: MCP tool calls (memory/recall/recommend)
    CLI->>Server: API requests
    Server->>Claude: Memory results

Sources: README.ko.md:1-20

Supported Clients

ClientMCP SupportHook SupportConfiguration Location
Claude CodeFullSessionStart + Stop~/.claude.json, ~/.claude/settings.json
Claude DesktopFullN/A~/Library/Application Support/Claude/
OpenCodeFullN/A~/.config/opencode/opencode.json
CursorPartialN/ACursor MCP settings

Sources: web/components/TokenManager.tsx:1-30

Distillation System

The distillation system processes captured sessions to extract structured memories. It operates as a configurable background worker with temperature and load-based throttling.

Distillation Settings

ParameterPurposeDefault Behavior
Temperature CeilingSoC temperature threshold (°C)Worker pauses when exceeded
Load Ceiling1-minute load average limitWorker pauses when exceeded
Overflow ThresholdWorkload threshold for aggressive processingIgnores load when exceeded

Sources: web/components/DistillationSettingsPanel.tsx:1-40

Processing Pipeline

  1. Session Capture: Hook scripts send transcripts via the ingest API
  2. Transcript Storage: Raw content stored with session metadata
  3. Embedding Generation: fastembed creates vector representations
  4. Memory Extraction: LLM processes transcript to identify key learnings
  5. Vector Indexing: Extracted memories indexed in LanceDB for retrieval

Admin Console

The admin console (web/app/admin/users/page.tsx) provides administrative oversight with user management and system statistics.

Admin Features

FeatureDescriptionEndpoint
User StatisticsTotal, pending, admin countsCalculated from database
User ManagementView and manage user accounts/api/admin/users
System HealthDashboard with key metricsDashboardSummaryPanels

Sources: web/app/admin/users/page.tsx:1-50

Version Management

The system uses a single-source version policy where pyproject.toml is the authoritative version source. The piloci.__version__ is derived from package metadata rather than hardcoded values.

Release Process

  1. Update version in pyproject.toml (patch increment by default)
  2. Run validation: pytest tests/ -v and uv build
  3. Tag with matching version: git tag v{version}
  4. Push tag to trigger GitHub Actions workflow

The publish workflow (publish.yml) performs tag/version consistency checks, runs tests, builds the web app, publishes Docker images, creates GitHub Release, and publishes to PyPI.

Sources: CLAUDE.md:1-30

Development Workflow

Development follows a session-based approach where each implementation session begins by reviewing PLAN.md and checking the current status section for the next incomplete item.

Development Stack Commands

# Backend development
cd src
uv run pytest tests/ -v
uv run black .
uv run ruff check .

# Frontend development
cd web
pnpm install --frozen-lockfile
pnpm build

Sources: README.md:60-75

System Data Flow

graph LR
    subgraph Capture["Capture Phase"]
        Transcript["User/AI Transcript"]
        Hook["SessionStart Hook"]
    end

    subgraph Process["Processing Phase"]
        Ingest["Ingest API"]
        Embed["Embedding (fastembed)"]
        Extract["Memory Extraction"]
    end

    subgraph Store["Storage Phase"]
        SQLite["SQLite (Metadata)"]
        LanceDB["LanceDB (Vectors)"]
        Redis["Redis (Cache)"]
    end

    subgraph Retrieve["Retrieval Phase"]
        Recall["recall tool"]
        Recommend["recommend tool"]
        Search["Vector Search"]
    end

    Transcript --> Hook
    Hook --> Ingest
    Ingest --> Embed
    Embed --> Extract
    Extract --> SQLite
    Extract --> LanceDB
    Ingest --> Redis

    Recall --> Search
    Recommend --> Search
    Search --> LanceDB
    Search --> Retrieve

Summary

piLoci's architecture reflects a pragmatic approach to self-hosted AI memory management. By combining FastAPI for the backend, Next.js for the frontend, and purpose-built storage solutions (SQLite, LanceDB, Redis), the system achieves a balance between simplicity and capability. The MCP integration layer enables seamless interaction with popular AI coding tools while maintaining client neutrality. The modular design allows each component to be upgraded or replaced independently, and the Docker-based deployment ensures consistent behavior across different host environments.

Sources: README.md:1-50

Technology Stack

Related topics: System Architecture, Storage Layer, Web Dashboard

Section Related Pages

Continue reading this section for the full explanation and source context.

Section Core Framework

Continue reading this section for the full explanation and source context.

Section Data Storage

Continue reading this section for the full explanation and source context.

Section Embeddings Engine

Continue reading this section for the full explanation and source context.

Related topics: System Architecture, Storage Layer, Web Dashboard

Technology Stack

piLoci is a memory curation system built on a modern, lightweight technology stack designed for privacy-focused local deployment. The architecture combines a Python-based API backend with a Next.js frontend, leveraging specialized databases for vector storage and session management.

Architecture Overview

graph TB
    subgraph "Client Layer"
        ClaudeCode["Claude Code"]
        OpenCode["OpenCode"]
        Cursor["Cursor"]
    end
    
    subgraph "Frontend Layer (Next.js)"
        WebApp["Next.js Web App<br/>:3000"]
        UI["shadcn/ui + TailwindCSS"]
    end
    
    subgraph "Backend Layer (Python)"
        API["FastAPI + Uvicorn<br/>:8314"]
        MCP["MCP Server Tools"]
        Auth["Google OAuth"]
    end
    
    subgraph "Storage Layer"
        SQLite["SQLite<br/>Identity Data"]
        LanceDB["LanceDB<br/>Vector Storage"]
        Redis["Redis<br/>Sessions"]
        FastEmbed["FastEmbed<br/>ONNX Embeddings"]
    end
    
    ClaudeCode --> MCP
    OpenCode --> MCP
    Cursor --> MCP
    WebApp --> API
    API --> SQLite
    API --> LanceDB
    API --> Redis
    LanceDB --> FastEmbed

Backend Technology

Core Framework

ComponentTechnologyPurpose
Web FrameworkFastAPIAsync API server with automatic OpenAPI docs
ASGI ServerUvicornHigh-performance ASGI server
ORMSQLAlchemyDatabase abstraction and migrations
ValidationPydanticData validation and serialization

Sources: pyproject.toml:1-50

Data Storage

#### SQLite — Identity Data

SQLite serves as the primary relational database for storing user identity, project metadata, and session records. It provides ACID compliance with minimal overhead, making it ideal for single-instance deployments.

# Simplified storage layer pattern
from sqlalchemy import create_engine
engine = create_engine("sqlite:///piloci.db")

Sources: pyproject.toml:20-35

#### LanceDB — Vector Storage

LanceDB is the vector database for semantic memory storage. It offers:

  • Columnar storage format optimized for ML workloads
  • Native Python bindings
  • Efficient similarity search on embedded vectors
  • Persistent storage with automatic indexing
# From the LanceDB store implementation
import lancedb
db = lancedb.connect("./data/lancedb")
table = db.open_table("memories")

Sources: src/piloci/storage/lancedb_store.py:1-30

The decision to use LanceDB was documented in ADR-014, citing advantages over alternatives like ChromaDB and Qdrant for local-first deployments.

Sources: docs/ADR-014-lancedb-backend.md:1-25

#### Redis — Session Management

Redis handles ephemeral session data with millisecond latency. It supports:

  • Session token storage and validation
  • Real-time session state tracking
  • Pub/sub for distributed caching

Sources: README.md:50-60

Embeddings Engine

FastEmbed provides ONNX-based embedding inference with these characteristics:

FeatureDescription
RuntimeONNX (Open Neural Network Exchange)
DeploymentOn-device inference
SpeedOptimized for CPU execution
PrivacyNo external API calls for embedding generation

Sources: README.md:55-60

# Embedding generation (conceptual)
from fastembed import TextEmbedding
model = TextEmbedding(model_name="BAAI/bge-small-en-v1.5")
embeddings = list(model.embed(documents))

Sources: pyproject.toml:40-50

Authentication

ProviderProtocolLibrary
Google OAuth 2.0OAuth 2.0Authlib

Sources: pyproject.toml:25-40

Google OAuth requires proper BASE_URL configuration when behind a reverse proxy:

BASE_URL=https://piloci.opencourse.kr

Sources: README.ko.md:100-110

Frontend Technology

Framework & Runtime

ComponentTechnologyVersion
FrameworkNext.js15.x
LanguageTypeScript5.x
RuntimeReact19.x
Package Managerpnpm9.x

Sources: web/package.json:1-30

UI Components

LayerLibraryPurpose
CSS FrameworkTailwindCSSUtility-first styling
Component Libraryshadcn/uiAccessible, customizable components
IconsLucide ReactConsistent icon system
Styling PatternCSS VariablesDesign token system via --pi-* variables

Sources: web/DESIGN-HARNESS.md:1-20

Design System Pattern

The frontend follows a standardized page pattern with consistent CSS class naming:

<AppShell>
  <div className="pi-page">
    <section className="pi-page-hero">
      <p className="pi-eyebrow">Area label</p>
      <h1 className="pi-title mt-2">Page title</h1>
      <p className="pi-subtitle">One sentence explaining the page.</p>
    </section>
    {/* Content sections */}
  </div>
</AppShell>

Sources: web/DESIGN-HARNESS.md:20-35

Infrastructure & Deployment

Containerization

# docker-compose.yml structure
services:
  api:
    build: .
    ports:
      - "8314:8314"
  redis:
    image: redis:alpine
  # SQLite and LanceDB are file-based, mounted as volumes

Sources: MEMORY.md:1-20

Hardware Targets

PlatformUse CaseNotes
Raspberry Pi 5Primary targetLocal deployment, Cloudflare Tunnel access
x86_64 ServerProductionMulti-arch Docker images
ARM64Edge computingSupported via Docker multi-arch builds

Sources: README.ko.md:30-45

Network Configuration

PortServiceProtocol
3000Next.js FrontendHTTP/HTTPS
8314FastAPI BackendHTTP (internal)
6379RedisTCP (internal)

Sources: README.ko.md:95-105

Reverse Proxy Support

  • Cloudflare Tunnel — Remote access without port forwarding
  • Caddy — Automatic HTTPS
  • nginx — Traditional reverse proxy
  • Custom BASE_URL — Required for OAuth callbacks behind proxies

Sources: README.ko.md:95-100

MCP Integration

The Model Context Protocol (MCP) enables AI assistants to interact with piLoci's memory system:

graph LR
    AI["AI Assistant<br/>(Claude Code, OpenCode, Cursor)"]
    MCP["MCP Server<br/>piloci.tools"]
    API["piLoci API<br/>:8314"]
    DB["Storage Layer"]
    
    AI -->|"MCP Protocol"| MCP
    MCP -->|"REST API"| API
    API -->|"Query/Store"| DB
ToolFunction
memoryStore new memories from conversation context
recallSemantic search through stored memories
recommendContext-aware memory suggestions

Sources: README.md:20-40

Technology Decision Records

Key architectural decisions are documented in the /docs/ADR-* directory:

ADRTopicStatus
ADR-014LanceDB Backend SelectionImplemented
ADR-015FastEmbed for EmbeddingsImplemented

Sources: docs/ADR-014-lancedb-backend.md:1-10

Development Workflow

Local Development Stack

# Backend
uv run pytest tests/ -v
uv build
uv run uvicorn src.piloci.api.main:app --reload --port 8314

# Frontend
cd web && pnpm install
pnpm dev    # Development server
pnpm build  # Production build

Sources: MEMORY.md:50-70

Release Process

# 1. Update version in pyproject.toml (+0.0.1 patch unit)
# 2. Validate
pytest tests/ -v
uv build

# 3. Tag and push
git tag v{version}
git push origin main v{version}

Sources: CLAUDE.md:25-40

GitHub Actions publish.yml handles:

  • Version guard validation
  • Test execution gate
  • Web app build artifact
  • Multi-arch Docker image publishing
  • GitHub Release creation
  • PyPI package publication (oc-piloci)

Sources: CLAUDE.md:20-30

Version Management

Version is managed as a single source of truth in pyproject.toml:

[project]
version = "0.3.0"

All release artifacts (Docker images, PyPI packages, GitHub releases) derive their versions from this field. No separate version files should be modified.

Sources: CLAUDE.md:10-25

Summary

LayerTechnologyKey Benefit
APIFastAPI + UvicornAsync performance, auto docs
DatabaseSQLiteZero-config, portable
VectorsLanceDB + FastEmbedLocal ML inference
SessionsRedisSub-millisecond latency
FrontendNext.js + shadcn/uiType-safe, accessible UI
AuthGoogle OAuth (Authlib)Secure SSO
DeploymentDocker + Cloudflare TunnelEdge-ready

Sources: pyproject.toml:1-50

MCP Server Implementation

Related topics: API Routes, Authentication & Security, Curator Pipeline

Section Related Pages

Continue reading this section for the full explanation and source context.

Related topics: API Routes, Authentication & Security, Curator Pipeline

MCP Server Implementation

Overview

The MCP (Model Context Protocol) Server in piLoci provides a standardized interface for AI clients (Claude Code, Claude Desktop, OpenCode, Cursor) to interact with piLoci's memory and cognitive services. This implementation exposes memory management tools, recall capabilities, and recommendation functions as MCP tools that can be invoked by AI assistants during conversations.

The MCP server architecture is designed for:

  • Session-aware context management — Tracking and persisting conversation context across sessions
  • Tool-based memory operations — Enabling LLMs to create, search, and retrieve memories
  • Multi-client support — Serving multiple AI clients simultaneously with isolated state
  • Streaming communication — Supporting both HTTP streaming and Server-Sent Events (SSE)

Sources: README.md

Sources: README.md

Authentication & Security

Related topics: MCP Server Implementation, API Routes, Database Models

Section Related Pages

Continue reading this section for the full explanation and source context.

Section Supported Providers

Continue reading this section for the full explanation and source context.

Section OAuth Flow

Continue reading this section for the full explanation and source context.

Section Provider Configuration

Continue reading this section for the full explanation and source context.

Related topics: MCP Server Implementation, API Routes, Database Models

Authentication & Security

piLoci implements a comprehensive authentication and security system supporting multiple OAuth providers, encrypted token storage, Redis-based session management, and JWT authentication for API access. The system is designed for self-hosted deployment on resource-constrained environments like Raspberry Pi devices while maintaining enterprise-grade security practices.

Architecture Overview

The authentication system consists of several interconnected layers:

graph TD
    A[Client] --> B[Next.js Frontend]
    A --> C[Python CLI Client]
    B --> D[FastAPI Backend /api/*]
    C --> D
    D --> E[OAuth Providers<br/>Google/Kakao/Naver]
    D --> F[Redis<br/>Session Store]
    D --> G[SQLite<br/>User Database]
    D --> H[LanceDB<br/>Memory Storage]
    G --> I[Encrypted OAuth Tokens<br/>Fernet + JWT Secret]

Sources: src/piloci/auth/oauth.py:1-50

OAuth Authentication

piLoci supports authentication through multiple OAuth 2.0 providers, allowing users to sign in with existing accounts rather than creating new credentials.

Supported Providers

ProviderAuth URLToken URLUser Info EndpointScopes
Googlehttps://accounts.google.com/o/oauth2/v2/authhttps://oauth2.googleapis.com/tokenhttps://www.googleapis.com/oauth2/v3/userinfoopenid email profile
Kakaohttps://kauth.kakao.com/oauth/authorizehttps://kauth.kakao.com/oauth/tokenhttps://kapi.kakao.com/v2/user/meprofile_nickname account_email
Naverhttps://nid.naver.com/oauth2.0/authorizehttps://nid.naver.com/oauth2.0/tokenhttps://openapi.naver.com/v1/nid/me(none)

Sources: src/piloci/auth/oauth.py:20-45

OAuth Flow

sequenceDiagram
    participant U as User
    participant F as Frontend
    participant B as Backend
    participant P as OAuth Provider
    participant R as Redis

    U->>F: Click "Login with Provider"
    F->>B: GET /api/auth/providers
    B->>F: Return available providers
    F->>U: Redirect to OAuth authorization URL
    U->>P: Authorize application
    P->>U: Redirect with authorization code
    U->>B: GET /auth/{provider}/callback?code=XXX
    B->>P: Exchange code for tokens
    P->>B: Access token + Refresh token
    B->>B: Encrypt tokens with Fernet
    B->>G: Upsert user in SQLite
    B->>R: Create Redis session
    B->>U: Set session cookie, redirect to dashboard

Provider Configuration

Each OAuth provider is configured using a ProviderConfig dataclass that encapsulates all provider-specific settings:

@dataclass
class ProviderConfig:
    name: str
    auth_url: str
    token_url: str
    userinfo_url: str
    scopes: str
    extract_user: Callable[[dict], OAuthUserInfo]

Sources: src/piloci/auth/oauth.py:1-20

Building Authorization URLs

The build_auth_url() function constructs OAuth authorization URLs with provider-specific parameters:

def build_auth_url(provider: str, client_id: str, redirect_uri: str, state: str) -> str:
    provider_config = _get_provider(provider)
    params: dict[str, str] = {
        "client_id": client_id,
        "redirect_uri": redirect_uri,
        "response_type": "code",
        "state": state,
    }
    if provider_config.scopes:
        params["scope"] = provider_config.scopes
    params.update(provider_config.extra_auth_params)
    return f"{provider_config.auth_url}?{urlencode(params)}"

Sources: src/piloci/auth/oauth.py:67-80

User Information Extraction

Each provider returns user data in different formats. The extract_user callback normalizes this data into a standard OAuthUserInfo structure:

@dataclass
class OAuthUserInfo:
    provider: str
    provider_user_id: str
    email: str | None
    name: str | None

Provider-specific extractors handle the normalization:

  • _extract_github_user() for GitHub (if configured)
  • _extract_kakao_user() for Kakao API v2 response format
  • _extract_naver_user() for Naver's response envelope

Sources: src/piloci/auth/oauth.py:1-50

Encrypted Token Storage

OAuth tokens are encrypted before storage to prevent exposure even if the database is compromised.

Encryption Mechanism

piLoci uses Fernet symmetric encryption with a key derived from the JWT secret:

graph LR
    A[JWT Secret<br/>from settings] --> B[Key Derivation<br/>Function]
    B --> C[Fernet Key<br/>32-byte key]
    C --> D[Fernet.encrypt<br/>OAuth Token]
    C --> E[Fernet.decrypt<br/>Stored Token]

Sources: src/piloci/auth/crypto.py:1-20

Token Storage Schema

The User model in SQLite stores encrypted OAuth credentials:

ColumnTypeDescription
oauth_providerString (nullable)Provider name (google/kakao/naver)
oauth_provider_user_idString (nullable)User ID from the provider
oauth_access_tokenString (nullable, encrypted)Encrypted OAuth access token
oauth_refresh_tokenString (nullable, encrypted)Encrypted OAuth refresh token

Sources: src/piloci/db/models.py:1-100

Token Encryption Flow

async def upsert_oauth_user(
    provider: str,
    provider_user_id: str,
    access_token: str,
    refresh_token: str | None,
    email: str | None,
    name: str | None,
) -> User:
    # Encrypt tokens before storage
    encrypted_access = encrypt_token(access_token)
    encrypted_refresh = encrypt_token(refresh_token) if refresh_token else None
    
    # Upsert user with encrypted tokens
    ...

Sources: src/piloci/auth/oauth.py:100-150

Session Management

Sessions are managed through Redis for fast, stateless authentication validation.

Session Architecture

graph TD
    A[Request] --> B[Auth Middleware]
    B --> C{Check Session Cookie}
    C -->|No Cookie| D[Return 401]
    C -->|Has Cookie| E[Query Redis]
    E --> F{Valid Session?}
    F -->|No| D
    F -->|Yes| G[Attach User to Request]
    G --> H[Proceed to Route Handler]

Sources: src/piloci/auth/middleware.py:1-50

Session Structure

Sessions stored in Redis contain the authenticated user's identity:

{
  "user_id": "uuid-string",
  "email": "[email protected]",
  "created_at": "2024-01-01T00:00:00Z",
  "expires_at": "2024-01-01T12:00:00Z"
}

Sources: src/piloci/auth/session.py:1-50

Provider Disconnect Flow

Users can disconnect OAuth providers from their account. The disconnect process:

  1. Validates the logged-in Redis session
  2. Verifies password presence as a safety check
  3. Revokes the provider token remotely via revoke_provider_token()
  4. Clears local OAuth fields even if remote revoke fails

Sources: src/piloci/api/routes.py:1-100

sequenceDiagram
    participant U as User
    participant F as Frontend
    participant B as Backend
    participant R as Redis
    participant P as OAuth Provider

    U->>F: Click "Disconnect {provider}"
    F->>B: POST /auth/{provider}/disconnect
    B->>R: Validate session
    B->>B: Check password exists
    B->>P: Revoke provider token
    P-->>B: Revocation confirmation
    B->>B: Encrypt/clear OAuth fields
    B->>R: Update session
    B-->>F: Success response

API Authentication

Provider Discovery Endpoint

The frontend dynamically discovers available OAuth providers:

GET /api/auth/providers

Returns the list of configured providers based on environment credentials:

{
  "providers": ["google", "kakao", "naver"],
  "local": true
}

Sources: src/piloci/api/routes.py:100-200

Authentication Callback Routes

RouteMethodDescription
/auth/{provider}GETInitiate OAuth flow
/auth/{provider}/callbackGETHandle OAuth callback
/auth/{provider}/disconnectPOSTDisconnect provider

Sources: src/piloci/api/routes.py:200-300

Rate Limiting

Authentication endpoints are protected by rate limiting to prevent brute-force attacks:

# Rate limit configuration in tests
@pytest.mark.skip(reason="regression guard — re-enabled after config freeze")
async def test_auth_rate_limits():
    ...

Sources: MEMORY.md:1-50

Rate limit tests verify:

  • Provider status route shape consistency
  • Proper rate limiting headers
  • Appropriate 429 responses after threshold exceeded

Security Configuration

Environment Variables

VariableRequiredDescription
JWT_SECRETYesSecret key for JWT signing and Fernet encryption
SESSION_SECRETYesRedis session encryption key
BASE_URLYes (production)External HTTPS domain for OAuth callbacks
GOOGLE_CLIENT_IDFor Google OAuthGoogle OAuth application client ID
GOOGLE_CLIENT_SECRETFor Google OAuthGoogle OAuth application secret
KAKAO_CLIENT_IDFor Kakao OAuthKakao OAuth application client ID
KAKAO_CLIENT_SECRETFor Kakao OAuthKakao OAuth application secret
NAVER_CLIENT_IDFor Naver OAuthNaver OAuth application client ID
NAVER_CLIENT_SECRETFor Naver OAuthNaver OAuth application secret

OAuth Redirect URI Configuration

When deploying behind a reverse proxy, the BASE_URL environment variable must be set:

BASE_URL=https://piloci.opencourse.kr

Google OAuth redirect URIs must match exactly. Register this callback in Google Cloud Console:

https://piloci.opencourse.kr/auth/google/callback

Sources: README.ko.md:1-50

Without BASE_URL, the backend may construct callback URLs using local/internal request hosts, causing redirect_uri_mismatch errors even when credentials are correct.

Development Guidelines

Security Non-Negotiables

Per project development rules:

  • All LanceDB queries must filter by (user_id, project_id) — omission causes data leakage
  • Passwords: argon2id only — bcrypt is prohibited
  • JWT secret and session secret must come from environment variables or Docker secrets only — no hardcoding in code
  • Raw SQL is prohibited — use SQLAlchemy ORM exclusively
  • All user input must be validated through Pydantic schemas before processing

Sources: CLAUDE.md:1-50

Testing Authentication

Run auth-related tests with:

uv run pytest tests/test_auth_rate_limits.py -v --no-cov

Sources: MEMORY.md:50-100

Token-Based CLI Authentication

For the Python CLI client, token-based authentication is used:

from piloci_client import (
    PilociError,           # base — all SDK errors
    PilociAuthError,       # HTTP 401
    PilociPermissionError, # HTTP 403
    PilociValidationError, # HTTP 422
    PilociServerError,     # HTTP 5xx
)

Sources: clients/python/README.md:1-50

Install Pairing Flow

The system supports device code flow for CLI authentication:

  1. CLI displays a device code (ABCD-1234)
  2. User opens /device page in browser
  3. User logs in and approves
  4. CLI polls and receives token
  5. CLI auto-configures detected clients

Sources: src/piloci/auth/install_pairing.py:1-50

Password-Based Authentication

Password Reset Flow

The frontend provides password reset functionality at /forgot-password:

<Link href="/forgot-password" className="text-sm text-muted-foreground">
  {t.login.forgotPassword}
</Link>

Sources: web/app/login/login-client.tsx:1-50

Error messages display in styled containers:

<div className="bg-red-50 p-3 text-sm text-red-800 dark:bg-red-950">
  {serverError}
</div>

Sources: web/app/forgot-password/page.tsx:1-50

Summary

piLoci's authentication and security system provides:

  1. Multi-provider OAuth — Google, Kakao, Naver with provider-specific user extraction
  2. Encrypted token storage — Fernet encryption using JWT secret-derived keys
  3. Redis session management — Fast, stateless session validation
  4. Rate limiting — Protection against brute-force attacks
  5. Provider disconnect — Full OAuth account unlinking support
  6. Device code flow — Secure CLI authentication for headless environments
  7. Production-ready configuration — BASE_URL support for reverse proxy deployments

All authentication components follow the security non-negotiables defined in project development rules, ensuring consistent protection against common vulnerabilities.

Sources: src/piloci/auth/oauth.py:1-50

API Routes

Related topics: MCP Server Implementation, Authentication & Security, Storage Layer

Section Related Pages

Continue reading this section for the full explanation and source context.

Section Core Route Files

Continue reading this section for the full explanation and source context.

Section V1 Router Configuration

Continue reading this section for the full explanation and source context.

Section Supported Operations

Continue reading this section for the full explanation and source context.

Related topics: MCP Server Implementation, Authentication & Security, Storage Layer

API Routes

Overview

The API Routes module in oc-piloci provides a comprehensive REST API layer for the platform, enabling programmatic interaction with agent orchestration, team management, auditing, data operations, and model distillation capabilities. The API follows a modular architecture with separate route handlers for different functional domains.

The routing system is built on FastAPI principles and organizes endpoints by API version and functional area, providing a clean separation of concerns while maintaining a unified API surface.

Architecture

graph TD
    A[Client Request] --> B[API Gateway]
    B --> C[v1 Routes]
    C --> D[Team Routes]
    C --> E[Audit Routes]
    C --> F[Data Portability Routes]
    C --> G[Distillation Routes]
    D --> H[Rate Limiter]
    E --> H
    F --> H
    G --> H
    H --> I[Backend Services]

Route Organization

Core Route Files

FilePurposePrimary Responsibility
routes.pyMain router configurationEntry point, aggregation of sub-routers
v1.pyAPI v1 versioningVersion-specific route mounting
team_routes.pyTeam managementTeam CRUD, membership, permissions
audit.pyAudit loggingAction tracking, audit trail retrieval
data_portability.pyData operationsImport/export, data migration
distillation_routes.pyModel distillationKnowledge distillation workflows
ratelimit.pyRate limitingRequest throttling, quota management

Sources: src/piloci/api/routes.py

Versioned API Structure

The API uses URL-based versioning with v1 as the current stable version.

graph LR
    A[/api/v1/*] --> B[Version Router]
    B --> C[Team Endpoints]
    B --> D[Audit Endpoints]
    B --> E[Data Endpoints]
    B --> F[Distillation Endpoints]

V1 Router Configuration

The v1 router serves as the main container for all v1 API endpoints, mounting sub-routers for each functional domain.

Sources: src/piloci/api/v1.py

Team Routes

Team routes handle all team-related operations including team creation, member management, and team-level configurations.

Supported Operations

OperationHTTP MethodEndpoint Pattern
List teamsGET/teams
Create teamPOST/teams
Get teamGET/teams/{team_id}
Update teamPUT/teams/{team_id}
Delete teamDELETE/teams/{team_id}
Add memberPOST/teams/{team_id}/members
Remove memberDELETE/teams/{team_id}/members/{user_id}
List membersGET/teams/{team_id}/members

Sources: src/piloci/api/team_routes.py

Audit Routes

Audit routes provide access to the system's audit trail, enabling compliance and monitoring use cases.

Audit Features

  • Action logging for all significant system events
  • Queryable audit history by time range
  • Filtering by user, team, or action type
  • Audit report generation

Common Audit Endpoints

EndpointDescription
GET /audit/eventsList audit events with filtering
GET /audit/events/{event_id}Get specific audit event details
GET /audit/teams/{team_id}Get team-specific audit history

Sources: src/piloci/api/audit.py

Data Portability Routes

Data portability endpoints support import and export operations for data migration and backup purposes.

Data Operations

OperationDescription
Export dataGenerate downloadable data archives
Import dataUpload and process data packages
Data format conversionTransform between supported formats
Partial syncIncremental data synchronization

Sources: src/piloci/api/data_portability.py

Distillation Routes

Distillation routes manage model knowledge distillation workflows, enabling the transfer of knowledge from larger models to smaller, more efficient ones.

Distillation Workflow

graph TD
    A[Teacher Model] --> B[Distillation Request]
    C[Student Model] --> B
    B --> D[Distillation Job]
    D --> E[Knowledge Transfer]
    E --> F[Trained Student Model]
    F --> G[Validation]
    G --> H[Model Registry]

Distillation Endpoints

EndpointMethodDescription
/distillation/jobsPOSTCreate new distillation job
/distillation/jobsGETList distillation jobs
/distillation/jobs/{job_id}GETGet job status
/distillation/jobs/{job_id}DELETECancel running job

Sources: src/piloci/api/distillation_routes.py

Rate Limiting

The rate limiting module protects the API from abuse and ensures fair resource allocation across clients.

Rate Limit Configuration

ParameterDefaultDescription
Requests per minute60Maximum requests per client per minute
Burst allowance10Temporary burst capacity
Window typeSlidingRate limit window algorithm

Rate Limit Headers

HeaderDescription
X-RateLimit-LimitMaximum requests allowed
X-RateLimit-RemainingRequests remaining in window
X-RateLimit-ResetUnix timestamp when limit resets

Sources: src/piloci/api/ratelimit.py

Request/Response Patterns

Standard Response Format

{
  "success": true,
  "data": { },
  "meta": {
    "request_id": "uuid",
    "timestamp": "ISO8601"
  }
}

Error Response Format

{
  "success": false,
  "error": {
    "code": "ERROR_CODE",
    "message": "Human readable message"
  },
  "meta": {
    "request_id": "uuid",
    "timestamp": "ISO8601"
  }
}

Authentication

API routes require authentication via Bearer tokens in the Authorization header:

Authorization: Bearer <token>

Common Parameters

ParameterLocationTypeDescription
team_idPath/QuerystringTeam identifier
user_idPath/QuerystringUser identifier
pageQueryintegerPagination offset
page_sizeQueryintegerResults per page
sort_byQuerystringSort field
orderQuerystringSort direction (asc/desc)

Middleware Stack

graph TD
    A[Request] --> B[Rate Limit Middleware]
    B --> C[Auth Middleware]
    C --> D[Validation Middleware]
    D --> E[Route Handler]
    E --> F[Response]

Usage Examples

Creating a Team

curl -X POST https://api.example.com/v1/teams \
  -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "ML Research",
    "description": "Machine learning research team"
  }'

Listing Audit Events

curl -X GET "https://api.example.com/v1/audit/events?team_id=123&from=2024-01-01" \
  -H "Authorization: Bearer <token>"

Sources: src/piloci/api/routes.py

Curator Pipeline

Related topics: Storage Layer, MCP Server Implementation

Section Related Pages

Continue reading this section for the full explanation and source context.

Section Core Components

Continue reading this section for the full explanation and source context.

Section Stage 1: Backlog Management

Continue reading this section for the full explanation and source context.

Section Stage 2: Prefilter

Continue reading this section for the full explanation and source context.

Related topics: Storage Layer, MCP Server Implementation

Curator Pipeline

The Curator Pipeline is the core memory processing engine of piLoci. It transforms raw AI session transcripts into structured, embeddable memory entries through a multi-stage pipeline that includes extraction, distillation, prefiltering, budgeting, scheduling, and vault storage.

Overview

The curator system is designed to run on resource-constrained devices (such as Raspberry Pi 5) while leveraging both local ONNX-based inference (via fastembed) and external LLM APIs for complex memory extraction tasks. It operates as a background worker that continuously processes session backlog, respects resource constraints (temperature, load), and manages external API budgets.

graph TD
    A[Session Transcript Ingested] --> B[Backlog Queue]
    B --> C[Prefilter Stage]
    C --> D{Filter Pass?}
    D -->|No| E[Skip Memory Extraction]
    D -->|Yes| F[Distillation Worker]
    F --> G{Resource Available?}
    G -->|No| H[Wait/Reschedule]
    G -->|Yes| I[Extraction via Gemma/External LLM]
    I --> J[Budget Check]
    J -->|Over Budget| K[Bypass External LLM]
    J -->|OK| L[Store to Vault]
    L --> M[Embed + Index via LanceDB]
    M --> N[Memory Available for Recall]
    
    H --> B

Pipeline Architecture

The curator module is organized into distinct components, each responsible for a specific stage of the memory processing pipeline.

Core Components

ComponentFileResponsibility
Backlogbacklog.pyQueue management for pending session processing
Prefilterprefilter.pyFast-pass filtering before expensive extraction
DistillationWorkerdistillation_worker.pyOrchestrates the extraction workflow
Schedulerscheduler.pyResource-aware scheduling (temperature, load)
Budgetbudget.pyExternal LLM API budget tracking and limits
Extractionextraction.pyMemory extraction logic via Gemma or external LLM
Vaultvault.pyPersistent storage and retrieval of memories
WeeklyDigestWorkerweekly_digest_worker.pyPeriodic digest generation

Pipeline Stages

Stage 1: Backlog Management

The backlog system (Backlog class) maintains a queue of sessions awaiting memory extraction. Sessions enter the backlog when they are ingested, and are processed in FIFO order unless priority adjustments are applied.

Key operations:

  • Add new sessions to pending queue
  • Track processing state per session
  • Handle retry logic for failed extractions
  • Provide metrics for dashboard panels (pending count, processed count)

Sources: src/piloci/curator/backlog.py

Stage 2: Prefilter

The prefilter (Prefilter class) performs fast, lightweight checks to determine whether a session warrants full memory extraction. This prevents wasteful LLM calls on sessions that are unlikely to contain valuable memories.

Prefilter criteria may include:

  • Session length thresholds
  • Client type filtering (Claude Code vs OpenCode)
  • Project-specific rules
  • Temporal patterns

Sources: src/piloci/curator/prefilter.py

Stage 3: Resource-Aware Scheduling

The scheduler (Scheduler class) ensures that distillation work only proceeds when the host system has adequate resources. It monitors:

ParameterDescriptionDefault Behavior
Temperature CeilingSoC temperature thresholdWorker halts when exceeded
Load Average1-minute system loadWorker halts above threshold
Overflow ThresholdQueue depth before bypassTriggers external LLM bypass
# Distillation settings schema (from API)
class DistillationPreferences:
    temp_ceiling: float      # °C threshold
    load_ceiling: float      # 1-min load average
    overflow: int            # queue length threshold
    budget_monthly_usd: float # external LLM budget limit

Sources: src/piloci/curator/scheduler.py

Sources: web/lib/api.ts (DistillationPreferences type)

Stage 4: Budget Management

The budget system (Budget class) tracks external LLM API usage against configured monthly limits. When the budget is exhausted, the system bypasses external LLM calls and relies solely on local Gemma inference.

Budget lifecycle:

  1. Check current month-to-date spend
  2. Compare against configured limit
  3. Allow or block external LLM calls
  4. Track per-project allocation if applicable

Sources: src/piloci/curator/budget.py

Stage 5: Memory Extraction

The extraction stage (Extraction class) is the core of the pipeline. It analyzes session transcripts and extracts structured memories using either:

  1. Local Gemma Model - ONNX-based inference using fastembed
  2. External LLM API - Fallback when local resources insufficient or for complex extraction

#### Gemma Integration

The Gemma class wraps local Gemma model inference for on-device memory extraction:

  • Loads ONNX model for fast, private inference
  • No API calls required for basic extraction
  • Optimized for Raspberry Pi 5 hardware

Sources: src/piloci/curator/gemma.py

#### Extraction Pipeline

graph LR
    A[Transcript] --> B[Context Windowing]
    B --> C{Model Selection}
    C -->|Local| D[Gemma Inference]
    C -->|Complex| E[External LLM]
    D --> F[Parse Memory Structure]
    E --> F
    F --> G[Validate Memory Schema]
    G --> H[Return Memory Entries]

Extraction produces memory entries with:

  • content: The extracted memory text
  • tags: Categorization tags
  • project_id: Associated project scope
  • session_id: Source session reference
  • metadata: Extraction confidence, model used, timing

Sources: src/piloci/curator/extraction.py

Stage 6: Vault Storage

The vault (Vault class) provides persistent storage for extracted memories. Memories are stored with embeddings for similarity search and retrieval.

Storage architecture:

  • Primary storage: LanceDB for vector embeddings
  • Metadata index: SQLite for structured queries
  • File-based notes: Markdown files for Obsidian export
# Export workspace to Obsidian vault
curl -sS http://localhost:8314/api/projects/slug/my-project/workspace

Sources: src/piloci/curator/vault.py

Distillation Worker

The distillation worker (DistillationWorker class) orchestrates the entire pipeline. It runs as a background task that:

  1. Polls the backlog for pending sessions
  2. Applies prefilter checks
  3. Waits for resource availability via scheduler
  4. Executes extraction (Gemma → external LLM fallback)
  5. Stores results to vault
  6. Updates session status and metrics

Manual Trigger

The pipeline supports manual trigger via API:

// From web/lib/api.ts
runDistillationNow: () =>
  request<{ woken: boolean; note: string }>("/api/distillation/run-now", {
    method: "POST",
  }),

Sources: src/piloci/curator/distillation_worker.py

Weekly Digest

The weekly digest worker (WeeklyDigestWorker) generates periodic summaries of memory activity:

  • Aggregates memories created during the week
  • Generates project-level summaries
  • Creates digest notifications for users
  • Runs on configurable schedule (default: weekly)

Sources: src/piloci/curator/weekly_digest_worker.py

Configuration

Distillation Preferences

SettingTypeDescription
temp_ceilingfloatTemperature threshold (°C) for halting worker
load_ceilingfloatLoad average threshold for halting worker
overflowintQueue length threshold triggering external LLM bypass
budget_monthly_usdfloatMonthly budget for external LLM calls (USD)

API Endpoints

EndpointMethodDescription
/api/distillation/run-nowPOSTManually trigger distillation cycle
/api/preferencesGETRetrieve distillation preferences
/api/preferencesPATCHUpdate distillation preferences
/api/budget/usageGETGet current budget usage

Sources: web/lib/api.ts

State Machine

stateDiagram-v2
    [*] --> Idle
    Idle --> Checking: Session Ingested
    Checking --> PrefilterPass: Apply Prefilter
    PrefilterPass --> Idle: Filter Reject
    PrefilterPass --> Waiting: Filter Pass
    Waiting --> ResourceAvailable: Resource Check OK
    Waiting --> Idle: Resource Unavailable
    ResourceAvailable --> Extracting: Budget Available
    ResourceAvailable --> Bypassing: Budget Exhausted
    Extracting --> Storing: Extraction Complete
    Bypassing --> Storing: Fallback Complete
    Storing --> Idle: Store Success
    Storing --> Idle: Store Failure (Retry Later)

Module Exports

The curator package exposes its public API through __init__.py:

# src/piloci/curator/__init__.py
from .backlog import Backlog
from .distillation_worker import DistillationWorker
from .scheduler import Scheduler
from .budget import Budget
# ... etc

Sources: src/piloci/curator/__init__.py

Usage Scenarios

Scenario A: Auto-Capture on Raspberry Pi

The pipeline runs continuously on a Pi 5, processing sessions from connected Claude Code clients. Local Gemma inference handles most extractions without external API calls.

Scenario B: Bypass Mode (Budget Exhausted)

When monthly budget is exceeded, the system falls back to Gemma-only extraction. Quality may degrade but no external API costs are incurred.

Scenario C: Overflow Mode (High Demand)

When backlog exceeds the overflow threshold, the system immediately routes to external LLM to clear the queue faster, accepting the additional cost.

Tech Stack Integration

The Curator Pipeline integrates with piLoci's core technologies:

ComponentTechnologyRole in Pipeline
Embeddingsfastembed (ONNX)Gemma model inference
Vector StorageLanceDBMemory indexing
Session CacheRedisProcessing state
Identity DataSQLiteUser/project metadata
API ServerFastAPIPreference management, manual triggers

Sources: README.md (Tech Stack section)

Sources: src/piloci/curator/backlog.py

Storage Layer

Related topics: Database Models, Curator Pipeline, Technology Stack

Section Related Pages

Continue reading this section for the full explanation and source context.

Section Base Storage Interface

Continue reading this section for the full explanation and source context.

Section LanceDB Vector Store

Continue reading this section for the full explanation and source context.

Section Embedding Engine

Continue reading this section for the full explanation and source context.

Related topics: Database Models, Curator Pipeline, Technology Stack

Storage Layer

Overview

The Storage Layer is a core architectural component of piLoci responsible for persisting and retrieving structured memory data. It provides a multi-backend abstraction for vector storage, caching, embedding computation, and privacy-preserving data handling. The storage subsystem is designed to operate efficiently on resource-constrained devices like Raspberry Pi 5 while maintaining the ability to serve semantic search and recall capabilities for AI memory tools.

Architecture

The storage layer employs a layered architecture with distinct responsibilities for each module. At the foundation sits the base abstraction layer, with specialized implementations for vector search, caching, embedding, and domain-specific storage like instincts and privacy rules.

graph TD
    A[API Layer] --> B[Storage Interface]
    B --> C[LanceDB Store]
    B --> D[Cache Layer]
    B --> E[Instincts Store]
    B --> F[Privacy Store]
    C --> G[LanceDB]
    D --> H[Redis]
    F --> I[SQLite]
    J[Embed Engine] --> C
    J --> K[fastembed ONNX]

Module Structure

Base Storage Interface

The base module defines the core storage contract that all implementations must follow. This abstraction enables the system to swap backend implementations without affecting the API layer.

ComponentResponsibility
BaseStoreAbstract interface defining add, search, delete, and update operations
StorageErrorCustom exception type for storage-related failures
Connection poolingShared connection management across store instances

Sources: src/piloci/storage/base.py

LanceDB Vector Store

LanceDB serves as the primary vector storage backend for semantic memory search. The store handles high-dimensional embedding vectors with efficient similarity search capabilities.

FeatureDescription
Vector dimensionsConfigurable based on embedding model
Index typeLanceDB's optimized disk-based indices
Query typesTop-k similarity, range search, filtered search
PersistenceOn-disk storage with automatic compaction

Key Operations:

# Pseudocode representation of store operations
async def add_memory(memory_id, embedding, metadata):
    """Store a memory with its vector embedding"""
    
async def search_memories(query_embedding, top_k=10, filters=None):
    """Semantic search across stored memories"""
    
async def delete_memory(memory_id):
    """Remove a memory from the vector store"""

Sources: src/piloci/storage/lancedb_store.py Sources: docs/ADR-014-lancedb-backend.md

Embedding Engine

The embed module provides ONNX-based embedding computation using fastembed. This enables on-device inference without requiring external API calls or cloud GPU resources.

ConfigurationDefaultDescription
ModelfastembedONNX embedding model
Batch sizeEnvironment-definedProcessing batch size
DimensionModel-dependentOutput vector dimensions
DevicecpuCompute device (cpu/optional cuda)

Sources: src/piloci/storage/embed.py

Cache Layer

The cache module provides fast access to frequently queried data using Redis as the backing store. Cache invalidation is handled automatically based on TTL and mutation events.

Cache TargetTTLPurpose
Session data1 hourRecent conversation context
User preferences24 hoursUI and behavior settings
Query results15 minutesExpensive search operations

Sources: src/piloci/storage/cache.py

Privacy Store

The privacy module manages access control rules and data retention policies. It stores privacy configurations in SQLite for transactional integrity and fast lookups.

Privacy Rule TypeStorageAccess Pattern
Project isolationSQLiteRead-heavy
Field-level maskingSQLiteRead-heavy
Retention policiesSQLiteBalanced

Sources: src/piloci/storage/privacy.py

Instincts Store

The instincts store manages automatic behavior triggers (instincts) that users define for their memory system. Each instinct consists of a trigger condition and an associated action.

FieldTypeDescription
instinct_idUUIDUnique identifier
project_slugStringAssociated project scope
triggerStringCondition expression
actionStringAction to execute
domainStringApplication domain
instinct_countIntegerTrigger invocation count

Sources: src/piloci/storage/instincts_store.py

Data Flow

sequenceDiagram
    participant Client
    participant API
    participant Embed
    participant Store
    participant Cache
    
    Client->>API: Submit memory content
    API->>Embed: Compute embedding
    Embed-->>API: Vector embedding
    API->>Store: Store memory + embedding
    Store-->>API: Confirm storage
    API->>Cache: Invalidate related cache
    API-->>Client: Memory saved confirmation
    
    Client->>API: Search memories
    API->>Cache: Check cache
    alt Cache hit
        Cache-->>API: Cached results
    else Cache miss
        API->>Embed: Compute query embedding
        Embed-->>API: Query vector
        API->>Store: Vector similarity search
        Store-->>API: Matching memories
        API->>Cache: Store results
    end
    API-->>Client: Search results

Storage Backend Selection

The system uses multiple storage backends based on data characteristics:

Data TypeBackendRationale
Vector embeddingsLanceDBOptimized for ANN search, disk-based
Session dataRedisLow-latency key-value access
Identity/AuthSQLiteACID transactions, simple schema
Privacy rulesSQLiteRelational integrity requirements
InstinctsSQLiteStructured query needs

Sources: README.md Sources: docs/ADR-014-lancedb-backend.md

Configuration

Storage behavior is controlled through environment variables:

# Database paths
PILOCI_DATA_DIR=~/.local/share/piloci

# LanceDB configuration
LANCEDB_DB_PATH=./data/lancedb

# Redis connection
REDIS_URL=redis://localhost:6379/0

# Embedding configuration
EMBED_BATCH_SIZE=32
EMBED_DEVICE=cpu

Performance Characteristics

OperationExpected LatencyNotes
Memory add< 100msIncluding embedding
Semantic search< 200msTop-10 results
Cache lookup< 10msRedis hit
Privacy check< 5msSQLite index

Security Considerations

The storage layer implements several security measures:

  1. Project isolation: Memory data is scoped to projects, preventing cross-project data leakage
  2. Token-based access: All storage operations require valid authentication tokens
  3. Encrypted at rest: Sensitive fields can be encrypted before storage
  4. Audit logging: Storage mutations are logged for compliance

Sources: src/piloci/storage/privacy.py

Extension Points

The storage layer is designed for extensibility:

  • Custom stores: Implement BaseStore interface for new backends
  • Embedding models: Swap embedding providers via configuration
  • Cache backends: Replace Redis with alternative cache implementations
  • Privacy engines: Add custom privacy rule evaluators

Sources: src/piloci/storage/base.py

Database Models

Related topics: Storage Layer, Authentication & Security, API Routes

Section Related Pages

Continue reading this section for the full explanation and source context.

Section User Model

Continue reading this section for the full explanation and source context.

Section Project Model

Continue reading this section for the full explanation and source context.

Section Session/ingest Model

Continue reading this section for the full explanation and source context.

Related topics: Storage Layer, Authentication & Security, API Routes

Database Models

⚠️ Source Files Not Available in Current Context
The following source files referenced in this page could not be retrieved from the current repository context:
- src/piloci/db/models.py
- src/piloci/db/session.py
- scripts/init-db.py
This wiki page is based on available context and architecture information. For complete model definitions, please refer to the actual source files in the repository.

Overview

piLoci uses a multi-layered data architecture combining SQLite for identity and relational data, LanceDB for vector embeddings, and Redis for session management. This hybrid approach enables fast on-device inference while maintaining structured relationships between users, projects, and memory artifacts.

The database layer is located in src/piloci/db/ with initialization handled by scripts/init-db.py.

Storage Architecture

graph TD
    subgraph "piLoci Data Layer"
        SQLite[(SQLite<br/>Identity Data)]
        LanceDB[(LanceDB<br/>Vector Store)]
        Redis[(Redis<br/>Sessions)]
        ONNX[ONNX Runtime<br/>fastembed]
    end
    
    SQLite -->|User/Project| API
    LanceDB -->|Embeddings| API
    Redis -->|Session Cache| API
    API -->|Inference| ONNX

Technology Stack

ComponentTechnologyPurposeLocation
Identity DataSQLiteUser accounts, projects, permissionssrc/piloci/db/
Vector StorageLanceDBMemory embeddings, similarity searchVector index
Session ManagementRedisActive session state, cachingExternal service
Embedding Enginefastembed (ONNX)Local inferencesrc/piloci/

Sources: README.md

Database Initialization

The scripts/init-db.py script handles initial database setup:

# From project root
python scripts/init-db.py

This script creates the necessary SQLite tables and initializes LanceDB indices if they don't exist.

Key Models (Schema Reference)

Based on the application architecture observed in the codebase:

User Model

  • id (Primary Key)
  • email
  • password_hash
  • created_at
  • updated_at
  • is_admin

Project Model

  • id (Primary Key)
  • slug (Unique identifier)
  • name
  • user_id (Foreign Key)
  • created_at

Session/ingest Model

  • ingest_id (Primary Key)
  • user_id (Foreign Key)
  • project_slug (Optional)
  • client (Claude Code, OpenCode, etc.)
  • created_at
  • processed_at
  • memories_extracted
  • error (Optional)

Memory/Instinct Model

  • memory_id / instinct_id (Primary Key)
  • project_slug
  • content
  • embedding (Vector)
  • trigger (For instincts)
  • action (For instincts)
  • domain
  • instinct_count

Sources: web/components/DashboardSummaryPanels.tsx Sources: web/components/ProjectSessionsPanel.tsx

Query Patterns

The API layer (src/piloci/api/routes.py) exposes database operations through REST endpoints:

EndpointOperationDescription
GET /api/projectsListFetch user's projects
GET /api/projects/{id}ReadFetch project details
POST /api/memoriesCreateStore new memory
GET /api/projects/{slug}/workspaceReadGet workspace notes

Sources: README.md Sources: MEMORY.md

Configuration

Database configuration is managed through src/piloci/config.py:

# Example configuration keys
DATABASE_URL = "sqlite:///./piloci.db"
REDIS_URL = "redis://localhost:6379"
LANCEDB_PATH = "./data/embeddings"

Vector Storage Details

LanceDB stores embeddings with the following characteristics:

  • Index Type: LanceDB (columnar format)
  • Embedding Model: fastembed (ONNX-based, runs locally)
  • Use Case: Semantic search for memories and instincts

Sources: README.md

Sources: README.md

Web Dashboard

Related topics: Workspace UI & Team Features, Technology Stack, Authentication & Security

Section Related Pages

Continue reading this section for the full explanation and source context.

Section Tech Stack

Continue reading this section for the full explanation and source context.

Section Component Hierarchy

Continue reading this section for the full explanation and source context.

Section Page Layout Pattern

Continue reading this section for the full explanation and source context.

Related topics: Workspace UI & Team Features, Technology Stack, Authentication & Security

Web Dashboard

Overview

The Web Dashboard is the primary user-facing interface for the piLoci system, built as a Next.js 14+ application with TypeScript and React. It provides authenticated users with a comprehensive view of their AI session memories, project workspaces, token management, and system administration capabilities.

The dashboard implements a server-side rendering (SSR) architecture where pages prefetch user data server-side, enabling fast initial loads and proper authentication checks before rendering protected routes.

Architecture

Tech Stack

LayerTechnologyPurpose
FrameworkNext.js 14+ (App Router)Server-side rendering, routing, API routes
UI Componentsshadcn/ui + Radix UIAccessible, composable components
StylingTailwind CSSUtility-first styling with design tokens
State ManagementReact Context + Server ComponentsAuth state and server-fetched data
Data FetchingServer Actions + fetch APIBackend communication

Component Hierarchy

graph TD
    A["<AppShell>"] --> B["Navigation Bar"]
    A --> C["Main Content Area"]
    A --> D["Footer/Sidebar"]
    
    C --> E["<DashboardSummaryPanels>"]
    C --> F["<ProjectListView>"]
    C --> G["<TokenManager>"]
    C --> H["<DistillationSettingsPanel>"]
    
    E --> I["<PanelCard>"]
    E --> J["<Pager>"]
    
    F --> K["Project Cards"]
    F --> L["Create Project Dialog"]
    
    G --> M["Token List Table"]
    G --> N["CopyBlock Components"]
    G --> O["Tabbed Setup Instructions"]

Page Layout Pattern

All dashboard pages follow a consistent layout pattern defined in DESIGN-HARNESS.md:

<AppShell>
  <div className="pi-page">
    <section className="pi-page-hero">
      <p className="pi-eyebrow">Area label</p>
      <h1 className="pi-title mt-2">Page title</h1>
      <p className="pi-subtitle">One sentence explaining the page.</p>
    </section>

    <section className="grid gap-3 sm:grid-cols-3">
      <div className="pi-metric-card">...</div>
    </section>

    <section className="pi-panel p-3">...</section>
  </div>
</AppShell>

Authentication System

Authentication Flow

sequenceDiagram
    participant User
    participant Browser
    participant NextAuth
    participant Google OAuth
    participant Backend API
    
    User->>Browser: Visit protected page
    Browser->>NextAuth: Check session
    NextAuth->>Browser: No session
    Browser->>User: Redirect to /login
    User->>Browser: Click "Sign in with Google"
    Browser->>Google OAuth: OAuth request
    Google OAuth->>User: Login prompt
    User->>Google OAuth: Authenticate
    Google OAuth->>Browser: Callback with code
    Browser->>NextAuth: Exchange code for session
    NextAuth->>Backend API: Validate/create user
    Backend API->>NextAuth: User data
    NextAuth->>Browser: Session cookie
    Browser->>User: Redirect to dashboard

Auth Configuration

The authentication system is configured in web/lib/auth.ts and uses NextAuth.js with Google OAuth provider:

SettingDescriptionEnvironment Variable
ProviderGoogle OAuth 2.0AUTH_GOOGLE_ID, AUTH_GOOGLE_SECRET
Base URLApplication root for callbacksBASE_URL
Session StrategyJWT-based sessionsN/A
CallbacksCustom session/user callbacksN/A

Protected Routes

Protected pages use a shared authentication pattern:

// In page components (e.g., web/app/dashboard/page.tsx)
const user = await getCurrentUser();
if (!user) {
  redirect("/login");
}

This pattern is consistent across all protected pages including:

  • /dashboard - Main user dashboard
  • /projects - Project workspace
  • /settings - User settings
  • /admin/* - Admin-only pages

Core Components

AppShell

AppShell is the root authenticated layout component that wraps all protected pages. It provides:

FeatureImplementation
BackgroundAuthenticated shell background with glass effect
NavigationTop navigation bar with user menu
User InfoUser display with email and role
Quick LinksDashboard, Projects, Settings navigation
Role-Based AccessAdmin menu visible only to admin users

DashboardSummaryPanels

The main dashboard view displays aggregated statistics and recent activity:

PanelData SourceComponents
Summary StatsUser stats APIpi-metric-card with icons
Top TagsTag frequency aggregationBadges with counts
Recent SessionsSession list with pagination<Pager> component

PanelCard

A reusable card component for dashboard sections:

<PanelCard
  icon={FileText}
  title="Panel Title"
  footer={<Pager {...pagerProps} />}
>
  {content}
</PanelCard>

ProjectListView

Manages project creation and listing:

FeatureDescription
Project GridResponsive grid layout (sm:2, lg:3 columns)
Create DialogModal form for new project creation
Loading StateSkeleton placeholders during fetch
Error StateRetry button on fetch failure

TokenManager

Handles API token lifecycle management:

FeatureDescription
Token ListTable with name, scope, creation date
Scope BadgesUser vs Project scope indicators
Install StatusShows installed clients and hostname
Setup InstructionsTabbed guides for Claude Desktop, Claude Code, OpenCode, Cursor

ProjectSessionsPanel

Displays ingest sessions for a project:

FeatureImplementation
Session CardsExpandable cards with transcript viewer
Status BadgesClient, status, timestamp display
Error DisplayRed text for failed sessions
Transcript ViewerLazy-loaded transcript content

API Integration

API Client

The API client in web/lib/api.ts handles all backend communication:

// Authentication header injection
const headers = {
  'Authorization': `Bearer ${session?.accessToken}`,
  'Content-Type': 'application/json',
};

// Server-side data fetching pattern
const response = await fetch(`${API_BASE_URL}/endpoint`, {
  headers,
  credentials: 'include',
});

API Endpoints Used

Endpoint PatternPurposeAuth Required
/api/usersUser managementAdmin
/api/projectsProject CRUDYes
/api/projects/:slug/sessionsSession listingYes
/api/tokensToken managementYes
/api/ingest/:id/transcriptTranscript fetchYes

Server-Side Data Fetching

Dashboard pages use a server-first data fetching pattern:

// web/app/dashboard/page.tsx pattern
export default async function DashboardPage() {
  const user = await getCurrentUser();
  if (!user) redirect("/login");

  const [stats, tags, sessions] = await Promise.all([
    fetchUserStats(),
    fetchTopTags(),
    fetchRecentSessions(),
  ]);

  return <DashboardSummaryPanels stats={stats} tags={tags} sessions={sessions} />;
}

Design System

piLoci Design Tokens

The project uses custom CSS variables for consistent styling:

TokenUsageExample
--pi-shadowCard shadowsBox elevation
--pi-shadow-smSmall element shadowsButtons, badges
--pi-primaryPrimary brand colorCTAs, links

Pattern Classes

ClassPurposeLocation
pi-pagePage container wrapperAll pages
pi-page-heroTitle/subtitle sectionAll pages
pi-eyebrowCategory labelPage headers
pi-titleMain page titleH1 elements
pi-subtitlePage descriptionIntro text
pi-metric-cardStatistics cardsDashboard panels
pi-panelContent containersLists, forms
pi-icon-cellIcon + color wrapperMetric cards

Responsive Breakpoints

BreakpointColumnsComponents Shown
Mobile1Essential info only
sm (640px)2-3Expanded cards
md (768px)3Full tables
lg (1024px)4Two-column grids

Page Routes

Route Structure

graph TD
    A[" / "] --> B[" Landing Page"]
    A --> C[" / login"]
    C --> D[" Google OAuth"]
    A --> E[" / signup"]
    A --> F[" / terms"]
    A --> G[" / privacy"]
    
    H[" Authenticated Routes"] --> I[" / dashboard"]
    H --> J[" / projects"]
    H --> K[" / settings"]
    H --> L[" / settings/tokens"]
    
    M[" Admin Routes"] --> N[" / admin/users"]
    
    style H fill:#e1eff6
    style M fill:#ffe6e6

Dashboard Pages

RoutePurposeMain Components
/dashboardMain user dashboardDashboardSummaryPanels
/projectsProject workspaceProjectListView, ProjectSessionsPanel
/settingsUser preferencesDistillationSettingsPanel
/settings/tokensAPI token managementTokenManager
/admin/usersUser administrationUser statistics table

State Management

Auth State

Authentication state is managed through NextAuth.js:

// Client-side auth access
const { data: session } = useSession();

// Server-side auth check
const session = await getServerSession(authOptions);

Loading States

All data-fetching components implement loading states:

{isLoading ? (
  <div className="space-y-1.5">
    {[1, 2, 3, 4].map((i) => (
      <Skeleton key={i} className="h-10 w-full" />
    ))}
  </div>
) : null}

Error Handling

Error states display retry options:

{isError ? (
  <Card>
    <CardContent className="flex flex-col items-center gap-4 py-12">
      <RefreshCcw className="size-8 text-muted-foreground" />
      <p className="text-sm text-muted-foreground">Error loading data</p>
      <Button variant="outline" onClick={() => refetch()}>
        {t.dashboard.error.retry}
      </Button>
    </CardContent>
  </Card>
) : null}

Internationalization

The application uses a translation system (likely next-intl) with keys structured by page:

NamespaceUsage
landingLanding page content
authLayoutAuth page headers/footers
dashboardDashboard labels and messages
adminAdmin page content
tokenManagerToken management strings
projectsProject page content

Security Considerations

Route Protection

All sensitive routes check authentication before rendering:

// Pattern used in all protected pages
const user = await getCurrentUser();
if (!user) {
  redirect("/login");
}

Role-Based Access

Admin routes check for admin role:

if (user.role !== "admin") {
  redirect("/dashboard");
}

Token Handling

  • Tokens are transmitted via HTTP-only cookies or Authorization headers
  • API keys are never exposed in client-side code
  • Install codes are single-use with 10-minute expiration

Source: https://github.com/jshsakura/oc-piloci / Human Manual

Workspace UI & Team Features

Related topics: Web Dashboard, Curator Pipeline

Section Related Pages

Continue reading this section for the full explanation and source context.

Section Project Workspace (web/app/projects/page.tsx)

Continue reading this section for the full explanation and source context.

Section Team Management (web/app/teams/page.tsx)

Continue reading this section for the full explanation and source context.

Section Project Sessions Panel (web/components/ProjectSessionsPanel.tsx)

Continue reading this section for the full explanation and source context.

Related topics: Web Dashboard, Curator Pipeline

Workspace UI & Team Features

Overview

The Workspace UI & Team Features module in piLoci provides a comprehensive interface for managing projects, teams, and collaborative memory curation. This system enables users to organize AI-assisted memory sessions into project-based workspaces, view memory graphs, manage vault notes, and collaborate with team members through shared access tokens and session tracking.

The workspace architecture follows a project-scoped model where memories are isolated per project, allowing both individual users and teams to maintain separate knowledge bases while benefiting from shared curated content.

Architecture Overview

graph TD
    A[User Dashboard] --> B[Project Workspace]
    A --> C[Team Management]
    B --> D[Memory Graph Panel]
    B --> E[Vault Notes]
    B --> F[Session Sessions]
    C --> G[Token Manager]
    C --> H[Team Members]
    F --> I[Transcript Viewer]
    D --> J[Memory Tags]
    E --> K[Note Links]

Core Components

Project Workspace (`web/app/projects/page.tsx`)

The project workspace serves as the central hub for managing project-specific memories and settings. It provides:

  • Project listing with slug-based navigation
  • Workspace view with notes and relationships per project
  • Session history and memory extraction metrics

Key Features:

  • Slug-based project routing (/projects/?slug={slug})
  • Integration with ProjectListView.tsx for listing projects
  • Dashboard summary panels for quick metrics

Sources: web/app/projects/page.tsx

Team Management (`web/app/teams/page.tsx`)

The team page enables users to manage collaborative workspaces and invite team members. Team features include:

  • Team member listing with roles and permissions
  • Shared project access control
  • Token-based client installation for team members

Sources: web/app/teams/page.tsx

Session Management

Project Sessions Panel (`web/components/ProjectSessionsPanel.tsx`)

The ProjectSessionsPanel displays historical AI client sessions within a project context.

Component Structure:

<div className="flex flex-col gap-3">
  <Card>
    <CardHeader className="pb-2">
      <div className="flex items-center justify-between">
        {/* Session header */}
      </div>
    </CardHeader>
    <CardContent>
      {/* Expandable transcript viewer */}
    </CardContent>
  </Card>
</div>

Session Display Elements:

ElementDescription
Client BadgeShows client type (e.g., Claude Desktop, Claude Code, OpenCode)
StatusProcessing status with timestamps
Memory CountExtracted memories count or pending indicator
Error DisplaySession errors in red text
TranscriptExpandable transcript viewer

Session Metadata Display:

<div className="flex flex-wrap items-center gap-1.5 text-[11px] text-muted-foreground">
  <Badge variant="outline" className="text-[10px]">{s.client}</Badge>
  <span>{meta}</span>
  <span>·</span>
  <span>{status}</span>
  <span>·</span>
  <span>{fmt(s.created_at)}</span>
</div>

Transcript Expansion:

  • Toggle button with chevron icons (up/down)
  • TranscriptViewer component renders full session transcript
  • State management via isExp boolean mapped to ingest_id

Sources: web/components/ProjectSessionsPanel.tsx:1-60

Dashboard Summary Panels (`web/components/DashboardSummaryPanels.tsx`)

The dashboard provides aggregated views of project activity across all workspaces.

Panel Types:

PanelIconContent
Recent SessionsFileTextLast processed sessions with memory counts
Top TagsSparklesMost used memory tags with usage frequency
Project StatsVariesMetrics per project

Recent Sessions Entry:

<li className="flex flex-wrap items-center justify-between gap-2 py-2 text-xs">
  <div className="flex min-w-0 items-center gap-2">
    <Link href={`/projects/?slug=${s.project_slug}`}>
      {s.project_name}
    </Link>
    <span className="text-muted-foreground">
      {s.processed_at
        ? summary.sessionMemories.replace("{count}", String(s.memories_extracted))
        : summary.sessionPending}
    </span>
  </div>
  <span className="text-muted-foreground">{timeFmt(s.created_at)}</span>
</li>

Tag Display with Pager:

<div className="flex flex-wrap gap-1.5">
  {tagPager.slice.map((tag) => (
    <Badge key={tag.tag} variant="secondary" className="break-all">
      #{tag.tag} <span className="ms-1 opacity-60 tabular-nums">×{tag.count}</span>
    </Badge>
  ))}
</div>

Sources: web/components/DashboardSummaryPanels.tsx:1-80

Memory Visualization

Memory Graph Panel

The Memory Graph Panel provides a visual representation of memory relationships within a project. Based on the design guidelines, future graph UI should:

  • Keep current landing preview dependency-free
  • Prefer React Flow for polished interactive curated-memory graphs
  • Reserve Sigma.js/WebGL for large workspace graphs if React Flow hits node-count limits

Sources: MEMORY.md

Vault Notes System

Vault Note Detail (`web/components/VaultNoteDetail.tsx`)

The vault notes system displays individual memories with their metadata, tags, and inter-note relationships.

Note Display Structure:

<div className="space-y-3">
  {/* Header with title */}
  <div>
    <h2 className="text-xl font-semibold">{note.title}</h2>
    {note.tags?.length > 0 && (
      <div className="flex flex-wrap gap-1.5 mt-2">
        {/* Tag badges */}
      </div>
    )}
  </div>
  
  {/* Path display */}
  <div className="break-all rounded-md bg-muted px-3 py-2 font-mono text-xs">
    {note.path}
  </div>
  
  {/* Content */}
  <pre className="whitespace-pre-wrap break-all">
    {note.markdown ?? note.excerpt}
  </pre>
  
  {/* Linked notes */}
  {note.links.length > 0 && <LinkedNotesSection />}
</div>

Note Metadata Fields:

FieldTypeDescription
titlestringNote title
pathstringFile system path
markdownstringFull markdown content
excerptstringShort preview text
tagsstring[]Associated tags
linksstring[]Related note paths

Linked Notes Section:

<Separator className="my-4" />
<div>
  <p className="mb-2 text-sm font-medium text-muted-foreground">
    {t.vaultNote.linkedNotes}
  </p>
  <div className="flex flex-wrap gap-1.5">
    {note.links.map((link) => (
      <Badge key={link} variant="outline">{link}</Badge>
    ))}
  </div>
</div>

Sources: web/components/VaultNoteDetail.tsx:1-50

Obsidian Export

The workspace system supports export to Obsidian vaults:

curl -OJ http://localhost:8314/api/vault/my-project/export

Export Process:

  1. Fetch workspace data from /api/projects/slug/{slug}/workspace
  2. Create project directory structure in ~/.config/piloci/projects/slug/{slug}/workspace
  3. Write each workspace.notes[].markdown to corresponding workspace.notes[].path
  4. Open directory as Obsidian vault or sync to existing vault

Sources: README.md

Team Collaboration

Token Manager (`web/components/TokenManager.tsx`)

The Token Manager provides a UI for generating and managing API tokens for team members.

Supported Client Types:

ClientConfig FileFeatures
Claude Desktop~/Library/Application Support/Claude/claude_desktop_config.jsonMCP server + hooks
Claude Code~/.claude.json / .mcp.jsonMCP server + auto-capture hooks
OpenCodeopencode.jsonMCP server only

Token Installation Status:

{token.installed_at ? (
  <span className="text-[11px] text-muted-foreground">
    {t.tokenManager.installedOn} {formatDate(token.installed_at)}
    {token.client_kinds && token.client_kinds.length > 0 && (
      <> · {token.client_kinds.join(" + ")}</>
    )}
    {token.hostname && <> · {token.hostname}</>}
  </span>
) : (
  <span className="text-[11px] text-muted-foreground/70">
    {t.tokenManager.notInstalled}
  </span>
)}

Token Scope Badge:

<Badge variant={token.scope === "user" ? "default" : "secondary"}>
  {token.scope}
</Badge>

Installation Methods:

``bash piloci login piloci install ``

  1. CLI Installation:

``bash curl -sSL https://piloci.example.com/install/<install_code> | bash ``

  1. One-line Bash:

```bash # Step 1: Install hook piloci hook install

  1. Manual Hook Setup:

# Step 2: Configure client # Copy generated JSON to client config file ```

Sources: web/components/TokenManager.tsx:1-100

Client-Side Setup

What the Connection Does:

Hook Behavior by Client:

ClientSessionStart HookSessionStop Hook
Claude CodeCatch-up batch retrieveLive push each turn
OpenCodeN/A (no hook mechanism)N/A

Sources: README.ko.md

Project Management

Project Knacks Panel (`web/components/ProjectKnacksPanel.tsx`)

The Project Knacks Panel displays project-specific insights and instinct metrics.

Instinct Display:

<div className="flex items-center gap-2">
  <Badge variant="outline" className="text-[10px]">
    {i.domain}
  </Badge>
  <span className="tabular-nums">×{i.instinct_count}</span>
</div>

Sources: web/components/ProjectKnacksPanel.tsx

Distillation Settings (`web/components/DistillationSettingsPanel.tsx`)

Project-level settings control memory processing behavior:

SettingTypeDescription
Temperature Ceiling°CWorker stops when SoC temp exceeds threshold
Load CeilingfloatWorker stops when load avg exceeds threshold
Overflow LimitnumberOptional external bypass cap

Sources: web/components/DistillationSettingsPanel.tsx:1-60

API Integration

Memory API

The backend exposes project-scoped memory endpoints:

Endpoint: POST /api/memories

Features:

  • Uses existing embed/store pipeline
  • Project-scoped isolation
  • Memory extraction from session transcripts

Sources: MEMORY.md

Workspace Export API

Endpoint: GET /api/projects/slug/{slug}/workspace

Returns workspace data including notes, paths, and relationships for Obsidian export.

Usage Scenarios

Scenario A — Team Project Memory Hub

A small team sets up one piLoci instance on shared hardware. Each member creates an account, joins shared projects, and stores memories via MCP tools. Project isolation keeps unrelated work separate while everyone benefits from the shared knowledge base.

Scenario B — Multi-Project Workspace

A solo developer or researcher runs several projects (thesis research, side project, client work) on one piLoci. Each project's memories stay isolated, and the workspace viewer shows notes and relationships per project.

Scenario C — Obsidian Export

Generate workspace notes and export to an Obsidian vault via simple API call for teams who want to curate knowledge in Obsidian after collection.

Page Design Patterns

Following the piLoci design harness guidelines:

<AppShell>
  <div className="pi-page">
    <section className="pi-page-hero">
      <p className="pi-eyebrow">Area label</p>
      <h1 className="pi-title mt-2">Page title</h1>
      <p className="pi-subtitle">One sentence explaining the page.</p>
    </section>

    <section className="grid gap-3 sm:grid-cols-3">
      <div className="pi-metric-card">...</div>
    </section>

    <section className="pi-panel p-3">...</section>
  </div>
</AppShell>

Design Classes:

ClassUsage
pi-pageMain page container
pi-page-heroHero section with title and subtitle
pi-eyebrowSmall label above title
pi-titlePage title (H1)
pi-subtitleDescriptive subtitle
pi-metric-cardMetric display cards
pi-panelContent panels with consistent styling

Sources: web/DESIGN-HARNESS.md

Sources: web/app/projects/page.tsx

Doramagic Pitfall Log

Source-linked risks stay visible on the manual page so the preview does not read like a recommendation.

medium Developers should check this installation risk before relying on the project: Release v0.3.61

Upgrade or migration may change expected behavior: Release v0.3.61

medium Developers should check this installation risk before relying on the project: Release v0.3.62

Upgrade or migration may change expected behavior: Release v0.3.62

medium Developers should check this installation risk before relying on the project: Release v0.3.63

Upgrade or migration may change expected behavior: Release v0.3.63

medium Developers should check this installation risk before relying on the project: Release v0.3.64

Upgrade or migration may change expected behavior: Release v0.3.64

Doramagic Pitfall Log

Doramagic extracted 16 source-linked risk signals. Review them before installing or handing real data to the project.

1. Installation risk: Developers should check this installation risk before relying on the project: Release v0.3.61

  • Severity: medium
  • Finding: Developers should check this installation risk before relying on the project: Release v0.3.61
  • User impact: Upgrade or migration may change expected behavior: Release v0.3.61
  • Recommended check: Before packaging this project, run the relevant install/config/quickstart check for: Release v0.3.61. Context: Observed when using docker
  • Evidence: failure_mode_cluster:github_release | fmev_238385c7d11f6862a1b9d0c024a94181 | https://github.com/jshsakura/oc-piloci/releases/tag/v0.3.61 | Release v0.3.61

2. Installation risk: Developers should check this installation risk before relying on the project: Release v0.3.62

  • Severity: medium
  • Finding: Developers should check this installation risk before relying on the project: Release v0.3.62
  • User impact: Upgrade or migration may change expected behavior: Release v0.3.62
  • Recommended check: Before packaging this project, run the relevant install/config/quickstart check for: Release v0.3.62. Context: Observed when using docker
  • Evidence: failure_mode_cluster:github_release | fmev_115c2527b334fad79621b999d3e94857 | https://github.com/jshsakura/oc-piloci/releases/tag/v0.3.62 | Release v0.3.62

3. Installation risk: Developers should check this installation risk before relying on the project: Release v0.3.63

  • Severity: medium
  • Finding: Developers should check this installation risk before relying on the project: Release v0.3.63
  • User impact: Upgrade or migration may change expected behavior: Release v0.3.63
  • Recommended check: Before packaging this project, run the relevant install/config/quickstart check for: Release v0.3.63. Context: Observed when using docker
  • Evidence: failure_mode_cluster:github_release | fmev_348782b397ba2bb56859e630ea890c99 | https://github.com/jshsakura/oc-piloci/releases/tag/v0.3.63 | Release v0.3.63

4. Installation risk: Developers should check this installation risk before relying on the project: Release v0.3.64

  • Severity: medium
  • Finding: Developers should check this installation risk before relying on the project: Release v0.3.64
  • User impact: Upgrade or migration may change expected behavior: Release v0.3.64
  • Recommended check: Before packaging this project, run the relevant install/config/quickstart check for: Release v0.3.64. Context: Observed when using docker
  • Evidence: failure_mode_cluster:github_release | fmev_a5608f313037217768976fadbcbd00e3 | https://github.com/jshsakura/oc-piloci/releases/tag/v0.3.64 | Release v0.3.64

5. Installation risk: Developers should check this installation risk before relying on the project: Release v0.3.65

  • Severity: medium
  • Finding: Developers should check this installation risk before relying on the project: Release v0.3.65
  • User impact: Upgrade or migration may change expected behavior: Release v0.3.65
  • Recommended check: Before packaging this project, run the relevant install/config/quickstart check for: Release v0.3.65. Context: Observed when using docker
  • Evidence: failure_mode_cluster:github_release | fmev_593467b90b436b99ecac227152d65f93 | https://github.com/jshsakura/oc-piloci/releases/tag/v0.3.65 | Release v0.3.65

6. Installation risk: Developers should check this installation risk before relying on the project: Release v0.3.66

  • Severity: medium
  • Finding: Developers should check this installation risk before relying on the project: Release v0.3.66
  • User impact: Upgrade or migration may change expected behavior: Release v0.3.66
  • Recommended check: Before packaging this project, run the relevant install/config/quickstart check for: Release v0.3.66. Context: Observed when using docker
  • Evidence: failure_mode_cluster:github_release | fmev_41cea4cedb6fe85b101b1ee1e744a2a2 | https://github.com/jshsakura/oc-piloci/releases/tag/v0.3.66 | Release v0.3.66

7. Installation risk: Developers should check this installation risk before relying on the project: Release v0.3.67

  • Severity: medium
  • Finding: Developers should check this installation risk before relying on the project: Release v0.3.67
  • User impact: Upgrade or migration may change expected behavior: Release v0.3.67
  • Recommended check: Before packaging this project, run the relevant install/config/quickstart check for: Release v0.3.67. Context: Observed when using docker
  • Evidence: failure_mode_cluster:github_release | fmev_51ad1a6fbbb3b6c3fdc1be72bcfae7ea | https://github.com/jshsakura/oc-piloci/releases/tag/v0.3.67 | Release v0.3.67

8. Installation risk: Developers should check this installation risk before relying on the project: Release v0.3.68

  • Severity: medium
  • Finding: Developers should check this installation risk before relying on the project: Release v0.3.68
  • User impact: Upgrade or migration may change expected behavior: Release v0.3.68
  • Recommended check: Before packaging this project, run the relevant install/config/quickstart check for: Release v0.3.68. Context: Observed when using docker
  • Evidence: failure_mode_cluster:github_release | fmev_7bc0641dd202d881746e1010d1b03fe5 | https://github.com/jshsakura/oc-piloci/releases/tag/v0.3.68 | Release v0.3.68

9. Installation risk: Developers should check this installation risk before relying on the project: Release v0.3.69

  • Severity: medium
  • Finding: Developers should check this installation risk before relying on the project: Release v0.3.69
  • User impact: Upgrade or migration may change expected behavior: Release v0.3.69
  • Recommended check: Before packaging this project, run the relevant install/config/quickstart check for: Release v0.3.69. Context: Observed when using docker
  • Evidence: failure_mode_cluster:github_release | fmev_ba1666889342a143a76dda2fa013ddf2 | https://github.com/jshsakura/oc-piloci/releases/tag/v0.3.69 | Release v0.3.69

10. Installation risk: Developers should check this installation risk before relying on the project: Release v0.3.70

  • Severity: medium
  • Finding: Developers should check this installation risk before relying on the project: Release v0.3.70
  • User impact: Upgrade or migration may change expected behavior: Release v0.3.70
  • Recommended check: Before packaging this project, run the relevant install/config/quickstart check for: Release v0.3.70. Context: Observed when using docker
  • Evidence: failure_mode_cluster:github_release | fmev_18504a4306cc5d44261e6d0f5ec47f54 | https://github.com/jshsakura/oc-piloci/releases/tag/v0.3.70 | Release v0.3.70

11. Installation risk: Developers should check this installation risk before relying on the project: Release v0.3.71

  • Severity: medium
  • Finding: Developers should check this installation risk before relying on the project: Release v0.3.71
  • User impact: Upgrade or migration may change expected behavior: Release v0.3.71
  • Recommended check: Before packaging this project, run the relevant install/config/quickstart check for: Release v0.3.71. Context: Observed when using docker
  • Evidence: failure_mode_cluster:github_release | fmev_4f40f1505195306061984312ceafb8d8 | https://github.com/jshsakura/oc-piloci/releases/tag/v0.3.71 | Release v0.3.71

12. Installation risk: Developers should check this installation risk before relying on the project: Release v0.3.72

  • Severity: medium
  • Finding: Developers should check this installation risk before relying on the project: Release v0.3.72
  • User impact: Upgrade or migration may change expected behavior: Release v0.3.72
  • Recommended check: Before packaging this project, run the relevant install/config/quickstart check for: Release v0.3.72. Context: Observed when using docker
  • Evidence: failure_mode_cluster:github_release | fmev_a62aef6e3f8ef8401a1d0bb3ce5d66d5 | https://github.com/jshsakura/oc-piloci/releases/tag/v0.3.72 | Release v0.3.72

Source: Doramagic discovery, validation, and Project Pack records

Community Discussion Evidence

These external discussion links are review inputs, not standalone proof that the project is production-ready.

Sources 12

Count of project-level external discussion links exposed on this manual page.

Use Review before install

Open the linked issues or discussions before treating the pack as ready for your environment.

Community Discussion Evidence

Doramagic exposes project-level community discussion separately from official documentation. Review these links before using oc-piloci with real data or production workflows.

Source: Project Pack community evidence and pitfall evidence