Skip to content

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Repository files navigation

Palantir Console

한국어

Goal: an independent control hub that launches AI coding sessions (Claude Code, Codex) across machines and handles instructions, approvals, status, and results from a single chat.

Direction (revised 2026-10-20, direction brief §0.2)

  • Sessions started elsewhere (a terminal, Orca, ...) are observed only. Palantir does not send them instructions. Observation moves to the vendors' official hooks in SH2–SH3.
  • Orca is an optional integration and is off by default. The core paths (observing sessions, status, instructions) work without Orca installed.
  • Available today: observing sessions by reading each machine's Claude Code and Codex transcripts, and querying them from chat (session assistant). Not built yet: the session host that launches sessions and takes instructions from chat (SH1), and hooks collection (SH2–SH3). The order is SH0–SH5 in brief §0.2.10.
  • The 3-tier delegation below (Top → Operator → Worker) is dormant. The code stays and is not deleted, but no new features go into it.
Main Manager (Top)          ← oversees all projects and Operators
 ├── Operator (Project A)         ← manages workers within the project
 │    ├── Worker 1          ← performs actual coding tasks
 │    ├── Worker 2
 │    └── Worker 3
 ├── Operator (Project B)
 │    └── Worker 1
 └── Operator (Project C)
      ├── Worker 1
      └── Worker 2

Worker — AI coding agents (Claude Code, Codex, etc.) that perform actual tasks within a project. Each worker runs in an isolated git worktree so they never collide.

Operator (Project Manager) — Assigned per-project to coordinate its workers. Distributes tasks, tracks progress, and maintains project-specific conventions and context for consistent direction.

Main Manager (Top) — The top-level orchestrator. Routes user instructions to the right Operator, manages priorities across projects, and serves as a single conversational entry point.

All layers are monitored and controlled from a single web dashboard (localhost:4177).

v3 Manager redesign shipped. See docs/specs/manager-v3-multilayer.md for the spec and docs/test-scenarios.md for the user-facing scenarios.

Quick Start

Local

npm install
npm start
open http://localhost:4177

Docker

docker compose up --build
open http://localhost:4177

Auto Setup (nvm/volta/fnm)

bash setup.sh   # auto-detects and installs Node 20+, runs npm install
npm start

Docker with Auth

# .env (Compose consumes this on the host; it is not copied into the image)
PALANTIR_TOKEN=my-secret-token
PALANTIR_PM_TOKEN=my-distinct-agent-token
ANTHROPIC_API_KEY=sk-ant-...    # optional: for a Claude-backed Manager
CODEX_API_KEY=...               # optional: for a Codex-backed Manager or Operator

docker compose up --build
# → http://localhost:4177 (send Authorization: Bearer my-secret-token)

This Compose example enables authentication, but direct environment injection is reported as an unverified actor split unless the agent runtime is isolated from the Console process by the deployment boundary.

Binding policy (changed in PR1)

By default the server now binds to 127.0.0.1 (loopback only, no auth). Setting PALANTIR_TOKEN automatically promotes the bind to 0.0.0.0 so remote clients can reach an authenticated API. If you want to listen on all interfaces without auth (discouraged), pass HOST=0.0.0.0 explicitly — the server will log a [security] WARNING in that case.

Setup HOST PALANTIR_TOKEN Bind
Dev default unset unset 127.0.0.1
Remote + auth unset set 0.0.0.0
Legacy ("always 0.0.0.0") 0.0.0.0 unset 0.0.0.0 (⚠️ open, logged)
Custom interface 192.168.x.y either as specified
PALANTIR_TOKEN=my-secret-token npm start
# → all APIs require Authorization: Bearer my-secret-token (CLI) OR
#   the palantir_token cookie set by POST /api/auth/login (browser).
# → binds to 0.0.0.0

Browser clients use an HttpOnly cookie under the hood. Visit http://host:4177/login.html, enter your token in the POST form, and you'll be redirected to the console with a palantir_token cookie set. The token never appears in a URL — earlier PR1 drafts accepted ?token= as a one-shot bootstrap, but that was removed after Codex review because the first document request would already leak the token into reverse proxy access logs. This is required because EventSource cannot send custom headers, so the /api/events SSE stream would otherwise be blocked.

The browser authenticates with PALANTIR_TOKEN through the HttpOnly cookie. Top/Operator and Worker processes never receive that global credential (or PALANTIR_PM_TOKEN). When agents are isolated from one another and from the Console by a real OS-user/container boundary, the server can issue boot-local, run-bound capabilities. Manager capabilities work only while that exact manager slot is active and only on the documented orchestration endpoints. Their values are delivered through the manager-only PALANTIR_MANAGER_TOKEN process environment and never rendered into argv or the persisted system-prompt file. Worker capabilities are accepted only by that run's candidate-only memory proposal endpoint. PALANTIR_PM_TOKEN is optional and retained as a distinct bearer credential for trusted external automation; it is not injected into agents.

Authenticated installs default to agent_capabilities_disabled. A same-UID process can inspect another process's environment (or temporary launch state), so the built-in local tmux/subprocess topology is not a capability boundary. Set PALANTIR_AGENT_PROCESS_ISOLATION=verified only when the deployment actually runs every capability-bearing agent behind a separate OS account or container boundary that prevents peer and Console-process inspection. Without that explicit attestation, managers receive no orchestration credential and workers receive no memory-proposal credential. This is fail-closed; browser and trusted external bearer access continue to work.

Run npm run diagnose:isolation (or npm run --silent diagnose:isolation -- --json for clean automation output) to see the exact policy inputs that currently block run-bound capabilities. A non-ready result exits with status 2. The command checks the runtime gate; it does not prove that an OS/container boundary exists. See the Korean isolated capability runbook before making the verified attestation.

PALANTIR_ACTOR_TOKEN_FILE 로 기동하는 경우 이 명령은 판정하지 못한다(종료 코드 3). 그 파일은 부팅 때 한 번 소비되어 애플리케이션 옵션으로 넘어가므로 환경변수로 존재하지 않는다 — 실패가 아니라 "여기서는 알 수 없음" 이다. 종료 코드 2 만 실제 미충족을 뜻한다.

Local installs must not store either global token in the repository .env (startup rejects that configuration). For the secure path, create a mode-0600, non-symlink JSON file containing PALANTIR_TOKEN and optionally PALANTIR_PM_TOKEN, then start with PALANTIR_ACTOR_TOKEN_FILE=/path/to/file; the Console validates ownership, reads it once, and unlinks it before spawning agents. This verifies token bootstrap, independently from the required agent process-isolation attestation. Direct environment variables remain supported for compatibility but are reported as an unverified token-source boundary because an unsandboxed CLI may be able to inspect its parent environment. Use an OS/container boundary if the one-shot file itself cannot be protected until startup. Windows currently rejects the one-shot file transport because Node's portable filesystem API cannot verify its DACL; use application-owned options or an OS/container secret boundary there, which remains reported as unverified unless the embedder marks it.

{"PALANTIR_TOKEN":"human-secret","PALANTIR_PM_TOKEN":"agent-secret"}

Save that JSON outside the repository with mode 0600, then pass only its path from the launcher environment:

PALANTIR_ACTOR_TOKEN_FILE=/secure/ephemeral/palantir-actor-tokens.json npm start

For an executor that genuinely provides per-agent isolation:

PALANTIR_ACTOR_TOKEN_FILE=/secure/ephemeral/palantir-actor-tokens.json \
PALANTIR_AGENT_PROCESS_ISOLATION=verified \
npm start

When enabling the split on an existing installation, rotate PALANTIR_TOKEN in the same restart. This revokes the value inherited by any legacy or remote worker that predates the split; local orphan workers are also stopped instead of reattached when they lack the credential-policy marker. Project workers with a run-bound memory proposal grant are also stopped on Console restart because that boot-local grant cannot be rewritten in a live process; safely scrubbed project-less workers remain recoverable. The same rotation is recommended when upgrading an authenticated shared-token installation that may still have workers launched by an older version. For SSH/fleet workers, set PALANTIR_BASE_URL to a Console URL reachable from the remote node. Without it, remote workers intentionally receive no memory proposal token or loopback URL; local workers derive a reachable URL from HOST and PORT.

Core Concepts

Main Manager (Top)  →  Operator (per project)  →  Worker (per task)
 (orchestrator)       (project manager)     (AI coding agent)
Concept Description
Main Manager (Top) Top-level orchestrator. Routes user instructions to the right Operator, oversees all projects
Operator (Project Manager) Per-project manager. Coordinates workers, distributes tasks, maintains project context. Lazy-spawned on first message
Worker AI agent (Claude Code or Codex) that executes a task. Runs in an isolated git worktree
Project Logical grouping of tasks. e.g. "Backend API", "Frontend Refactor"
Task A unit of work. Managed on a kanban board. Status: Backlog → Todo → In Progress → Review → Done
Run An agent execution against a Task. Multiple Runs per Task allowed
Agent Profile Agent configuration (Claude Code, Codex CLI, custom)
Conversation 1st-class identity for any chat surface: top, operator:<projectId> (pm:<projectId> accepted), or worker:<runId>

Views

1. Dashboard (◉)

Control hub. Shows only what needs attention right now — active agents, needs-input, failures, and the new Drift ⚠ badge.

  • Drift badge — summary of Operator dispatch-audit incoherences (annotate-only; hidden when zero). Click to open the Drift Drawer with per-row Operator claim vs DB truth diffs, dismiss/restore, and kind color bar.

2. Task Board (⊞)

Kanban board. Drag tasks across 5 columns. Drag to In Progress → agent execution modal opens.

3. Projects (▣)

Project list. Tasks are grouped by project. Each project exposes:

  • pm_enabled — whether the project can lazy-spawn an Operator
  • preferred_pm_adapter — Codex or Claude preference (Claude resume falls back to Codex until Phase 3b)
  • project_brief — conventions + known pitfalls injected into Operator system prompt

4. Manager (✦)

Central orchestrator. Runs a manager agent (Claude Code or Codex CLI) with multi-turn chat and v3 multi-layer routing.

  • 40/60 split layout: chat (left) + worker session grid (right)
  • Conversation target dropdown (v3 Phase 6) — lets the user send messages to the Top session or any operator:<projectId> slot (pm:<projectId> is still accepted). Operator rows are marked active when an Operator is currently spawned. @<projectName> in a message is rewritten to the matching Operator via /api/router/resolve.
  • Reset Operator button — disposes the Codex thread and clears the persisted pm_thread_id; the next message starts a fresh thread.
  • Per-Operator drift indicator (v3 Phase 7) — ⚠ N button next to Reset Operator when the selected Operator has pending incoherent audit rows.
  • Manager queries the Palantir Console REST API via curl to report real agent/task status.
  • Supports Claude Code CLI (--print --output-format stream-json --input-format stream-json protocol) and Codex CLI (codex exec --json + resume via codex exec resume <thread_id>).

5. Agents (⚙)

Agent profile management. Default profiles: Claude Code and Codex CLI. Agent profiles can gate dispatch via capabilities_json and max_concurrent.

6. Resources (❖) — #resources

Consolidated tab group (nav-consolidation). Three sub-tabs:

  • Skill Packs (#resources/skills, formerly #skills) — MCP server templates and skill pack management. Browse the gallery registry, install from registry or URL, import/export as JSON. Packs can be bound to projects, tasks, and runs.
  • Presets (#resources/presets, formerly #presets) — Worker Preset management. Bundle agent profile + plugin refs + MCP server templates + system prompt into a reusable preset. Link presets to tasks via preferred_preset_id. Run Inspector shows frozen snapshot vs current preset drift.
  • MCP Servers (#resources/mcp-servers, formerly #mcp-servers) — MCP server template CRUD UI (M3-UI, PR #119). Add / edit / delete the templates that Skill Packs and Presets reference by alias. Templates carry command, args, env, allowed_env_keys, and updated_at (migration 020) — RunInspector compares the snapshot's updated_at against the current template to surface body-level drift even though the snapshot only stores the template id.

Legacy hashes #skills, #presets, #mcp-servers redirect to their canonical sub-routes via the app.js redirect map.

7. Memory (◈) — #memory

8. Operator (✸) — #operator

Consolidated tab group (nav-consolidation). Main sub-tabs:

  • Operator Roster (#operator) — create durable Operator instances, map codebases, manage schedules, and select each instance's CLI (Codex, Claude Code, or automatic fallback). Changing CLI preserves the Operator identity/profile/mappings/schedules and resets only its runtime conversation thread.
  • Codebases (#operator/codebases) — inspect and manage Operator codebase placement.
  • Operator Profiles (#operator/profiles, formerly #operator-profiles) — Operator profile CRUD (PF-1/PF-2).
  • Specialist (#operator/specialist) — Invoke a folder-less specialist worker against an active manager run.

Theme toggle

Light mode launched in PR #150~#153 (K-2). The NavSidebar bottom toggle is 3-state — ◑ system (auto via prefers-color-scheme) / ☀ light / ☽ dark — and the choice is stored in localStorage.palantir.theme. server/public/theme-init.js runs in <head> before tokens.css to set <html data-theme> and patch <meta name="theme-color"> so there is no FOUC and the mobile chrome color follows the active theme.

API

REST API for external control. When auth is enabled, include Authorization: Bearer <token> header.

Projects

GET    /api/projects           — list
POST   /api/projects           — create { name, directory?, color?, pm_enabled?, preferred_pm_adapter? }
GET    /api/projects/:id       — get
PATCH  /api/projects/:id       — update
DELETE /api/projects/:id       — delete (fail-closed: aborts if operatorCleanupService cannot dispose a live Operator)
GET    /api/projects/:id/tasks — list tasks
GET    /api/projects/:id/brief — read project brief (conventions + known pitfalls)
PATCH  /api/projects/:id/brief — partial update { conventions?, known_pitfalls? }

Tasks

GET    /api/tasks              — list (?project_id=, ?status=)
POST   /api/tasks              — create { title, project_id?, priority?, description?, task_kind?, requires_capabilities?, acceptance_criteria? }
GET    /api/tasks/:id          — get
PATCH  /api/tasks/:id          — update
PATCH  /api/tasks/:id/status   — change status { status }
DELETE /api/tasks/:id          — delete
PATCH  /api/tasks/reorder      — reorder { orderedIds: [] }
POST   /api/tasks/:id/execute  — run agent { agent_profile_id, prompt? }

Operator instances

GET    /api/operator-instances              — list durable Operator instances
POST   /api/operator-instances              — create { profile_id, display_name?, primary_project_id?, preferred_adapter? }
PATCH  /api/operator-instances/:id/adapter  — switch CLI { preferred_adapter: "codex" | "claude" | null }; resets only the runtime thread

Runs

GET    /api/runs               — list (?task_id=, ?status=)
GET    /api/runs/:id           — get
GET    /api/runs/:id/events    — event list
GET    /api/runs/:id/output    — live output (tmux)
POST   /api/runs/:id/input     — send input { text } (delegates to conversationService, same parent-notice router)
POST   /api/runs/:id/cancel    — cancel
DELETE /api/runs/:id           — delete

Agents

GET    /api/agents             — list profiles
POST   /api/agents             — create { name, type, command, args_template?, max_concurrent?, capabilities_json?, env_allowlist? }
GET    /api/agents/:id         — get (+ runningCount)
GET    /api/agents/:id/usage   — provider-backed usage snapshot for this profile
PATCH  /api/agents/:id         — update
DELETE /api/agents/:id         — delete

Manager Session (Top + Operator)

POST   /api/manager/start              — start the Top manager { prompt?, cwd?, model?, agent_profile_id? }
POST   /api/manager/message            — send to Top (delegates to conversationService.sendMessage('top', ...))
GET    /api/manager/status             — { active, run, usage, claudeSessionId, top: {...}, pms: [...] }
GET    /api/manager/events             — Top event list (incremental via ?after=<id>)
GET    /api/manager/output             — Top output text
POST   /api/manager/stop               — stop Top (also clears pending parent-notice queue for Top's runId)
POST   /api/manager/pm/:projectId/message — lazy-spawn Operator if needed, then send
POST   /api/manager/pm/:projectId/reset   — single-owner teardown: dispose adapter, cancel run, clear pm_thread_id, drop registry slot

Conversations (1st-class) — v3 Phase 1.5+

GET    /api/conversations/:id          — resolve { conversation: { kind, conversationId, run? } }
POST   /api/conversations/:id/message  — send { text, images? } — `id` is 'top' | 'operator:<projectId>' | 'worker:<runId>' (`pm:<projectId>` accepted)
GET    /api/conversations/:id/events   — event list (incremental ?after=<id>)

Router (v3 Phase 6)

POST   /api/router/resolve             — { text, currentConversationId?, defaultConversationId? }
                                         → { target, text, matchedRule, ambiguous?, candidates? }

Dispatch Audit (v3 Phase 4 + 7) — annotate-only reconciliation

POST   /api/dispatch-audit             — record a Operator claim
                                         { project_id, task_id?, pm_run_id?, selected_agent_profile_id?, rationale?, pm_claim: { kind, task_id? / run_id? } }
                                         → 201 { audit: { ..., incoherence_flag, incoherence_kind } }
GET    /api/dispatch-audit             — list (?project_id=, ?incoherent_only=1, ?limit=<1..500>)

Supported pm_claim.kind values: task_complete, task_in_progress, worker_spawned, worker_running, worker_completed, worker_failed. Unknown kinds are stored with incoherence_flag=0, incoherence_kind='unknown_kind' so later matchers can widen without rewriting history.

Legacy / support routes

GET    /api/sessions                    — list legacy OpenCode sessions
GET    /api/sessions/:id                — read a single session (with messages)
POST   /api/sessions                    — create a new session
POST   /api/sessions/:id/message        — append a message { content }
PATCH  /api/sessions/:id                — rename
DELETE /api/sessions/:id                — move to trash

GET    /api/trash/sessions              — list trashed sessions
POST   /api/trash/sessions/:trashId/restore — restore a trashed session
DELETE /api/trash/sessions/:trashId     — permanent delete

GET    /api/fs                          — directory browse (?path=)

GET    /api/usage/providers             — aggregated provider usage (Codex / Anthropic / …)
GET    /api/usage/codex-status          — Codex-specific connection/auth status

GET    /api/claude-sessions             — active Claude Code subprocesses (Manager + workers)

SSE / Health

GET    /api/events             — SSE stream
GET    /api/health             — health check

Worker Presets (Phase 10B)

GET    /api/worker-presets             — list
POST   /api/worker-presets             — create
GET    /api/worker-presets/:id         — get
PATCH  /api/worker-presets/:id         — update
DELETE /api/worker-presets/:id         — delete (app-level cascade: tasks.preferred_preset_id → NULL)
GET    /api/worker-presets/plugin-refs — available plugin directories

MCP Server Templates (M3-UI, PR #119)

GET    /api/mcp-server-templates       — list
POST   /api/mcp-server-templates       — create { alias, command, args?, env?, allowed_env_keys? }
GET    /api/mcp-server-templates/:id   — get
PATCH  /api/mcp-server-templates/:id   — update (bumps `updated_at` so RunInspector can show drift vs preset snapshot)
DELETE /api/mcp-server-templates/:id   — delete (rejected if a preset references it)

Skill Packs (Phase 10G)

GET    /api/skill-packs                — list installed (MCP server templates)
POST   /api/skill-packs               — create template
GET    /api/skill-packs/:id            — get
PATCH  /api/skill-packs/:id            — update
DELETE /api/skill-packs/:id            — delete
GET    /api/skill-packs/:id/export     — export as JSON
POST   /api/skill-packs/import         — import from JSON
GET    /api/skill-packs/templates      — list templates
GET    /api/skill-packs/registry       — browse gallery registry
GET    /api/skill-packs/registry/pack  — get single pack detail
POST   /api/skill-packs/registry/install     — install from registry
POST   /api/skill-packs/registry/install-url — install from URL (SSRF-guarded)
POST   /api/skill-packs/registry/update      — update installed pack
POST   /api/skill-packs/registry/refresh     — refresh registry cache

Project/Task/Run bindings (mounted via skillPacks.projectBindings / taskBindings / runSnapshots):

GET    /api/projects/:id/skill-packs   — project's skill packs
POST   /api/projects/:id/skill-packs   — bind pack to project
PATCH  /api/projects/:id/skill-packs/:packId — update binding
DELETE /api/projects/:id/skill-packs/:packId — unbind
GET    /api/tasks/:id/skill-packs      — task's skill packs
POST   /api/tasks/:id/skill-packs      — bind pack to task
DELETE /api/tasks/:id/skill-packs/:packId   — unbind
GET    /api/runs/:id/skill-packs       — run's resolved packs
PATCH  /api/runs/:id/skill-packs/checks — update pack checks

API reference completeness: the sections above enumerate every route mounted by server/app.js at Phase 10G merge. When adding a new route, mount it in app.js AND add it to this section — otherwise this file silently drifts out of sync with the server.

SSE channels

Channel Meaning v3 semantic envelope fields
task:created / task:updated / task:deleted Task mutations —
run:created New run row —
run:status Any run status transition (incl. createRun normalized emit) from_status, to_status, reason, task_id, project_id
run:ended Terminal transition same as run:status
run:completed Agent exit captured in health loop same + reason='agent-exit-success' | 'agent-exit-error(N)'
run:needs_input Priority alert — idle timeout detected same + priority: 'alert'
run:event Per-vendor raw event (high volume) —
manager:started / manager:stopped Top manager lifecycle —
dispatch_audit:recorded New Operator dispatch claim audited audit, project_id, pm_run_id, incoherence_flag, incoherence_kind

Client pattern: the Drift badge + drawer and run:needs_input tab-title pulse are both wired through these semantic fields. run:status is a pure reload trigger and does NOT fire priority notifications — that responsibility belongs to the dedicated channels (run:needs_input, run:completed) to avoid duplicate alerts.

Creating a Worker Preset

Worker Presets bundle a system prompt, MCP server set, and (optionally) host-isolated plugin directories so a worker spawn is reproducible across machines. Spec: docs/specs/worker-preset-and-plugin-injection.md.

When to use

  • You want a Claude worker that loads ecosystem plugins (e.g. agent-olympus) without polluting your host ~/.claude/.
  • You want to enforce a specific MCP server set per task class.
  • You want forensic snapshots of "exactly what plugin files / prompt / MCP config the worker ran with" for past runs.

Steps

  1. Drop a Claude Code plugin under server/plugins/<name>/ with a plugin.json at its root. Example:

    server/plugins/agent-olympus/
      plugin.json
      skills/
      commands/
      agents/
    

    The directory is gitignored — operators place plugins by hand. The CI suite uses fixtures under server/tests/fixtures/plugins/.

  2. Open the Presets view (#resources/presets) and create a preset. Fields:

    • Plugin Refs — one or more directory names from server/plugins/.
    • MCP Server Templates — pick from existing mcp_server_templates entries (managed by the Skill Pack subsystem).
    • Base System Prompt (≤16KB) — prepended to skill-pack sections.
    • Isolated — Tier 2 (Claude only). Adds --bare, --strict-mcp-config, --setting-sources, and one --plugin-dir flag per ref to the worker spawn. Non-Claude workers get a preset:tier2_skipped warning and continue with Tier 1 only.
    • Min Claude Version — semver gate enforced before spawn.
    • Setting Sources — passed as --setting-sources <value>. Default empty disables host setting inheritance entirely.
  3. Set the preset on a Task (the Worker Preset dropdown in Execute Task). The dropdown defaults to the task's preferred_preset_id. Operator can override per-execute.

  4. After the run finishes, open Run Inspector → Preset to see the frozen snapshot, the current preset row, and any drift between them.

Auth in isolated mode

--bare Claude ignores OAuth and the macOS keychain. By default Palantir does not read, store, forward, or convert Claude OAuth credentials, so an isolated preset only authenticates with an actual ANTHROPIC_API_KEY (not an sk-ant-oat* OAuth token) or a cloud-provider auth mode; otherwise it fails closed with a 400 + diagnostic. PALANTIR_LEGACY_CLAUDE_CREDENTIAL_ACCESS=1 restores the old materialization (env → .claude-auth.json → keychain claudeAiOauth.accessToken, written to a temporary apiKeyHelper).

Snapshot semantics

run_preset_snapshots rows are written at preset-resolve time (before spawn), keyed by run_id with <pluginRef>/<relpath> namespaced file hashes. Deleting a preset later does not erase past snapshot rows; tasks.preferred_preset_id is set NULL via app-level cascade.

Codex manager sessions launched through codexAdapter always run with --dangerously-bypass-approvals-and-sandbox; there is no environment-variable switch for this behavior. Managers need network access to call the Palantir Console API, and the --full-auto sandbox blocks that access, making orchestration impossible. Codex task workers use the separate lifecycle worker path: their approval and sandbox flags come from the profile's editable args_template. The default exec {prompt} profile does not add the bypass flag.

Environment Variables

Variable Default Description
PORT 4177 Server port
PALANTIR_TOKEN (none) Enables Bearer/cookie auth and promotes bind from 127.0.0.1 to 0.0.0.0
PALANTIR_PM_TOKEN (none) Optional distinct bearer credential for trusted external automation; never injected into agent processes
PALANTIR_ACTOR_TOKEN_FILE (none) POSIX only: mode-0600 one-shot JSON containing the two actor tokens; consumed and unlinked before agent startup (Windows fails closed because DACLs cannot be verified portably)
PALANTIR_AGENT_PROCESS_ISOLATION (none) Set to verified only when every capability-bearing agent is isolated by a separate OS account or container; otherwise run-bound agent capabilities stay disabled
PALANTIR_GIT_ENV_ALLOWLIST (none) Additional node-local environment variable names inherited by Git operations (comma-separated), for example an askpass helper's companion credential
PALANTIR_PROJECT_TEST_ENV_ALLOWLIST (none) Additional node-local environment variable names inherited by materialized project test commands (comma-separated), for example PYTHONPATH
HOST auto Override the bind address. 0.0.0.0 without a token logs a security warning
PALANTIR_ALLOWED_COMMANDS (none) Additional allowed CLI commands (comma-separated)
PALANTIR_DEFAULT_PM_ADAPTER codex Global Operator adapter fallback when an instance uses Auto and its project has no preferred_pm_adapter
ANTHROPIC_BASE_URL / CLAUDE_CODE_OAUTH_TOKEN / ANTHROPIC_API_KEY — Claude Code auth. By default OAuth values (CLAUDE_CODE_OAUTH_TOKEN, sk-ant-oat* keys) are removed at boot and never forwarded; the claude CLI reads its own login. An actual API key is still used
PALANTIR_LEGACY_CLAUDE_CREDENTIAL_ACCESS (off) Exactly 1 restores legacy Claude credential handling (.claude-auth.json save/restore, token materialization for --bare/isolated/distiller, usage lookup). Not an SH1-supported configuration
CODEX_API_KEY / OPENAI_API_KEY — Codex auth (preflight checks ~/.codex/auth.json)
CODEX_BIN codex Codex CLI path
CODEX_HOME ~/.codex Codex config home
OPENCODE_STORAGE ~/.local/share/opencode/storage OpenCode session storage path
OPENCODE_BIN opencode OpenCode binary path
OPENCODE_FS_ROOT $HOME Directory picker root path

Tech Stack

  • Backend: Express.js 5, SQLite (WAL mode, better-sqlite3), EventEmitter SSE
  • Frontend: Preact + HTM (ESM + UMD, no build step), hash router, self-hosted Inter font
  • Worker agents: tmux session + git worktree isolation
  • Manager agents: Claude Code CLI (stream-json NDJSON) OR Codex CLI (codex exec --json + thread resume), selected per agent profile
  • Real-time: SSE (Server-Sent Events) with Last-Event-ID replay
  • Tests: Node.js built-in test runner + supertest (902 unit/integration) + Playwright e2e (smoke + manager + a11y 32 + visual 32) at PR #169, 2026-04-29

Development

npm test          # run tests (902 unit/integration)
npm run test:e2e  # Playwright e2e (smoke + manager + a11y + visual)
npm run test:a11y # axe-core a11y only (K-4, 32 scenarios — 8 routes × 2 themes × 2 viewports)
npm run test:visual # Playwright screenshot diff (K-5, same 32 scenarios)
npm run dev       # dev server

Data is stored in palantir.db (SQLite). Auto-migrated on server start (server/db/migrations/001..021_*.sql; the latest two are 020_mcp_template_updated_at.sql and 021_skill_pack_origin_type_check.sql).

See also:

  • docs/specs/manager-v3-multilayer.md — the v3 redesign spec (lock-in + phase history)
  • docs/specs/worker-preset-and-plugin-injection.md — Phase 10 Worker Preset spec
  • docs/specs/skill-packs.md — Skill Pack spec
  • docs/specs/light-theme-k2-brief-2026-04-28.md — K-2 light mode launch brief (LAUNCHED stamp)
  • docs/handoff-post-k2-launch-2026-04-29.md — UI/UX cleanup + K-2 launch series handoff
  • docs/test-scenarios.md — QA scenarios (PRJ, TSK, BRD, RUN, INS, MGR, Operator, DRIFT, ROUTER, SSE, REG, PRESET, …)
  • CLAUDE.md — project conventions + autonomous-mode working style

License

ISC

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages