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
Continue reading this section for the full explanation and source context.
Continue reading this section for the full explanation and source context.
Continue reading this section for the full explanation and source context.
Continue reading this section for the full explanation and source context.
Related Pages
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
| Aspect | Description |
|---|---|
| Privacy | Self-hosted on local hardware; no data leaves your network |
| Automatic | Silent capture of sessions without manual intervention |
| Project-scoped | Memories organized by project for clean isolation |
| MCP-enabled | Native 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 <--> WebUITechnology Stack
| Component | Technology | Purpose |
|---|---|---|
| Backend | Python | MCP-enabled API server |
| Identity DB | SQLite | User accounts, projects, sessions |
| Vector Store | LanceDB | Embedded memory storage |
| Session Cache | Redis | Session state management |
| Embeddings | FastEmbed (ONNX) | Fast on-device inference |
| Frontend | Next.js | Web 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
| Page | Component | Purpose |
|---|---|---|
| Dashboard | app/dashboard/page.tsx + DashboardSummaryPanels.tsx | User overview with metrics |
| Admin Console | app/admin/users/page.tsx | User management |
| Project Workspace | app/projects/page.tsx + ProjectListView.tsx | Project-level memory access |
| Privacy | app/privacy/page.tsx | Privacy policy |
| Terms | app/terms/page.tsx | Terms of service |
Sources: DESIGN-HARNESS.md
Client Connection Flow
Supported Clients
piLoci integrates with multiple AI coding assistants through MCP:
| Client | Session Capture | MCP Tools |
|---|---|---|
| Claude Code | SessionStart/Stop hooks | memory, recall, recommend |
| Claude Desktop | Static config | memory, recall, recommend |
| OpenCode | Static config only | memory, recall, recommend |
| Cursor | Static config | memory, 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 availableWhat 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:
| Command | Description |
|---|---|
piloci login | Authenticate with the server (OAuth or install code) |
piloci install | Install MCP server and hooks for AI clients |
piloci uninstall | Remove all piLoci artifacts, optionally restore backups |
piloci restore | Restore client configs from .piloci-bak snapshots |
piloci backfill-cwd | Fix legacy slug-collision bug in session data |
Install Command Options
| Flag | Purpose |
|---|---|
--server | Override server URL when only install code is provided |
--token | Use token directly instead of resolving URL |
--force | Wipe existing plugin folders and reinstall fresh |
Uninstall Command Options
| Flag | Purpose |
|---|---|
--yes | Skip confirmation prompt |
--no-restore | Remove 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:
| Field | Description |
|---|---|
ingest_id | Unique session identifier |
client | AI client used (Claude Code, OpenCode, etc.) |
project_slug | Associated project |
project_name | Human-readable project name |
created_at | Session start timestamp |
processed_at | When distillation completed |
memories_extracted | Number of memories extracted |
error | Any processing errors |
transcript | Full session transcript (expandable) |
Sources: web/components/ProjectSessionsPanel.tsx
Instincts (Top Knacks)
Instincts are triggered memory patterns:
| Field | Description |
|---|---|
instinct_id | Unique instinct identifier |
trigger | Condition pattern ("when...") |
action | Suggested action ("→...") |
project_slug | Associated project |
domain | Knowledge domain |
instinct_count | Number 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:
| Rule | Description |
|---|---|
| Source | pyproject.toml → [project].version |
| Default bump | +0.0.1 patch only |
| Major/Minor | Requires explicit approval |
| Release trigger | Git tag push: git tag v{version} && git push origin main v{version} |
| Tag format | Must match: v0.2.0 ↔ 0.2.0 |
Pre-release Checklist
Before tagging:
- Update version in
pyproject.toml - Run tests:
pytest tests/ -v - Build package:
uv build - Build web (if changed):
pnpm buildinweb/
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
- Begin each session at
PLAN.md - Check
## 현재 상태(Current Status) for incomplete items - Implement the next pending item
- 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
Continue reading this section for the full explanation and source context.
Continue reading this section for the full explanation and source context.
Continue reading this section for the full explanation and source context.
Continue reading this section for the full explanation and source context.
Related Pages
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
| Component | Minimum | Recommended |
|---|---|---|
| Device | Raspberry Pi 5 (4GB+) | Raspberry Pi 5 (8GB) |
| Storage | 32GB SD card | 64GB+ SSD via USB |
| Network | Ethernet or WiFi | Ethernet |
| OS | Raspberry 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 setBASE_URLto your external HTTPS domain. Without it, Google OAuth redirect URIs will fail withredirect_uri_mismatch. Sources: README.ko.md
#### Google OAuth Setup
- Go to Google Cloud Console
- Create a new project or select an existing one
- Navigate to APIs & Services → Credentials
- Create an OAuth 2.0 Client ID (Web application type)
- 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:
| Service | Port | Purpose |
|---|---|---|
| web | 8314 | Next.js frontend + API server |
| redis | 6379 | Session 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| CCSources: README.md
Client Connection
Claude Code Setup
- Navigate to Settings → Tokens in the web UI
- Generate an install code
- 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:
- Writes token + URLs to
~/.config/piloci/config.json - Registers the MCP server in
~/.claude.json - Configures session capture hooks in
~/.claude/settings.json
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/Tunnel | Configuration |
|---|---|
| Cloudflare Tunnel | Point to http://127.0.0.1:8314 |
| Caddy | Proxy to localhost:8314 |
| nginx | Proxy pass to 127.0.0.1:8314 |
Cloudflare Tunnel Setup
cloudflared tunnel --url http://localhost:8314
Sources: README.ko.md
Configuration Reference
Environment Variables
| Variable | Required | Default | Description |
|---|---|---|---|
BASE_URL | Yes (remote) | http://localhost:8314 | External HTTPS URL when behind proxy |
GOOGLE_CLIENT_ID | Yes | - | Google OAuth Client ID |
GOOGLE_CLIENT_SECRET | Yes | - | Google OAuth Client Secret |
SECRET_KEY | Yes | - | Session encryption key |
DATA_DIR | No | ./data | Data persistence directory |
REDIS_URL | No | redis://redis:6379 | Redis 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:
- Create an account via the web UI at
http://localhost:8314/signup - Connect your AI client using the pairing flow
- Create projects to organize your memories
- Explore the dashboard to view session history and extracted memories
For troubleshooting, check the logs:
docker compose logs -f web
docker compose logs -f workerSources: README.md
System Architecture
Related topics: Introduction to piLoci, Technology Stack, Storage Layer, MCP Server Implementation
Continue reading this section for the full explanation and source context.
Continue reading this section for the full explanation and source context.
Continue reading this section for the full explanation and source context.
Continue reading this section for the full explanation and source context.
Related Pages
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 --> MCPSources: 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.
| Component | Technology | Purpose | Location |
|---|---|---|---|
| Backend API | FastAPI | REST API + MCP server | src/piloci/ |
| Vector Storage | LanceDB | Embedded memory storage with vector search | src/piloci/storage/ |
| Identity DB | SQLite | User/project identity and metadata | src/piloci/db/ |
| Session Cache | Redis | Temporary session data caching | docker-compose.yml |
| Embeddings | fastembed (ONNX) | Local CPU-based embedding inference | src/piloci/storage/ |
| Frontend | Next.js 14 | React-based web application | web/ |
| Styling | Tailwind CSS | Utility-first design system | web/ |
| Container | Docker | Self-contained deployment | docker-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 --> PanelThe 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
| Component | File Path | Responsibility |
|---|---|---|
| AppShell | web/components/AppShell.tsx | Authenticated shell with glass navigation |
| DashboardSummaryPanels | web/components/DashboardSummaryPanels.tsx | User dashboard with metrics and session lists |
| ProjectSessionsPanel | web/components/ProjectSessionsPanel.tsx | Project-specific session viewer with transcripts |
| TokenManager | web/components/TokenManager.tsx | Installation token generation and display |
| DistillationSettings | web/components/DistillationSettingsPanel.tsx | Memory 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 --> UninstallSources: 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:
| Parameter | Default | Purpose |
|---|---|---|
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 |
PORT | 8314 | HTTP 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 Prefix | Handler | Purpose |
|---|---|---|
/api/auth/* | Authentication | OAuth flows, session management |
/api/projects/* | Project management | CRUD, slug lookup, freshness |
/api/memories/* | Memory operations | Create, list, vector search |
/api/budget/* | Budget tracking | Usage reporting |
/api/preferences | User settings | Distillation configuration |
/api/distillation/* | Worker control | Manual 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 --> MCPSources: src/piloci/installer.py:20-50
Installation Workflow
- Manifest Creation: Generates
plugin.jsonwith version, description, and author metadata - Hook Configuration: Creates
hooks.jsonlinking SessionStart and Stop events to plugin scripts - Script Download: Fetches
hook.pyandstop-hook.shfrom the server's/api/hook/endpoints - MCP Registration: Creates
.mcp.jsonexposing 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 resultsSources: README.ko.md:1-20
Supported Clients
| Client | MCP Support | Hook Support | Configuration Location |
|---|---|---|---|
| Claude Code | Full | SessionStart + Stop | ~/.claude.json, ~/.claude/settings.json |
| Claude Desktop | Full | N/A | ~/Library/Application Support/Claude/ |
| OpenCode | Full | N/A | ~/.config/opencode/opencode.json |
| Cursor | Partial | N/A | Cursor 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
| Parameter | Purpose | Default Behavior |
|---|---|---|
| Temperature Ceiling | SoC temperature threshold (°C) | Worker pauses when exceeded |
| Load Ceiling | 1-minute load average limit | Worker pauses when exceeded |
| Overflow Threshold | Workload threshold for aggressive processing | Ignores load when exceeded |
Sources: web/components/DistillationSettingsPanel.tsx:1-40
Processing Pipeline
- Session Capture: Hook scripts send transcripts via the ingest API
- Transcript Storage: Raw content stored with session metadata
- Embedding Generation: fastembed creates vector representations
- Memory Extraction: LLM processes transcript to identify key learnings
- 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
| Feature | Description | Endpoint |
|---|---|---|
| User Statistics | Total, pending, admin counts | Calculated from database |
| User Management | View and manage user accounts | /api/admin/users |
| System Health | Dashboard with key metrics | DashboardSummaryPanels |
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
- Update version in
pyproject.toml(patch increment by default) - Run validation:
pytest tests/ -vanduv build - Tag with matching version:
git tag v{version} - 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 --> RetrieveSummary
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
Continue reading this section for the full explanation and source context.
Continue reading this section for the full explanation and source context.
Continue reading this section for the full explanation and source context.
Continue reading this section for the full explanation and source context.
Related Pages
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 --> FastEmbedBackend Technology
Core Framework
| Component | Technology | Purpose |
|---|---|---|
| Web Framework | FastAPI | Async API server with automatic OpenAPI docs |
| ASGI Server | Uvicorn | High-performance ASGI server |
| ORM | SQLAlchemy | Database abstraction and migrations |
| Validation | Pydantic | Data 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:
| Feature | Description |
|---|---|
| Runtime | ONNX (Open Neural Network Exchange) |
| Deployment | On-device inference |
| Speed | Optimized for CPU execution |
| Privacy | No 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
| Provider | Protocol | Library |
|---|---|---|
| Google OAuth 2.0 | OAuth 2.0 | Authlib |
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
| Component | Technology | Version |
|---|---|---|
| Framework | Next.js | 15.x |
| Language | TypeScript | 5.x |
| Runtime | React | 19.x |
| Package Manager | pnpm | 9.x |
Sources: web/package.json:1-30
UI Components
| Layer | Library | Purpose |
|---|---|---|
| CSS Framework | TailwindCSS | Utility-first styling |
| Component Library | shadcn/ui | Accessible, customizable components |
| Icons | Lucide React | Consistent icon system |
| Styling Pattern | CSS Variables | Design 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
| Platform | Use Case | Notes |
|---|---|---|
| Raspberry Pi 5 | Primary target | Local deployment, Cloudflare Tunnel access |
| x86_64 Server | Production | Multi-arch Docker images |
| ARM64 | Edge computing | Supported via Docker multi-arch builds |
Sources: README.ko.md:30-45
Network Configuration
| Port | Service | Protocol |
|---|---|---|
| 3000 | Next.js Frontend | HTTP/HTTPS |
| 8314 | FastAPI Backend | HTTP (internal) |
| 6379 | Redis | TCP (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| Tool | Function |
|---|---|
memory | Store new memories from conversation context |
recall | Semantic search through stored memories |
recommend | Context-aware memory suggestions |
Sources: README.md:20-40
Technology Decision Records
Key architectural decisions are documented in the /docs/ADR-* directory:
| ADR | Topic | Status |
|---|---|---|
| ADR-014 | LanceDB Backend Selection | Implemented |
| ADR-015 | FastEmbed for Embeddings | Implemented |
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
| Layer | Technology | Key Benefit |
|---|---|---|
| API | FastAPI + Uvicorn | Async performance, auto docs |
| Database | SQLite | Zero-config, portable |
| Vectors | LanceDB + FastEmbed | Local ML inference |
| Sessions | Redis | Sub-millisecond latency |
| Frontend | Next.js + shadcn/ui | Type-safe, accessible UI |
| Auth | Google OAuth (Authlib) | Secure SSO |
| Deployment | Docker + Cloudflare Tunnel | Edge-ready |
Sources: pyproject.toml:1-50
MCP Server Implementation
Related topics: API Routes, Authentication & Security, Curator Pipeline
Continue reading this section for the full explanation and source context.
Related Pages
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
Continue reading this section for the full explanation and source context.
Continue reading this section for the full explanation and source context.
Continue reading this section for the full explanation and source context.
Continue reading this section for the full explanation and source context.
Related Pages
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
| Provider | Auth URL | Token URL | User Info Endpoint | Scopes |
|---|---|---|---|---|
https://accounts.google.com/o/oauth2/v2/auth | https://oauth2.googleapis.com/token | https://www.googleapis.com/oauth2/v3/userinfo | openid email profile | |
| Kakao | https://kauth.kakao.com/oauth/authorize | https://kauth.kakao.com/oauth/token | https://kapi.kakao.com/v2/user/me | profile_nickname account_email |
| Naver | https://nid.naver.com/oauth2.0/authorize | https://nid.naver.com/oauth2.0/token | https://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 dashboardProvider 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:
| Column | Type | Description |
|---|---|---|
oauth_provider | String (nullable) | Provider name (google/kakao/naver) |
oauth_provider_user_id | String (nullable) | User ID from the provider |
oauth_access_token | String (nullable, encrypted) | Encrypted OAuth access token |
oauth_refresh_token | String (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:
- Validates the logged-in Redis session
- Verifies password presence as a safety check
- Revokes the provider token remotely via
revoke_provider_token() - 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 responseAPI 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
| Route | Method | Description |
|---|---|---|
/auth/{provider} | GET | Initiate OAuth flow |
/auth/{provider}/callback | GET | Handle OAuth callback |
/auth/{provider}/disconnect | POST | Disconnect 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
| Variable | Required | Description |
|---|---|---|
JWT_SECRET | Yes | Secret key for JWT signing and Fernet encryption |
SESSION_SECRET | Yes | Redis session encryption key |
BASE_URL | Yes (production) | External HTTPS domain for OAuth callbacks |
GOOGLE_CLIENT_ID | For Google OAuth | Google OAuth application client ID |
GOOGLE_CLIENT_SECRET | For Google OAuth | Google OAuth application secret |
KAKAO_CLIENT_ID | For Kakao OAuth | Kakao OAuth application client ID |
KAKAO_CLIENT_SECRET | For Kakao OAuth | Kakao OAuth application secret |
NAVER_CLIENT_ID | For Naver OAuth | Naver OAuth application client ID |
NAVER_CLIENT_SECRET | For Naver OAuth | Naver 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:
- CLI displays a device code (
ABCD-1234) - User opens
/devicepage in browser - User logs in and approves
- CLI polls and receives token
- 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:
- Multi-provider OAuth — Google, Kakao, Naver with provider-specific user extraction
- Encrypted token storage — Fernet encryption using JWT secret-derived keys
- Redis session management — Fast, stateless session validation
- Rate limiting — Protection against brute-force attacks
- Provider disconnect — Full OAuth account unlinking support
- Device code flow — Secure CLI authentication for headless environments
- 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
Continue reading this section for the full explanation and source context.
Continue reading this section for the full explanation and source context.
Continue reading this section for the full explanation and source context.
Continue reading this section for the full explanation and source context.
Related Pages
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
| File | Purpose | Primary Responsibility |
|---|---|---|
routes.py | Main router configuration | Entry point, aggregation of sub-routers |
v1.py | API v1 versioning | Version-specific route mounting |
team_routes.py | Team management | Team CRUD, membership, permissions |
audit.py | Audit logging | Action tracking, audit trail retrieval |
data_portability.py | Data operations | Import/export, data migration |
distillation_routes.py | Model distillation | Knowledge distillation workflows |
ratelimit.py | Rate limiting | Request 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
| Operation | HTTP Method | Endpoint Pattern |
|---|---|---|
| List teams | GET | /teams |
| Create team | POST | /teams |
| Get team | GET | /teams/{team_id} |
| Update team | PUT | /teams/{team_id} |
| Delete team | DELETE | /teams/{team_id} |
| Add member | POST | /teams/{team_id}/members |
| Remove member | DELETE | /teams/{team_id}/members/{user_id} |
| List members | GET | /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
| Endpoint | Description |
|---|---|
GET /audit/events | List 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
| Operation | Description |
|---|---|
| Export data | Generate downloadable data archives |
| Import data | Upload and process data packages |
| Data format conversion | Transform between supported formats |
| Partial sync | Incremental 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
| Endpoint | Method | Description |
|---|---|---|
/distillation/jobs | POST | Create new distillation job |
/distillation/jobs | GET | List distillation jobs |
/distillation/jobs/{job_id} | GET | Get job status |
/distillation/jobs/{job_id} | DELETE | Cancel 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
| Parameter | Default | Description |
|---|---|---|
| Requests per minute | 60 | Maximum requests per client per minute |
| Burst allowance | 10 | Temporary burst capacity |
| Window type | Sliding | Rate limit window algorithm |
Rate Limit Headers
| Header | Description |
|---|---|
X-RateLimit-Limit | Maximum requests allowed |
X-RateLimit-Remaining | Requests remaining in window |
X-RateLimit-Reset | Unix 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
| Parameter | Location | Type | Description |
|---|---|---|---|
team_id | Path/Query | string | Team identifier |
user_id | Path/Query | string | User identifier |
page | Query | integer | Pagination offset |
page_size | Query | integer | Results per page |
sort_by | Query | string | Sort field |
order | Query | string | Sort 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
Continue reading this section for the full explanation and source context.
Continue reading this section for the full explanation and source context.
Continue reading this section for the full explanation and source context.
Continue reading this section for the full explanation and source context.
Related Pages
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 --> BPipeline Architecture
The curator module is organized into distinct components, each responsible for a specific stage of the memory processing pipeline.
Core Components
| Component | File | Responsibility |
|---|---|---|
Backlog | backlog.py | Queue management for pending session processing |
Prefilter | prefilter.py | Fast-pass filtering before expensive extraction |
DistillationWorker | distillation_worker.py | Orchestrates the extraction workflow |
Scheduler | scheduler.py | Resource-aware scheduling (temperature, load) |
Budget | budget.py | External LLM API budget tracking and limits |
Extraction | extraction.py | Memory extraction logic via Gemma or external LLM |
Vault | vault.py | Persistent storage and retrieval of memories |
WeeklyDigestWorker | weekly_digest_worker.py | Periodic 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:
| Parameter | Description | Default Behavior |
|---|---|---|
| Temperature Ceiling | SoC temperature threshold | Worker halts when exceeded |
| Load Average | 1-minute system load | Worker halts above threshold |
| Overflow Threshold | Queue depth before bypass | Triggers 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:
- Check current month-to-date spend
- Compare against configured limit
- Allow or block external LLM calls
- 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:
- Local Gemma Model - ONNX-based inference using fastembed
- 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 texttags: Categorization tagsproject_id: Associated project scopesession_id: Source session referencemetadata: 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:
- Polls the backlog for pending sessions
- Applies prefilter checks
- Waits for resource availability via scheduler
- Executes extraction (Gemma → external LLM fallback)
- Stores results to vault
- 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
| Setting | Type | Description |
|---|---|---|
temp_ceiling | float | Temperature threshold (°C) for halting worker |
load_ceiling | float | Load average threshold for halting worker |
overflow | int | Queue length threshold triggering external LLM bypass |
budget_monthly_usd | float | Monthly budget for external LLM calls (USD) |
API Endpoints
| Endpoint | Method | Description |
|---|---|---|
/api/distillation/run-now | POST | Manually trigger distillation cycle |
/api/preferences | GET | Retrieve distillation preferences |
/api/preferences | PATCH | Update distillation preferences |
/api/budget/usage | GET | Get 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:
| Component | Technology | Role in Pipeline |
|---|---|---|
| Embeddings | fastembed (ONNX) | Gemma model inference |
| Vector Storage | LanceDB | Memory indexing |
| Session Cache | Redis | Processing state |
| Identity Data | SQLite | User/project metadata |
| API Server | FastAPI | Preference 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
Continue reading this section for the full explanation and source context.
Continue reading this section for the full explanation and source context.
Continue reading this section for the full explanation and source context.
Continue reading this section for the full explanation and source context.
Related Pages
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.
| Component | Responsibility |
|---|---|
BaseStore | Abstract interface defining add, search, delete, and update operations |
StorageError | Custom exception type for storage-related failures |
| Connection pooling | Shared 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.
| Feature | Description |
|---|---|
| Vector dimensions | Configurable based on embedding model |
| Index type | LanceDB's optimized disk-based indices |
| Query types | Top-k similarity, range search, filtered search |
| Persistence | On-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.
| Configuration | Default | Description |
|---|---|---|
| Model | fastembed | ONNX embedding model |
| Batch size | Environment-defined | Processing batch size |
| Dimension | Model-dependent | Output vector dimensions |
| Device | cpu | Compute 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 Target | TTL | Purpose |
|---|---|---|
| Session data | 1 hour | Recent conversation context |
| User preferences | 24 hours | UI and behavior settings |
| Query results | 15 minutes | Expensive 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 Type | Storage | Access Pattern |
|---|---|---|
| Project isolation | SQLite | Read-heavy |
| Field-level masking | SQLite | Read-heavy |
| Retention policies | SQLite | Balanced |
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.
| Field | Type | Description |
|---|---|---|
instinct_id | UUID | Unique identifier |
project_slug | String | Associated project scope |
trigger | String | Condition expression |
action | String | Action to execute |
domain | String | Application domain |
instinct_count | Integer | Trigger 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 resultsStorage Backend Selection
The system uses multiple storage backends based on data characteristics:
| Data Type | Backend | Rationale |
|---|---|---|
| Vector embeddings | LanceDB | Optimized for ANN search, disk-based |
| Session data | Redis | Low-latency key-value access |
| Identity/Auth | SQLite | ACID transactions, simple schema |
| Privacy rules | SQLite | Relational integrity requirements |
| Instincts | SQLite | Structured 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
| Operation | Expected Latency | Notes |
|---|---|---|
| Memory add | < 100ms | Including embedding |
| Semantic search | < 200ms | Top-10 results |
| Cache lookup | < 10ms | Redis hit |
| Privacy check | < 5ms | SQLite index |
Security Considerations
The storage layer implements several security measures:
- Project isolation: Memory data is scoped to projects, preventing cross-project data leakage
- Token-based access: All storage operations require valid authentication tokens
- Encrypted at rest: Sensitive fields can be encrypted before storage
- 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
BaseStoreinterface 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
Related Documentation
Sources: src/piloci/storage/base.py
Database Models
Related topics: Storage Layer, Authentication & Security, API Routes
Continue reading this section for the full explanation and source context.
Continue reading this section for the full explanation and source context.
Continue reading this section for the full explanation and source context.
Continue reading this section for the full explanation and source context.
Related Pages
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| ONNXTechnology Stack
| Component | Technology | Purpose | Location |
|---|---|---|---|
| Identity Data | SQLite | User accounts, projects, permissions | src/piloci/db/ |
| Vector Storage | LanceDB | Memory embeddings, similarity search | Vector index |
| Session Management | Redis | Active session state, caching | External service |
| Embedding Engine | fastembed (ONNX) | Local inference | src/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)emailpassword_hashcreated_atupdated_atis_admin
Project Model
id(Primary Key)slug(Unique identifier)nameuser_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_atprocessed_atmemories_extractederror(Optional)
Memory/Instinct Model
memory_id/instinct_id(Primary Key)project_slugcontentembedding(Vector)trigger(For instincts)action(For instincts)domaininstinct_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:
| Endpoint | Operation | Description |
|---|---|---|
GET /api/projects | List | Fetch user's projects |
GET /api/projects/{id} | Read | Fetch project details |
POST /api/memories | Create | Store new memory |
GET /api/projects/{slug}/workspace | Read | Get 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
Related Documentation
- MEMORY.md - Memory extraction and distillation system
- CLAUDE.md - Development guidelines
- web/DESIGN-HARNESS.md - Frontend design patterns
Sources: README.md
Web Dashboard
Related topics: Workspace UI & Team Features, Technology Stack, Authentication & Security
Continue reading this section for the full explanation and source context.
Continue reading this section for the full explanation and source context.
Continue reading this section for the full explanation and source context.
Continue reading this section for the full explanation and source context.
Related Pages
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
| Layer | Technology | Purpose |
|---|---|---|
| Framework | Next.js 14+ (App Router) | Server-side rendering, routing, API routes |
| UI Components | shadcn/ui + Radix UI | Accessible, composable components |
| Styling | Tailwind CSS | Utility-first styling with design tokens |
| State Management | React Context + Server Components | Auth state and server-fetched data |
| Data Fetching | Server Actions + fetch API | Backend 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 dashboardAuth Configuration
The authentication system is configured in web/lib/auth.ts and uses NextAuth.js with Google OAuth provider:
| Setting | Description | Environment Variable |
|---|---|---|
| Provider | Google OAuth 2.0 | AUTH_GOOGLE_ID, AUTH_GOOGLE_SECRET |
| Base URL | Application root for callbacks | BASE_URL |
| Session Strategy | JWT-based sessions | N/A |
| Callbacks | Custom session/user callbacks | N/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:
| Feature | Implementation |
|---|---|
| Background | Authenticated shell background with glass effect |
| Navigation | Top navigation bar with user menu |
| User Info | User display with email and role |
| Quick Links | Dashboard, Projects, Settings navigation |
| Role-Based Access | Admin menu visible only to admin users |
DashboardSummaryPanels
The main dashboard view displays aggregated statistics and recent activity:
| Panel | Data Source | Components |
|---|---|---|
| Summary Stats | User stats API | pi-metric-card with icons |
| Top Tags | Tag frequency aggregation | Badges with counts |
| Recent Sessions | Session 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:
| Feature | Description |
|---|---|
| Project Grid | Responsive grid layout (sm:2, lg:3 columns) |
| Create Dialog | Modal form for new project creation |
| Loading State | Skeleton placeholders during fetch |
| Error State | Retry button on fetch failure |
TokenManager
Handles API token lifecycle management:
| Feature | Description |
|---|---|
| Token List | Table with name, scope, creation date |
| Scope Badges | User vs Project scope indicators |
| Install Status | Shows installed clients and hostname |
| Setup Instructions | Tabbed guides for Claude Desktop, Claude Code, OpenCode, Cursor |
ProjectSessionsPanel
Displays ingest sessions for a project:
| Feature | Implementation |
|---|---|
| Session Cards | Expandable cards with transcript viewer |
| Status Badges | Client, status, timestamp display |
| Error Display | Red text for failed sessions |
| Transcript Viewer | Lazy-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 Pattern | Purpose | Auth Required |
|---|---|---|
/api/users | User management | Admin |
/api/projects | Project CRUD | Yes |
/api/projects/:slug/sessions | Session listing | Yes |
/api/tokens | Token management | Yes |
/api/ingest/:id/transcript | Transcript fetch | Yes |
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:
| Token | Usage | Example |
|---|---|---|
--pi-shadow | Card shadows | Box elevation |
--pi-shadow-sm | Small element shadows | Buttons, badges |
--pi-primary | Primary brand color | CTAs, links |
Pattern Classes
| Class | Purpose | Location |
|---|---|---|
pi-page | Page container wrapper | All pages |
pi-page-hero | Title/subtitle section | All pages |
pi-eyebrow | Category label | Page headers |
pi-title | Main page title | H1 elements |
pi-subtitle | Page description | Intro text |
pi-metric-card | Statistics cards | Dashboard panels |
pi-panel | Content containers | Lists, forms |
pi-icon-cell | Icon + color wrapper | Metric cards |
Responsive Breakpoints
| Breakpoint | Columns | Components Shown |
|---|---|---|
| Mobile | 1 | Essential info only |
sm (640px) | 2-3 | Expanded cards |
md (768px) | 3 | Full tables |
lg (1024px) | 4 | Two-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:#ffe6e6Dashboard Pages
| Route | Purpose | Main Components |
|---|---|---|
/dashboard | Main user dashboard | DashboardSummaryPanels |
/projects | Project workspace | ProjectListView, ProjectSessionsPanel |
/settings | User preferences | DistillationSettingsPanel |
/settings/tokens | API token management | TokenManager |
/admin/users | User administration | User 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:
| Namespace | Usage |
|---|---|
landing | Landing page content |
authLayout | Auth page headers/footers |
dashboard | Dashboard labels and messages |
admin | Admin page content |
tokenManager | Token management strings |
projects | Project 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
Related Documentation
Source: https://github.com/jshsakura/oc-piloci / Human Manual
Workspace UI & Team Features
Related topics: Web Dashboard, Curator Pipeline
Continue reading this section for the full explanation and source context.
Continue reading this section for the full explanation and source context.
Continue reading this section for the full explanation and source context.
Continue reading this section for the full explanation and source context.
Related Pages
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.tsxfor 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:
| Element | Description |
|---|---|
| Client Badge | Shows client type (e.g., Claude Desktop, Claude Code, OpenCode) |
| Status | Processing status with timestamps |
| Memory Count | Extracted memories count or pending indicator |
| Error Display | Session errors in red text |
| Transcript | Expandable 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)
TranscriptViewercomponent renders full session transcript- State management via
isExpboolean mapped toingest_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:
| Panel | Icon | Content |
|---|---|---|
| Recent Sessions | FileText | Last processed sessions with memory counts |
| Top Tags | Sparkles | Most used memory tags with usage frequency |
| Project Stats | Varies | Metrics 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:
| Field | Type | Description |
|---|---|---|
title | string | Note title |
path | string | File system path |
markdown | string | Full markdown content |
excerpt | string | Short preview text |
tags | string[] | Associated tags |
links | string[] | 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:
- Fetch workspace data from
/api/projects/slug/{slug}/workspace - Create project directory structure in
~/.config/piloci/projects/slug/{slug}/workspace - Write each
workspace.notes[].markdownto correspondingworkspace.notes[].path - 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:
| Client | Config File | Features |
|---|---|---|
| Claude Desktop | ~/Library/Application Support/Claude/claude_desktop_config.json | MCP server + hooks |
| Claude Code | ~/.claude.json / .mcp.json | MCP server + auto-capture hooks |
| OpenCode | opencode.json | MCP 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 ``
- CLI Installation:
``bash curl -sSL https://piloci.example.com/install/<install_code> | bash ``
- One-line Bash:
```bash # Step 1: Install hook piloci hook install
- 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:
- Records token + ingest/analyze URL to
~/.config/piloci/config.json(mode 0600) - Claude Code: Registers MCP server in
~/.claude.jsonwithmemory/recall/recommendtools, plus auto-capture hooks in~/.claude/settings.json - OpenCode: Registers MCP server in
~/.config/opencode/opencode.json
Hook Behavior by Client:
| Client | SessionStart Hook | SessionStop Hook |
|---|---|---|
| Claude Code | Catch-up batch retrieve | Live push each turn |
| OpenCode | N/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:
| Setting | Type | Description |
|---|---|---|
| Temperature Ceiling | °C | Worker stops when SoC temp exceeds threshold |
| Load Ceiling | float | Worker stops when load avg exceeds threshold |
| Overflow Limit | number | Optional 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:
| Class | Usage |
|---|---|
pi-page | Main page container |
pi-page-hero | Hero section with title and subtitle |
pi-eyebrow | Small label above title |
pi-title | Page title (H1) |
pi-subtitle | Descriptive subtitle |
pi-metric-card | Metric display cards |
pi-panel | Content 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.
Upgrade or migration may change expected behavior: Release v0.3.61
Upgrade or migration may change expected behavior: Release v0.3.62
Upgrade or migration may change expected behavior: Release v0.3.63
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.
Count of project-level external discussion links exposed on this manual page.
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.
- Release v0.3.77 - github / github_release
- Release v0.3.76 - github / github_release
- Release v0.3.75 - github / github_release
- Release v0.3.74 - github / github_release
- Release v0.3.73 - github / github_release
- Release v0.3.72 - github / github_release
- Release v0.3.71 - github / github_release
- Release v0.3.70 - github / github_release
- Release v0.3.69 - github / github_release
- Release v0.3.68 - github / github_release
- Release v0.3.67 - github / github_release
- Release v0.3.66 - github / github_release
Source: Project Pack community evidence and pitfall evidence