npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@daniel156161/prism

v0.3.23

Published

Prism-branded wrapper around pi that stores config in ~/.prism

Readme

Prism

Prism is a branded harness around the pi coding agent. It bundles the pi runtime, keeps all agent state in ~/.prism, patches pi in-place for Prism branding and behavior, and ships a set of built-in extensions: planning, research, memory integrations (Obsidian, Logseq), a code-graph integration (mex), a hidden diagnostic toolbox, role-play long-term context, local Ollama models and Manifest routing.

Prism does not embed pi as a library. It resolves the bundled pi CLI, sets Prism-specific env vars, and idempotently patches the runtime package in ~/.prism/pi-package.

  • Package: @daniel156161/prism
  • Binary: prism
  • Bundled pi runtime: @earendil-works/pi-coding-agent 0.87.1
  • Node: >=25
  • Config/state: ~/.prism

Requirements

  • Node.js >=25
  • No separate pi install needed — @earendil-works/pi-coding-agent is a bundledDependency. Override with PRISM_PI_CLI_PATH only if you know the patch layer matches that pi version.

Optional, only needed for the features that use them:

  • mex-agent (npm install -g mex-agent) plus a .mex/ scaffold for the code graph
  • a local or cloud Ollama instance for the ollama provider

Install

npm install -g --legacy-peer-deps @daniel156161/prism

--legacy-peer-deps is required: pi-mcp-adapter declares an optional peer on @earendil-works/pi-ai@^0.84.1 || ^0.85.0 while Prism ships pi 0.87.x. Without the flag npm "overrides" that peer and silently drops the whole MCP subtree (pkce-challenge, jose, zod, ajv, eventsource), which only surfaces later as a missing-module crash at runtime.

The binary is:

prism
prism --version

Run from source

npm install
npm run dev

A justfile wraps the common workflows (just --list), including the Docker sandbox in sandbox-kit/.

CLI

Subcommands

prism auth status
prism auth list
prism auth save work|private
prism auth use work|private
prism auth work
prism auth private

prism obsidian-memory append [--path NOTE] [--heading TITLE] <text>
prism obsidian-memory read [path]
prism obsidian-memory search [--limit N] [--subdir DIR] <query>
prism obsidian-memory list [--dir DIR] [--limit N]
# alias: prism memory ...

Prism-specific flags

Consumed before the remaining args are handed to pi:

  • --caveman[=mode] — start in caveman mode. Bare --caveman means full. Modes: lite, full, ultra, wenyan-lite, wenyan, wenyan-ultra.
  • --model provider:model — Prism normalizes provider:model (colon) to provider/model (slash) for pi compatibility. --model provider/model works directly. Known providers are read from the bundled pi model resolver.
  • --auth-profile work|private — use a profile for a single run without moving the auth.profile marker.

All other pi flags (--provider, --models, --no-tools, --list-models, --no-extensions, …) pass through unchanged.

Config paths

Prism forces pi to use the Prism agent directory:

  • default: ~/.prism
  • override: PRISM_CODING_AGENT_DIR=/path/to/prism-dir

Important files:

  • ~/.prism/settings.json
  • ~/.prism/models.json
  • ~/.prism/auth.json
  • ~/.prism/auth.private.json
  • ~/.prism/auth.work.json
  • ~/.prism/auth.profile — active auth profile marker
  • ~/.prism/sessions/ — JSONL sessions
  • ~/.prism/sessions.db — SQLite mirror
  • ~/.prism/rp-state.json — active role-play marker
  • ~/.prism/pi-package/ — lightweight piConfig dir (package.json, themes, linked pi docs/, examples/, README.md)

Project-local Prism resources live under the project .prism/ directory:

.prism/skills/<skill-name>/SKILL.md
.prism/settings.json
.prism/extensions/
.prism/prompts/
.prism/themes/

Example skill path:

.prism/skills/last30days/SKILL.md

After trusting the project, Prism lists discovered project skills in a separate startup section:

[Skills]
  last30days

/skill:last30days is available as a slash command when skill commands are enabled.

WristPrompt server integration

Prism has a built-in WristPrompt extension that talks to your configured server API directly. It does not use local inbox files or a local bridge.

Configure it with a root API URL and a refresh token with the pebble scope.

Environment variables:

export PRISM_WRISTPROMPT_API_BASE_URL="https://example.com"
export PRISM_WRISTPROMPT_REFRESH_TOKEN="..."

Or ~/.prism/settings.json:

{
  "wristPrompt": {
    "apiBaseUrl": "https://example.com",
    "refreshToken": "..."
  }
}

Optional timeout:

export PRISM_WRISTPROMPT_TIMEOUT_MS=30000

The extension is enabled automatically when both apiBaseUrl and refreshToken are configured.

When configured, Prism/pi gets the /wristprompt command. The request tools stay inactive until watch input is enabled for the current session with /wristprompt:

wristprompt_ask             blocking: create request + wait for the watch answer
wristprompt_check_request   check one earlier request that timed out
wristprompt_cancel_request  withdraw a request the agent created

/wristprompt off disables watch input again and removes those request tools from the active tool set.

wristprompt_ask blocks on purpose. An agent turn ends as soon as the model stops, so a fire-and-forget request could never be picked up again in the same turn. The tool creates the request (POST /api/pebble/wristprompt), polls it (GET /api/pebble/wristprompt/<id>), and returns as soon as the watch answers:

{ "request_id": "wrp_...", "status": "approved", "answered": true, "action": "approve", "message": "go", "waited_ms": 8123 }

The wait window is not a tool parameter. The model always gets the full window, otherwise it could time itself out of an answer. Only you can change it, via env:

export PRISM_WRISTPROMPT_ASK_TIMEOUT_MS=600000   # default: 600 s
export PRISM_WRISTPROMPT_ASK_POLL_MS=2000        # poll interval while waiting
export PRISM_WRISTPROMPT_POLL_MS=3000            # claim interval for watch transcripts

Or in ~/.prism/settings.json, in milliseconds or seconds:

{
  "wristPrompt": {
    "apiBaseUrl": "https://example.com",
    "refreshToken": "...",
    "askTimeoutSeconds": 600,
    "askPollSeconds": 2,
    "pollSeconds": 3
  }
}

askTimeoutMs, askPollMs, and pollMs work too. Env wins over settings.json, and values below the minimum (1 s timeout, 250 ms ask poll, 500 ms claim poll) fall back to the defaults.

On timeout or tool-call abort, Prism dismisses the watch request automatically so stale prompts do not stay open. If that dismissal fails, the result keeps status: "pending" plus the request_id, so the agent can check or cancel it later. The agent can only dismiss its own request; approving/rejecting is the watch's job.

Watch input per session (opt-in)

Watch transcripts and WristPrompt request tools are never enabled automatically. Run /wristprompt inside the one session that should receive watch input and access to the WristPrompt tools:

/wristprompt          # enable this session as watch-input listener
/wristprompt off      # disable again
/wristprompt status   # show current state

Enabling registers the current session (POST /api/pebble/wristprompt/sessions), so the watch can show and target it, and starts a claim loop (POST /api/pebble/wristprompt/input/claim). Each transcript is claimed exactly once, so it never fans out to other open sessions. The status-bar segment ⌚ <host> is only shown while a session is active, and the session is unregistered on shutdown. Claim failures are reported once and retried with exponential backoff up to 60 s; successful claims reset the backoff. Session registration also sends stale_after_ms (24 h), so the server can prune sessions that survived a hard process kill.

The extension refreshes 1-hour access tokens through POST /token/refresh and retries once after 401/403.

Sessions

Sessions are persisted immediately and mirrored into ~/.prism/sessions.db (src/pi/pi-patch-session.ts, src/session-db.ts). Existing JSONL sessions are imported on startup.

  • PRISM_SESSION_BACKEND=db (default) — SQLite is authoritative, JSONL is imported and cleaned up
  • PRISM_SESSION_BACKEND=file — plain pi JSONL behavior, no DB mirroring

Auth profiles

Keep separate private/work auth files and switch before pi starts:

prism auth save private
prism auth save work
prism auth private
prism auth work
prism auth status

Single-run override without changing the marker:

prism --auth-profile work
prism --auth-profile=private "your prompt"

Profiles live in ~/.prism:

  • auth.json — legacy auth file, unused by Prism profile switching
  • auth.private.json — private profile
  • auth.work.json — work profile
  • auth.profile — active profile marker (work or private)

Built-in commands

Always available:

  • /plan [task] — read-only planning mode; approve to restore full tool access. See plan mode.
  • /research <topic> [provider/model|pick] — citation-backed web research workflow.
  • /context — visual context usage grid (system prompt, tools, skills, project context, messages).
  • /toolbox <query> — search hidden toolbox tools.
  • /git-commit — ask the current model to create a signed git commit from staged changes.
  • /clear or /cls — clear terminal/scrollback and start a fresh session.
  • /caveman [lite|full|ultra|wenyan-lite|wenyan|wenyan-ultra|off] — concise response modes.
  • /exit — optional session-end workflow (daily note / insight / inbox cleanup) before shutdown.

Memory:

  • /obsidian-note — ask the current model to write or update Obsidian notes from the current context.
  • /obsidian-commit — commit staged Obsidian vault changes with an automatic German commit message.
  • /logseq — show Logseq vault status and the default journal path.
  • /rp [status] | list | new <name> | start <name> | stop | recap — manage role-plays.

Safe harness improvement (all human-gated, see docs/safe-harness-improvement.md):

  • /self-improve [focus] — read-only inspection, then concrete proposals with blast radius, validation plan and rollback.
  • /eval [focus] — read-only regression/eval pass, compared against prior eval logs.
  • /vote <task> — multi-perspective review without implementing anything.
  • /prompt-review <focus> — review prompts/behavior patterns and propose safer candidates.

Conditional:

  • /ollama status|refresh|list|running|version|show <model>|pull <model> and /ollama-refresh — when Ollama is reachable.
  • /manifest status|tier <tier> — when a Manifest base URL is configured.
  • /mex [status] | graph | check | timeline | scope <task> — when the mex CLI and a .mex/ scaffold exist.

From bundled npm extensions:

  • /voice — local speech dictation overlay (@juicesharp/rpiv-voice).
  • /todos — agent todo list (@juicesharp/rpiv-todo), panel toggle ctrl+shift+t.

Built-in tools

Obsidian memory:

obsidian_memory_append   obsidian_memory_read   obsidian_memory_search   obsidian_memory_list

Logseq memory:

logseq_append   logseq_read   logseq_search   logseq_list

Research:

web_search   web_fetch

web_search and web_fetch prefer a local-first NodeSeek backend when its health endpoint answers. web_search falls back to DuckDuckGo and Bing, web_fetch falls back to a direct page fetch. YouTube transcripts (yt-dlp) and GitHub handling always run first.

NodeSeek graph tools (loaded only when the service answers at startup):

nodeseek_context   nodeseek_navigate
PRISM_NODESEEK_URL   default http://127.0.0.1:8000, use "off" to disable
PRISM_NODESEEK_AVAILABILITY_TIMEOUT_SECONDS   default 0.5   curl budget per startup probe
PRISM_NODESEEK_STARTUP_ATTEMPTS   default 2   startup probes before giving up
PRISM_NODESEEK_HEALTH_TIMEOUT_MS   default 1200   runtime health check
PRISM_NODESEEK_HEALTH_CACHE_TTL_MS   default 30000   health result cache
PRISM_NODESEEK_SEARCH_TIMEOUT_MS   default 12000   /v1/search
PRISM_NODESEEK_READ_TIMEOUT_MS   default 15000   /v1/read
PRISM_NODESEEK_GRAPH_TIMEOUT_MS   default 12000   /v1/context + /v1/navigate

Every value can also come from the nodeseek block in settings.json (env wins over settings, settings win over the defaults):

{
  "nodeseek": {
    "baseUrl": "https://nodeseek.example",
    "availabilityTimeoutSeconds": 1,
    "startupAttempts": 3,
    "healthTimeoutMs": 3000,
    "healthCacheTtlMs": 60000,
    "searchTimeoutMs": 20000,
    "readTimeoutMs": 25000,
    "graphTimeoutMs": 20000
  }
}

For a remote NodeSeek host, raise the timeouts and keep startupAttempts above 1: a single failed startup probe is usually a stalled DNS lookup on the client, and a retry resolves it without disabling the graph tools for the whole session.

Role-play context:

rp_state   rp_update   rp_search

Safe harness improvement:

self_improvement_record   self_improvement_list   self_improvement_update_proposal

mex code graph (conditional):

mex_scope   mex_get   mex_query   mex_impact   mex_log

Hidden toolbox:

toolbox_search   toolbox_execute

Hidden toolbox

Hidden tools are not listed in the system prompt. The agent discovers them with toolbox_search and runs them with toolbox_execute; relevant candidates are also suggested per turn. Extensions can register their own via the toolbox:register event.

Built-in toolbox tools (src/prism-extensions/tools/) are read-only diagnostics unless noted: | Tool | Purpose | |---|---| | ssh_config | Read ~/.ssh/config, show host context, optional read-only SSH status checks | | docker_status | Containers, compose services, images, disk usage | | docker_logs | Recent logs from a local container | | systemd_services | Running/failed units or status for one unit | | port_check | TCP reachability from this machine | | http_health | HTTP status, content type, selected headers, small body preview | | process_find | Find local processes by text query | | ssh_remote_logs | Docker/systemd logs on a configured SSH host | | netbird_status | Local or remote NetBird status, peers, service state | | pfsense_status | pfSense/OPNsense health: uptime, interfaces, states, gateways, DNS, disk | | borg_backup_info | borg info/borg list on a backup repository | | prism_runtime_status | Prism runtime/config paths, versions, sessions DB, auth marker | | prism_deploy_check | Read-only checks for a deployed Prism SSH/tmux container | | npm_package_version | Latest published version from an npm-compatible registry metadata endpoint | | portainer_webhook | Inspect or trigger a Portainer stack webhook (dry-run by default) | | mex_graph_build | Rebuild .mex/graph.db | | mex_check | mex drift detection between the .mex wiki and the codebase | | mex_timeline | mex event-log timeline |

Plan mode tool filter

/plan narrows the session to the intersection of the active tools and the allowlist in src/pi/plan-mode-tools.ts (PRISM_PLAN_MODE_READ_ONLY_TOOLS), and restores the previous tool set when the plan is approved, rejected or cancelled.

Allowed: pi built-ins read/grep/find/ls, web_search/web_fetch, obsidian_memory_read|search|list, logseq_read|search|list, mex_scope|get|query|impact, rp_state/rp_search, toolbox_search, self_improvement_list, todo.

Deliberately excluded: bash, edit, write, every *_append and vault-write tool, mex_log, rp_update, toolbox_execute, self_improvement_record|update_proposal, mcp, mcpScript.

Only add non-mutating tools. prismPlanReadOnlyToolSetDeclaration() builds the set for the runtime patch; refreshPrismPlanReadOnlyToolSet() updates an already-patched runtime.

Obsidian memory

Vault selection is env-only. Prism intentionally ignores ~/.prism/settings.json and generic OBSIDIAN_VAULT / OBSIDIAN_VAULT_NAME so it never falls back to a personal/default vault by accident.

export PRISM_OBSIDIAN_VAULT_NAME=AI-Worker   # resolved via: obsidian vault info=path vault=AI-Worker
export PRISM_OBSIDIAN_VAULT=/path/to/vault   # or pin an explicit path

Fallbacks: PI_OBSIDIAN_VAULT_NAME, PI_OBSIDIAN_VAULT. An explicitly empty PRISM_OBSIDIAN_VAULT_NAME/PRISM_OBSIDIAN_VAULT stays empty and does not fall back.

CLI behavior:

  • Memory tools use the Obsidian CLI when PRISM_OBSIDIAN_VAULT_NAME is set (read, append, property:set, files, search:context). Missing notes are created with create; full overwrite is only used when existing note structure must be normalized.
  • The vault is passed as a leading global option (obsidian vault=AI-Worker ...) because the CLI ignores trailing vault=... for some commands.
  • Auto-context uses the resolved vault path for direct Markdown scanning/injection.
  • Obsidian CLI calls time out to avoid hangs when Obsidian is not running. Default: PRISM_OBSIDIAN_CLI_TIMEOUT_MS=5000.

Auto-context behavior:

  • 00 Kontext/ is injected as full always-loaded background context.
  • Prompt-relevant memories are injected only as compact candidates: path, description, score, tags.
  • The model calls obsidian_memory_read for a candidate path only when full note context is needed.
  • PI_OBSIDIAN_CONTEXT_DIR restricts candidate search to one vault subdirectory.

Vault structure used by Prism:

  • MEMORY.md root index, no YAML frontmatter
  • 00 Kontext/ always-loaded background context
  • 01 Inbox/ unsorted captures
  • 02 Projekte/ projects
  • 03 Bereiche/ areas
  • 04 Ressourcen/ references/resources
  • 05 Daily Notes/ daily notes
  • 06 Archiv/ archived notes
  • RP/<slug>/ role-play long-term context
  • Pi/ pi/prism-specific notes

Logseq memory

export PRISM_LOGSEQ_VAULT=/path/to/logseq-graph
export PRISM_LOGSEQ_CONTEXT_DIR=pages       # optional: restrict candidate search
export PRISM_LOGSEQ_ALWAYS_CONTEXT=Kontext  # optional: always-loaded namespace prefix

Fallbacks: PI_LOGSEQ_VAULT, PI_LOGSEQ_CONTEXT_DIR, PI_LOGSEQ_ALWAYS_CONTEXT.

Pages under the Kontext/... namespace are injected as always-loaded context; other matches are injected as compact per-turn candidates. Writes go to pages/<Name>.md, journal-style names (YYYY_MM_DD) to journals/. Without a path, logseq_append targets today's journal.

Role-play context

/rp stores long-term role-play context in the Obsidian vault so it survives session resets:

<vault>/RP/<slug>/Overview.md     premise, setting, tone, rules
<vault>/RP/<slug>/Characters.md   "## <Name>" persona sections
<vault>/RP/<slug>/World.md        "## <Topic>" lore sections
<vault>/RP/<slug>/State.md        running recap, current scene, relationships, threads
<vault>/RP/<slug>/Story.md        chronological prose archive (searchable, not always-loaded)

Multiple role-plays live side by side. The active one is tracked in ~/.prism/rp-state.json, outside the vault, so rp_state/rp_update/rp_search can be gated. Overview/Characters/World/State are always-loaded while a role-play runs; the toolbar shows a segment only then.

mex code graph

integrations/mex-memory.ts loads only when the mex CLI (npm install -g mex-agent) is installed and the repo has a .mex/ scaffold (npx mex-agent setup). It exposes mex_scope, mex_get, mex_query, mex_impact, mex_log and /mex; maintenance lives in the hidden toolbox (mex_graph_build, mex_check, mex_timeline).

When active, .mex/AGENTS.md (frontmatter stripped, max 8000 chars) is injected as an always-loaded context file, so the agent knows the graph and scaffold exist without being told.

A missing .mex/graph.db is rebuilt automatically (core/mex-graph-db.ts): in the background on session start, and lazily before the first graph-reading tool call. Builds are deduplicated per scaffold and never fail hard. Without a scaffold nothing is ever built.

The 🕸 mex toolbar segment appears only when mex really works (scaffold and non-empty graph.db); 🕸 mex ⟳ while a build runs; nothing when disabled, scaffold-less or failed.

Env switches:

  • PRISM_DISABLE_MEX=1 — off entirely
  • PRISM_MEX_FORCE=1 — load without a scaffold
  • PRISM_MEX_BIN — custom binary path
  • PRISM_MEX_TELEMETRY=1 — allow mex telemetry (Prism otherwise sets DO_NOT_TRACK=1 / MEX_TELEMETRY=0)
  • PRISM_DISABLE_MEX_ANCHOR=1 — do not inject .mex/AGENTS.md
  • PRISM_DISABLE_MEX_AUTO_GRAPH=1 — never auto-build graph.db

Provider extensions

Provider integrations live under src/prism-extensions/providers/ and are loaded conditionally.

Ollama provider

Loaded when ${OLLAMA_BASE_URL}/api/tags responds with at least one model and PRISM_DISABLE_OLLAMA is not 1. Prism registers a dynamic ollama provider from Ollama's live API (/api/tags, /api/show, /api/ps, /api/version) and serves models through the OpenAI-compatible /v1 API: streaming, tools, vision when capabilities report it, structured outputs/JSON mode, usage metrics, and reasoning controls for thinking models.

/ollama status | refresh | list | running | version | show <model> | pull <model>
/ollama-refresh

Manifest provider

Loaded when a Manifest base URL is configured via env or ~/.prism/settings.json. The API key goes through pi's normal auth flow (/login → API key → Manifest) into the active Prism auth profile.

~/.prism/settings.json:

{
  "manifestProvider": {
    "baseUrl": "https://manifest.example/v1",
    "tier": "plan"
  }
}
prism
# /login → Use an API key → Manifest
# /model manifest/auto

Env overrides take precedence over settings:

export PRISM_MANIFEST_BASE_URL="https://manifest.example/v1"
export PRISM_MANIFEST_API_KEY="mnfst_..."   # optional alternative to /login
export PRISM_MANIFEST_MODEL="auto"          # optional
export PRISM_MANIFEST_TIER="plan"           # auto (no tier header) or a custom tier
export PRISM_MANIFEST_ENABLE_IMAGES="1"     # opt-in, see below
prism --model manifest/auto

At runtime:

/manifest status
/manifest tier plan | research | auto

Prism forwards Manifest custom routing headers and shows response metadata (X-Manifest-Tier, X-Manifest-Model, fallback headers, …) in the status line. Manifest is registered as reasoning-capable, so thinking levels are forwarded as OpenAI-compatible reasoning_effort.

Image input is opt-in (PRISM_MANIFEST_ENABLE_IMAGES=1 or manifestProvider.enableImages: true). By default Manifest is registered text-only because its public docs document OpenAI-compatible chat routing but do not guarantee vision routing for every resolved upstream model.

Bundled npm extensions

Beyond the source extensions, Prism loads npm packages that ship a pi manifest (PRISM_BUILTIN_NPM_EXTENSION_PACKAGES in src/pi/pi-extensions.ts):

  • pi-mcp-adapter — MCP tools (mcp, mcpScript)
  • @juicesharp/rpiv-voice — /voice dictation via local Whisper (sherpa-onnx); the model is downloaded on first use into ~/.pi/models/whisper-base/
  • @juicesharp/rpiv-todo — todo tool, /todos, and a panel above the editor; state is session-scoped and rebuilt from the conversation

Entry resolution (src/pi/pi-npm-extension-entry.ts) supports both packages with exports/main and packages that only declare their entry in pi.extensions. The latter count as Prism-internal, so e.g. /voice shows up without a package prefix.

Runtime patching

Prism accepts only the pi runtime version it was built against:

SUPPORTED_PI_CODING_AGENT_VERSION = "0.87.1"

Patches run against compiled pi JavaScript with exact string replacements via replaceRequired(), which is idempotent. Never hand-edit pi in node_modules — change src/pi/pi-patch-*.ts instead.

Patch areas:

  • pi-patch-auth.ts — auth storage uses PRISM_AUTH_PATH / PI_AUTH_PATH
  • pi-patch-interactive.ts — Prism/▲ branding, process title, plan-mode tool filter, usage-limit recovery menu instead of generic autoretry, _isRetryableError hardened for usage_limit_reached
  • pi-patch-session.ts — immediate persistence plus the ~/.prism/sessions.db mirror
  • pi-patch-system-prompt.ts — documentation block focused on project documentation
  • pi-patch-context-files.ts — extra always-loaded context files (PRISM_EXTRA_CONTEXT_FILES)
  • pi-patch-extension-loader.ts — treat Prism's own extensions as internal (no package prefix)
  • pi-patch-autocomplete.ts — command/argument completion behavior
  • pi-package.ts — build ~/.prism/pi-package and link the bundled pi docs/, examples/, README.md

When updating pi:

npm outdated
npm run package:update-check
npm test
npm run typecheck
npm run build
node --import tsx/esm src/cli.ts --version

Environment variables

Core:

  • PRISM_CODING_AGENT_DIR — Prism config/state directory, default ~/.prism
  • PRISM_PI_CLI_PATH / PI_CLI_PATH — override the bundled pi CLI
  • PRISM_SESSION_BACKEND — db (default) or file
  • PRISM_AUTH_PROFILE — active auth profile for this process
  • PRISM_CAVEMAN_MODE / CAVEMAN_MODE — default caveman mode

Obsidian:

  • PRISM_OBSIDIAN_VAULT_NAME — Obsidian CLI vault name (env-only resolution)
  • PRISM_OBSIDIAN_VAULT — explicit vault path
  • PI_OBSIDIAN_VAULT_NAME / PI_OBSIDIAN_VAULT — fallbacks
  • PI_OBSIDIAN_CONTEXT_DIR — restrict prompt-relevant memory search to a subdirectory
  • PRISM_OBSIDIAN_INJECT_CANDIDATES — number of per-turn candidates
  • PRISM_OBSIDIAN_CLI_TIMEOUT_MS — Obsidian CLI timeout, default 5000

Logseq:

  • PRISM_LOGSEQ_VAULT / PI_LOGSEQ_VAULT — Logseq graph path
  • PRISM_LOGSEQ_CONTEXT_DIR / PI_LOGSEQ_CONTEXT_DIR — restrict candidate search
  • PRISM_LOGSEQ_ALWAYS_CONTEXT / PI_LOGSEQ_ALWAYS_CONTEXT — always-loaded namespace prefix, default Kontext

Ollama:

  • PRISM_DISABLE_OLLAMA=1 — disable the provider
  • PRISM_OLLAMA_BASE_URL / OLLAMA_BASE_URL — accepts /api, /v1 or root; default http://localhost:11434/v1
  • PRISM_OLLAMA_API_KEY / OLLAMA_API_KEY — Ollama Cloud key; local Ollama ignores keys
  • PRISM_OLLAMA_CONTEXT_WINDOW / OLLAMA_CONTEXT_WINDOW — fallback context window, default 128000
  • PRISM_OLLAMA_MAX_TOKENS / OLLAMA_MAX_TOKENS — max output tokens, default 32000
  • PRISM_OLLAMA_SHOW_DETAILS=0 — skip /api/show capability lookups
  • PRISM_OLLAMA_TIMEOUT_MS — API timeout
  • PRISM_OLLAMA_AVAILABILITY_TIMEOUT_SECONDS — startup probe timeout, default 0.5

Manifest (each has a MANIFEST_* fallback):

  • PRISM_MANIFEST_BASE_URL, PRISM_MANIFEST_API_KEY, PRISM_MANIFEST_MODEL (default auto)
  • PRISM_MANIFEST_TIER — custom tier header; auto sends none
  • PRISM_MANIFEST_ENABLE_IMAGES=1 — opt into image input
  • PRISM_MANIFEST_CONTEXT_WINDOW, PRISM_MANIFEST_MAX_TOKENS

mex: see mex code graph.

SSH/tmux container

A CI-built container with key-only SSH, tmux and the Prism package from the latest pushed commit:

docker compose -f compose.ssh-prism.yml pull
docker compose -f compose.ssh-prism.yml up -d
docker compose -f compose.ssh-prism.yml exec prism-ssh prism-tmux

prism-tmux reconnects to an existing tmux session named prism; otherwise it creates one and starts prism. See docs/ssh-tmux-container.md.

For a local throwaway sandbox with Manifest routing, see sandbox-kit/README.md and the just sandbox-* recipes.

Repository layout

src/
├── cli.ts                         # entry point + CLI subcommands
├── session-db.ts                  # import/mirror existing JSONL sessions
├── pi/
│   ├── pi-native.ts               # delegation to the bundled pi CLI
│   ├── pi-env.ts                  # runtime paths, version guard, patch helpers
│   ├── pi-package.ts              # build ~/.prism/pi-package + patch the runtime
│   ├── pi-extensions.ts           # auto-loaded built-in extensions
│   ├── pi-patch-*.ts              # runtime patches (auth, interactive, session, prompt, …)
│   ├── plan-mode-tools.ts         # read-only tool allowlist for /plan
│   └── prism-auth.ts              # private/work auth profiles
└── prism-extensions/
    ├── commands/                  # slash commands
    ├── core/                      # shared config, vault, fuzzy, stores
    ├── integrations/              # Obsidian, Logseq, mex, research, role-play
    ├── providers/                 # Ollama, Manifest
    ├── tools/                     # hidden toolbox + toolbox tools
    └── ui/                        # toolbar, context usage, status, tool rendering

Tests live in tests/ and tests/prism-extensions/. src/pi/pi-extensions.ts is the single manifest for which extension entrypoints load automatically — a new built-in extension must be listed there.

Development

npm run typecheck
npm test
npm run build

Package helpers:

npm run package:build
npm run package:update-check
npm run package:update-build
npm run package:publish:npm   # @daniel156161/prism to npmjs

Further docs:

  • docs/safe-harness-improvement.md — self-improvement workflow and safety boundaries
  • docs/ssh-tmux-container.md — SSH/tmux container
  • docs/pi/ — vendored pi documentation
  • .mex/ROUTER.md — code-graph scaffold navigation

License

MIT — see LICENSE.