Command Center is a personal operational OS for Obsidian — a local-first AI multi-agent orchestrator that turns your vault into a single, navigable control room. One dashboard gives you a zero-token “happening now” snapshot of today's note, unfiled captures, open tasks, and managed workspaces; a calendar for creating and completing dated work; a doorway that jumps to any note, folder, tag, or Bases view; and a Markdown-backed Command Deck that turns your workflow files into one-click buttons. Behind it sits a 13-provider routing layer, a local Pi ReAct engine with Orchestrator–Worker loops, hybrid vault RAG (BM25 + semantic retrieval), persistent agent memory, native Markdown/Canvas workflows with Bases queue integration, voice input and live transcription, extensible MCP and REST connectors, and headless automation — all behind an absolute write gate, and all without imposing a productivity framework on your notes.
Important
Command Center can modify vault files when you approve or run mutating operations. Keep backups, review destructive action cards, and test workflows on non-critical notes first.
Most AI integrations add a chat box. Command Center adds an operational layer:
- Framework-agnostic by design — no required PARA, GTD, Johnny.Decimal, folder taxonomy, note schema, or life-management methodology. The setup interview learns the structures already used in your vault.
- Metacognitive Partner, not prescriptive organizer — two-stage Socratic Triage first learns your goals, constraints, language, and personal definition of efficiency, then negotiates topology observations as neutral evidence. It preserves intentional friction and proposes capabilities only with consent.
- Interview-driven configuration — embedded dashboard discovery collects topology, life map, capacity rules, triage policy, focus constraints, and writing style; confirmation and synthesis then generate only the assets you approve.
- Token-efficient stationary indexing — protected
_index.mdfiles describe folder purpose and direct-child contents so agents can route work without repeatedly scanning the whole vault. - Built-in Obsidian Secrets — API keys are managed through Obsidian's native Secret Storage, so they persist with your vault instead of a custom encrypted file. Keys are edited from a dedicated settings modal, and keyed cloud providers remain available whenever their secrets are present.
- Local-first options — Pi, Ollama, LM Studio, custom OpenAI-compatible endpoints, local embeddings, and deterministic fallback retrieval support private or disconnected workflows.
- Human control at mutation boundaries — an absolute write gate wraps every capability, so no agent can touch a file without your explicit click. Approval cards show target paths and syntax-colored diffs, an append-only log records every decision, and you may delegate write authority with a global Auto write toggle while keeping chosen folders permanently click-gated.
- Zero-cost intelligence — the four dashboard cards, the calendar, and the vault doorway are computed entirely from Obsidian's own metadata cache. They populate instantly and cost no API tokens, reserving model spend for actual reasoning.
- A hub, not another chat box — dates, tasks, notes, folders, tags, Bases views, and workflows are all reachable and actionable from one responsive grid, so recording and finding information never means hunting through folders.
- The six core principles
- Feature overview
- Architecture
- Installation
- First-run onboarding
- Configuration
- Everyday usage
- Write gate and approvals
- Workflows and Bases
- Voice and automation
- Privacy and security model
- Development
- Future improvements
- Quality, security, and release controls
- Community and support
- License and attribution
Every feature in Command Center answers to one of six principles. They are design constraints, not slogans: each one names the code that enforces it, so a claim in this README can be checked against the implementation.
No agent writes to your vault without your explicit approval.
Implemented in src/security/WriteGate.ts. gateTools() wraps every capability handed to a model so authorization happens inside the tool's execute path — a forgotten check at a call site cannot bypass it, because there is no ungated route to a tool. getGatedTools() is the only sanctioned way to obtain capabilities. Mutations surface as proposals with target paths and diffs; protected paths override even the global Auto write toggle, matched prefix-exactly so Vault/Private never captures Vault/PrivateNotes. Every decision — approved, rejected, timed out, or auto-approved — lands in an append-only log on the dashboard. Dashboard task edits abort if the target line changed while awaiting approval, and success is reported only after the write completes.
Situational awareness must never cost a token.
Implemented in src/intelligence/VaultDataBridge.ts, following Dataview's model: read only Obsidian's metadataCache and cachedRead, never a model. It powers the four “Happening now” cards, the calendar, and the vault doorway. One snapshot feeds every surface, in-flight scans are shared rather than duplicated, and results are bounded (25 captures, 200 tasks) so a large vault cannot stall the UI. Model spend is reserved for actual reasoning — dashboards are free.
Your vault is the configuration. Extend the plugin by writing notes, not by editing settings JSON.
Implemented in src/ui/CommandDeck.ts, src/ui/CustomCards.ts, and src/connectors/ApiConnectorManager.ts. Workflow files become deck buttons, and any note carrying cc-card: true becomes a dashboard card — discovered, not registered. Both hot-register on vault events with no Obsidian restart. New tools, MCP servers, and REST connectors join the same CapabilityRegistry at runtime. Connectors are strictly declarative: a validated method, path, and schema, never downloaded code.
You can always see what the system did, what it is about to do, and what it cost.
Implemented across the ReAct monitor, the write-gate log, and the provenance line on every intelligence card (scan time plus “no tokens used”). Panels state their data source and say plainly when they are unconfigured or empty rather than rendering a misleading blank. Failures degrade visibly with the actual error text — no silent blanking, no frozen panel. Action blocks are stripped from visible chat, executed through real APIs, and confirmed back into model context, so the transcript reflects what actually happened rather than what was merely claimed.
Use what Obsidian already provides instead of reimplementing it.
Writes go through Vault.process, which is atomic and compatible with native File Recovery. Tasks use standard Markdown checkboxes with inline fields, so Dataview, Tasks, Kanban, and Bases keep working on whatever Command Center produces. .base views render through Obsidian's own renderer; folders reveal in the native file explorer; tag searches hand off to the built-in global search; card bodies render via MarkdownRenderer, so embeds, callouts, and Dataview blocks work unchanged. Styling uses Obsidian theme variables throughout, so the plugin inherits your theme rather than fighting it.
One surface for recording, finding, deciding, and acting.
The dashboard is a doorway, not a destination: dates, tasks, notes, folders, tags, Bases views, and workflows are all reachable and actionable from one responsive grid. The vault doorway jumps anywhere in the vault; the calendar creates and completes dated work; the embedded browser keeps documentation beside your notes, expandable inline or poppable into its own pane. Every panel is reorderable, resizable, and hideable per vault, and each one states its purpose and next action so nothing needs to be guessed.
Note
Principles 1 and 2 sometimes constrain features that would be easier to build otherwise — that is intentional. A dashboard that quietly spends tokens, or an agent that writes without asking, would be more convenient and less trustworthy.
Command Center exposes one dispatch layer across 13 providers:
| Provider | Type | Notes |
|---|---|---|
| Pi Daemon | Local companion | Serialized Pi JSONL RPC; keyless at the plugin boundary |
| OpenAI | Cloud | GPT/o-series, vision, embeddings |
| Anthropic | Cloud | Claude, tools, prompt caching |
| Google Gemini | Cloud | Multimodal, long context, cached-content support |
| OpenRouter | Cloud gateway | Multi-model OpenAI-compatible routing |
| Ollama | Local | Local chat, keep-alive lifecycle controls, and optional bearer authentication |
| Groq | Cloud | Low-latency inference and transcription-compatible routing |
| DeepInfra | Cloud | Hosted open-weight models |
| Mistral AI | Cloud | Mistral, Codestral, and Voxtral families with native STT/TTS (/v1/audio/transcriptions, /v1/audio/speech). |
| Cohere | Cloud | Command models for RAG with native STT (/v2/audio/transcriptions). |
| LM Studio | Local | Dynamic native model resolution, resource-aware JIT loading, OpenAI-compatible inference, and optional bearer authentication |
| xAI (Grok) | Cloud | Grok models with vision, tools, native STT (/v1/stt), and TTS (/v1/tts). |
| Custom Endpoint | Local or remote | User-defined OpenAI-compatible service with optional bearer authentication |
Routing classifies work as coding, vision, reading, reasoning, or fast. Capability checks prevent invalid model selection; optional exponential moving averages optimize initial routes for latency, cost, or a balanced objective. Recovery remains reliability-first: authentication and invalid-request failures fail or fall through immediately, while rate limits, network errors, timeouts, and server errors use isolated circuit breakers, bounded backoff, and a configurable multi-tier fallback chain.
Additional provider capabilities include:
- Background model discovery with persistent catalogs and static-registry fallback — live models auto-fetch from each enabled provider's
/modelsendpoint on startup, covering chat, STT, and TTS model resolution - Anthropic prompt caching and Gemini cached-content bookkeeping
- Multimodal image preprocessing for vault attachments and Canvas file nodes
- Structured-output repair only at model-authored JSON boundaries
- Local model pre-warm, TTL/keep-alive, best-effort eviction, and auto-download of missing models
- LM Studio model download via
POST /api/v1/models/downloadwith progress tracking - Dynamic LM Studio model resolution through
/api/v1/models: reuse a loaded primary LLM or select the smallest downloaded non-draft conversational model, excluding embedding and speculative draft models - Optional secure-vault bearer tokens for LM Studio Require Authentication, authenticated Ollama proxies, and custom OpenAI-compatible endpoints; unauthenticated local operation remains supported
- Cloud-bound payload scrubbing of local-only lifecycle fields
The ReAct runtime follows an Orchestrator → Worker → Observation → Correction loop:
- The orchestrator reasons about the objective and selects one or more workers.
- Independent workers are planned in parallel and transported safely over serialized Pi RPC.
- Observations return to the orchestrator with evaluation scorecards.
- Validation detects incomplete, circular, hedged, conflicting, or error-heavy output.
- The loop corrects, re-routes, or synthesizes a final answer.
Built-in worker profiles cover orchestration, retrieval, summarization, and structural editing. ReAct-capable profiles (react-orchestrator, react-analyst) extend these with iterative reason-act-observe loops. Five standard agent roles—Orchestrator, Triage, Indexer, Health, and System Architect—bind each operational responsibility to a compute tier and least-privilege tool ceiling, and the runtime can create constrained custom roles without granting tools outside the parent worker's ceiling.
Role vocabulary (three layers)
The codebase uses three distinct, layered vocabularies — they are intentionally not collapsed, because each keys a different table:
WorkerProfileName(src/types.ts) — the 4 static prompt+token configs insrc/workers/:orchestrator,retriever,summarizer,editor. Smallest and most stable.AgentWorkerProfile(src/execution/ExecutionRouter.ts) — a superset addingreact-orchestratorandreact-analyst, the ReAct-capable profiles that have no static prompt entry but declare an execution modality (text/embeddings/…).StandardAgentRole(src/engine/AgentTypes.ts) — the 5 operational roles above; each maps to a compute tier + a worker profile + aTaskTypeviaAGENT_TAXONOMY.Task.workerRolereuses this union.
The pi-daemon string is a sentinel, not a profile: command-palette local tasks set workerProfile: 'pi-daemon' to route directly to the local Pi daemon via router.routeDirect.
Operational safeguards include:
- Same-cycle target conflict detection and normalized FIFO file locks
- Circuit breakers, retry/backoff, timeout recovery, deadlock detection, and safe-state rollback
- Four-dimension evaluation: completeness, relevance, specificity, and correctness
- Cooperative Debug / Step Mode that pauses only at safe cycle boundaries
- A fixed 50-row ReAct monitor with All, Actions & corrections, and Errors filters
- Full-fidelity session replay and Markdown audit export
Command Center can ground model calls in vault content without rebuilding the index on every query:
- Markdown is chunked into semantic 300–500-word units aligned to headings, paragraphs, and sentences.
- Chunk metadata retains path, H1/H2 hierarchy, normalized wikilinks, and inclusive line ranges.
- Path + mtime + size keys skip unchanged reads and embeddings.
- BM25 lexical ranking and cosine semantic ranking are merged through weighted reciprocal rank fusion (RRF).
- Folder scopes constrain retrieval, and cited snippets remain inside a hard prompt budget.
- Unavailable embedding services degrade to deterministic local term-frequency vectors.
Persistent agent memory stores facts, preferences, entities, and session summaries in vault-native state. Semantic duplicate updates, thematic session hubs, threshold-aware pruning, and bounded prompt injection keep memory useful without allowing it to grow without control.
Command Center acts as a Metacognitive Partner: it helps users examine and negotiate how their own system works rather than grading it against a generic productivity framework. Discovery follows two deliberate stages:
- Contextual baseline — one focused Socratic question at a time establishes goals, constraints, working context, preferred cognitive style, and the user's subjective definition of success and efficiency.
- Topographical negotiation — only after that baseline exists does Command Center introduce read-only vault observations. Patterns are treated as hypotheses; intentional exceptions and useful friction are preserved, and automation, semantic linking, or multi-agent synthesis are offered as optional capability expansions with explicit tradeoffs.
The metacognition layer builds supporting local context without reorganizing or rewriting user notes:
TopographySweepuses Obsidian'sTAbstractFile,TFile,TFolder,MetadataCache, andgetAllTagsAPIs to map folders, tag frequencies, links, and hub/MOC candidates.- The sweep runs silently and cooperatively, excludes
.obsidianand.trash, and writes only.obsidian/plugins/command-center/vault_topography.json. - Logic Discovery onboarding is consent-led and treats topology as neutral evidence requiring user confirmation. Confirmed preferences and the transcript are stored in
user_logic_profile.json. - Header-aware Markdown chunking preserves
##/###boundaries, source lines, frontmatter tags/aliases, and outbound[[wikilinks]]. - The semantic database schema separates documents, chunks, and vectors. With an injected desktop SQLite-VSS driver, document replacement is transactional and nearest-neighbor search is persisted locally; the distributed build otherwise uses a process-lifetime in-memory index.
- Dialectic RAG requests only the
embeddingsmodality through the Native Auto-Router and Python execution boundary. The shipped Python worker is a secure transport stub and reports that no embedding backend is configured; an integrated backend must return normalized, dimension-validated vectors before they can be stored.
Workflows are vault-native rather than hidden in a remote service:
- Parse Markdown frontmatter or JSON Canvas graphs into validated DAGs
- Collect typed text, dropdown, and toggle inputs in native Obsidian modals
- Execute independent steps in parallel topological tiers
- Evaluate constrained conditions over inputs and earlier step results—without
eval - Interpolate
{{inputs.*}}and{{steps.*.result}} - Route each step through a provider or Pi policy
- Export Markdown workflows to deterministic, executable Canvas layouts
The Command Center Queue integrates with Obsidian Bases. It consumes native evaluated results, preserves filters/formulas/sorts/limits, excludes terminal notes, supports selection and bounded concurrency, and writes agent_status, score, and timestamp fields through processFrontMatter() so active Bases views refresh in real time.
The interview becomes the source of truth for daily operations:
- Morning capacity evaluation, inbox proposals, and daily-note assembly
- Midday text or voice updates under a stable log heading
- Evening review with explicit complete, rollover, discard, or leave decisions
- Optional Silent Daily Startup that assembles and opens the note while leaving inbox mutations unapproved
- Collision-safe inbox move/archive/extract/delete proposals
- Frog/aging audits and configurable capacity rules
- Protected
_index.mdmanifests maintained from direct-child scans
Stationary indexes contain purpose, scope, summary, and status metadata. Compact purpose headers allow routing to the correct folder before deeper retrieval, reducing full-vault reads and prompt waste.
The full-page Command Center Dashboard is the single operational interface for Socratic vault discovery, onboarding, agent monitoring, queue control, approvals, and daily operations. Discovery is a dashboard mode—not a separate deck, pane, or modal. It begins with a contextual baseline before introducing read-only TopographySweep evidence. Topology remains supporting evidence and is never promoted into a rule without user confirmation.
Logic Discovery uses bounded generation and disables model reasoning where supported so the dashboard presents one concise visible question at a time. With LM Studio enabled, Command Center discovers native catalog state through /api/v1/models, prefers an already loaded primary conversational model, or JIT-loads the smallest suitable downloaded model before calling /v1/chat/completions.
Open Command Center from the ribbon or run Command Center: Start Setup / Onboarding Interview. Both routes use the same full-page dashboard.
Command Center now supports the Model Context Protocol for discovering and executing external tools from MCP servers. Add MCP server URLs in settings to make their tools available to the LLM during inference:
- JSON-RPC 2.0 transport over HTTP/SSE
- Dynamic tool discovery via
tools/list— tools are wrapped asToolDefinitions - Error isolation — one MCP server failing doesn't affect others
- LM Studio MCP — LM Studio can be configured as an MCP host at
/api/v1/mcp
Standard and Python-backed agent work crosses a mandatory execution boundary:
NativeAutoRouterreads the shippedmodel_matrix.jsonand applies the global 1–10 quality/cost depth to text, image, audio, video, and embedding intents.- Orchestrator, summarizer, editor, retrieval, and ReAct worker profiles declare an explicit modality before provider/model resolution.
- Python workers use isolated JSON-RPC 2.0 subprocesses over stdin/stdout with
shell: false, bounded output, cancellation, timeouts, cleanup, and circuit breaking. Credentials are never placed in argv or environment variables. DataNormalizeris the trust boundary for provider responses, Python results, intermediate observations, and multi-agent merges. It sanitizes tracebacks, stderr, malformed JSON, control characters, and oversized output before UI or vault use.- Locked or failed keyed routes retain local-first behavior through provider usability checks and circuit-breaker fallback.
Run Command Center: Run Shadow-Clone Diagnostics from the command palette to verify credential-memory wiping, current slider/matrix routing, fail-safe local routing, and Python-output sanitization. The harness uses in-memory fixtures and prints a sanitized report to the developer console; it does not modify user notes.
When enabled in settings, Command Center includes a server-side web search tool in requests routed through OpenRouter. The model can invoke web_search_call to pull live information from the web, with results and citations returned directly in the response. Controlled by the webSearchEnabled setting toggle.
The right-sidebar chat supports Quick, ReAct, and Workflow modes with:
- Provider/model status and streamed Markdown responses
- Bounded multi-turn history
- Active editor selection,
@Note,@path, and.basecontext - Dismissible active/recent-note suggestion pills
- Inline collapsible ReAct traces
- Dashboard handoff for approval/rejection of destructive tools
- Tail-aware auto-scroll and lifecycle-safe cancellation
- Message actions: copy to clipboard, delete, and read-aloud buttons with SVG icons
- Code block copy: hover-revealed copy button on every rendered code block
- Blinking streaming cursor (
▊) on pending assistant messages - Hover-revealed action bar: timestamp, copy, delete, and read-aloud fade in on bubble hover
- Scroll-to-bottom button: appears when chat history is scrolled up
- New conversation and Markdown export with tagged frontmatter
Command Center now includes a Capability Registry — a central, discoverable surface for every instrument the agent can invoke. Instead of the orchestrator pre-selecting which tools to use, the model can autonomously reason about which capability serves each task:
- Unified registry: Vault tools (read, write, search, list), web search, MCP-discovered tools, and agent worker profiles all register in one place.
- User-configurable: Each capability can be enabled or disabled from Settings, grouped by category (Search, File Operations, Media, Time, Memory, System, MCP, Agent).
- Autonomous mode: The model can decide to call a tool on its own, or only when the user explicitly requests it via
@-command aliases. - Alias-aware: Capabilities expose
@-command aliases (e.g.,@vault,@websearch,@composer,@memory) so users can invoke tools explicitly. - Execution modes:
always(always included in context),autonomous(model may decide),explicit(only on user request). - Confirmation policies:
never,on-threshold, oralwaysfor destructive operations. - Event-driven UI: The registry emits events when capabilities are registered, enabled, or disabled — the Settings UI and dashboard widgets react in real time.
- System prompt injection:
describeEnabled()produces a compact inventory of available capabilities for the model's context window.
Projects are focused AI workspaces with isolated chat history, per-project model configuration, and scoped context sources:
- Vault-native storage: Each project is a
.mdfile under.command-center/projects/with YAML frontmatter — no hidden databases or external services. - Per-project model: Override the global provider/model for a specific project.
- Custom system prompt: Assign a system prompt to shape the agent's behavior for that project.
- File scoping: Inclusion and exclusion patterns control which notes are visible to the project's agent.
- Web and YouTube context: Pre-load web page URLs and YouTube video transcripts as always-available context.
- Isolated chat history: Conversations in one project never bleed into another.
- Archiving: Archive projects to hide them from the active list while preserving data.
- Usage tracking: Automatic last-used timestamps and conversation counts for sorting.
The composer provides a three-stage fuzzy matching engine for precise text replacement:
- Exact match — after line-ending normalization (CRLF → LF)
- Fuzzy match — NFKC normalization, smart quotes, special dashes, non-breaking spaces
- Trimmed match — retry after stripping trailing newlines
Additional capabilities:
- BOM handling: UTF-8 BOM is preserved through edit cycles.
- LCS-based diff: Longest-common-subsequence diff computation with line-level granularity.
- Multi-operation editing:
applyOperations()applies a sequence of insert, update, replace, and delete operations in order. - Diff statistics: Additions, deletions, and unchanged line counts for progress reporting.
The typeahead engine provides real-time suggestions as you type @ in the editor:
- Multi-source: Searches notes, folders, tags, and capabilities simultaneously.
- Categorized results: Results grouped by source type with clear labels and descriptions.
- Keyboard navigation: Arrow keys, Enter/Tab to select, Escape to dismiss.
- Vault caching: 30-second TTL cache prevents repeated vault scans.
- Capability aliases:
@vault,@websearch,@composer,@memoryresolve to their corresponding capabilities. - Wikilink insertion: Selected notes are inserted as
[[wikilink]]references.
System prompts are stored as vault-native Markdown files with YAML frontmatter:
- CRUD management: Create, edit, delete, and browse prompts from the vault.
- Variable substitution:
{{vault}},{{date}},{{time}},{{user}},{{style}},{{memory}}are resolved at render time. - Custom resolvers: Override variable resolution per-project or per-chat-mode.
- Default prompt: A sensible default prompt is created on first launch.
- Category filtering: Organize prompts by category for quick access.
Builds on the persistent agent memory store to provide user-facing memory operations:
- Explicit memory:
remember()processes natural-language "remember that" commands. - Auto-extraction:
extractFromTurn()detects "I prefer", "I am", "remember that" patterns in conversation turns. - Profile building:
buildProfile()aggregates stored facts into a structuredUserMemoryProfilewith name, style, expertise, and goals. - Contextual recall:
recall()searches memories by relevance to a query and returns formatted Markdown. - System prompt injection:
injectMemoryPrompt()produces a bounded memory context block for the model.
Obsidian desktop
├── Command Center dashboard
│ ├── task queue, status, history, and frame-batched streaming
│ └── fixed-pool ReAct monitor, replay, export, and debug stepping
├── Right-sidebar chat
│ ├── Quick → ConversationManager → ProviderDispatcher
│ ├── ReAct → PiAgentDaemon → Orchestrator/Workers/Tools
│ └── Workflow → WorkflowEngine → provider or Pi routes
├── Interview-derived operations
│ ├── ConfigManager + generated style guide
│ ├── FolderIndexer → protected _index.md manifests
│ └── DailyEngine + InboxTriager + CapacityEngine
├── Metacognition and knowledge layer
│ ├── TopographySweep + dashboard LogicDiscovery → localized topology/profile JSON
│ ├── ChunkingEngine → H2/H3 chunks + tags/aliases/wikilinks
│ ├── DialecticRAG → normalized embedding ingestion → memory / injected SQLite-VSS
│ ├── HybridRetriever → BM25 + embeddings + weighted RRF
│ └── AgentMemoryStore/ReActMemoryBank → bounded persistent memory
├── Workflow layer
│ ├── Markdown/Canvas parser → validated DAG tiers
│ ├── Bases queue → bounded target batches
│ └── frontmatter state sync → live Bases refresh
├── Execution layer
│ ├── NativeAutoRouter → model_matrix.json + global depth 1–10
│ ├── ExecutionRouter → explicit worker modalities + secure credentials
│ ├── PythonWorkerTransport → bounded JSON-RPC subprocesses
│ └── DataNormalizer → sanitized results, observations, and merges
└── Provider layer
├── ModelRouter/ProviderDispatcher → capability, fallback, isolated circuits
├── cloud adapters → OpenAI, Anthropic, Gemini, etc.
└── local adapters → Pi, Ollama, LM Studio, custom endpoint
- Obsidian-native I/O: vault files are read and changed through Obsidian APIs wherever possible.
- Shared write coordination: UI, CLI, daily services, indexers, workflows, and tools use one normalized per-vault lock namespace.
- Serialized Pi transport: Pi events do not identify an originating prompt, so one active RPC prompt is correlated through
agent_endandagent_settled. - Raw-byte framing: JSONL is split on byte
0x0Abefore UTF-8 decoding, preserving split code points, CRLF, U+2028/U+2029, bursts, and final unterminated frames. - Bounded UI work: model deltas and trace events are coalesced with
requestAnimationFrame; trace history and visible rows are capped.
- Obsidian 1.13.0 or newer
- Desktop Obsidian (the plugin is desktop-only)
- A provider configured in Command Center settings
- Optional: Node.js 20+ and Pi 0.83.0+ for local Pi/ReAct execution
-
Download the release assets or the packaged
command-centerdirectory. -
Create this folder inside your vault:
<your-vault>/.obsidian/plugins/command-center/ -
Copy the plugin assets from
release/command-center/:command-center/ ├── main.js ├── manifest.json └── styles.cssRepository-level
LICENSEandATTRIBUTIONS.mdremain published alongside the source and GitHub release documentation. -
Restart Obsidian or reload community plugins.
-
Open Settings → Community plugins and enable Command Center.
-
Run Command Center: Start Setup / Onboarding Interview from the command palette.
Pi powers local palette tasks and the full multi-agent ReAct path. Install it separately:
npm install -g @earendil-works/pi-coding-agent
pi --versionCommand Center auto-detects common global npm locations. On Windows it resolves pi.cmd to Pi's JavaScript CLI and launches it with the real Node executable to avoid Electron/Node wrapper issues. You can override the detected path in Settings → Command Center → Core Configuration.
Pi is an external MIT-licensed companion and is not bundled into this plugin.
Launch onboarding in the full-page dashboard from either the Command Center ribbon action or Command Center: Start Setup / Onboarding Interview. Discovery, confirmation, and synthesis stay in the central workspace instead of opening a separate setup modal.
The six configuration phases are:
- Topology — inboxes, daily notes, managed folders, and vault structure
- Life map — domains, projects, time horizons, and completion definitions
- Capacity — tracked metrics and rules that scale daily commitments
- Triage — move, archive, extraction, deletion, and aging policies
- Focus — priority caps, frog rules, quick wins, and task conventions
- Style — writing voice, agent persona, vocabulary, layouts, and reflections
A confirmation/synthesis stage then previews 2–4 templates and 2–3 workflows. Nothing is generated until you explicitly select and approve it.
The interview writes validated assets under .command-center/, including:
.command-center/
├── config.json
├── style-guide.md
├── templates/
└── workflows/
These are local runtime files and must not be published with the plugin. The repository includes a non-secret reference at docs/config.example.json.
Do not enter API keys, passwords, tokens, URLs, hosts, ports, or endpoint details into the interview. Secret-like input is rejected locally. Configure provider credentials and endpoints only in Settings → Command Center.
To start over, run Command Center: Reset / Re-Initialize Vault Configuration. Generated configuration and style files are moved through Obsidian's trash flow before onboarding restarts.
Open Settings → Command Center. The settings UI is organized into six sections.
Configure the active profile, token limits, Pi path, daemon startup, memory limits, Base batch concurrency, and Silent Daily Startup. Pi detection and status diagnostics are available here.
Configure text-to-speech enablement, speaking voice, speaking rate, speech-to-text enablement, transcription provider preferences, and automatic read-aloud behavior here. Chat and voice recording use the same speech settings.
Speech-to-text models are per-provider (STT model IDs are not portable across providers — openai/gpt-4o-mini-transcribe is an OpenRouter routing slug, grok-stt is xAI, whisper-1 is OpenAI). Set the slug each provider accepts in the per-provider model fields; a blank entry uses the provider's built-in default.
Text-to-speech can use the browser's built-in speech engine (default) or route through a provider's /audio/speech (or xAI /v1/tts) endpoint for higher-quality voices. Pick the engine in Text-to-speech engine; set a per-provider TTS model and voice id when using a provider engine.
Each provider has a collapsible card for enablement, endpoint configuration, health checks, and model refresh. API keys are not exposed through ordinary settings fields.
Select Manage API Keys to open the built-in secrets editor. Provider secrets are stored in Obsidian Secret Storage under the Command Center namespace, so they persist with your vault instead of a custom encrypted file. Existing secrets can be replaced or removed, but they are not revealed back into the UI.
Authentication metadata distinguishes required, optional, and unsupported credentials. LM Studio's Require Authentication token, authenticated Ollama proxies, and custom OpenAI-compatible bearer tokens all use Obsidian Secret Storage for persistence without making a key mandatory for ordinary local operation. Tokens are applied consistently to inference, streaming, model discovery, health checks, transcription, and local model lifecycle requests.
Credentials are resolved only at request time. Provider secrets stay in Obsidian's secret store, while interviews, generated workflows, CLI/URI arguments, subprocess argv/environment, logs, and repository examples continue to exclude credentials.
Assign a provider/model pair to each task class:
| Task class | Typical use |
|---|---|
coding |
Code generation, refactoring, technical edits |
vision |
Image and Canvas attachment analysis |
reading |
Long documents, synthesis, extraction |
reasoning |
Planning, analysis, orchestration |
fast |
Classification and low-latency transforms |
Live-discovered models appear with a network indicator. If discovery fails, the static registry remains available.
Enable or disable fallback, then add, remove, and reorder providers. Permanent request/schema errors fail fast; transient failures use backoff and reliability-ranked alternatives without allowing cost optimization to weaken recovery.
Review provider state, test one provider, refresh all providers, and inspect actionable errors such as a missing Pi binary or unreachable local endpoint.
Open Command Center from the ribbon or command palette. Every panel carries a one-line description of what it shows and what to do with it, so nothing needs to be guessed.
Happening now — four zero-token intelligence cards
Computed from Obsidian's metadata cache only; no model calls, no token spend.
| Card | What it shows | What to do |
|---|---|---|
| Daily intelligence | Today's note, its sections, tracked metrics, and any capacity rule that tripped | Click to open today's note |
| Capture | Notes you dropped in but have not filed | Open one to process it, or ask for triage |
| Action items | Open tasks vault-wide, in Kanban-style lanes (Overdue / Due today / Scheduled / Undated) | Click a row to jump to that exact line |
| Workspaces | Managed folders with live note counts, freshness, and index state, plus nested .base views |
Click to open a folder index or Bases view |
Calendar — a month grid marking which days have notes and how much work is scheduled. Click a date to open or create its daily note, tick tasks complete, reschedule them, delete them, or add new dated tasks. Every write is a proposal that passes the write gate first.
Vault doorway — one filter box across note titles, folders, tags, canvases, and .base views, ranked by prefix, word-boundary, then substring match. Press Enter to open the top hit. Left empty it lists your most recently edited notes. Folders reveal in the native file explorer; tags hand off to Obsidian's own global search.
Command deck — a vertical rail built from your vault's workflow files (.md, .canvas, and generated .json). Labels, descriptions, and icons come from native frontmatter, and new workflows hot-register without an Obsidian restart.
Browser — a real embedded web view for documentation, API references, and research. Use it inline, expand it to fill the dashboard for close reading, or pop it out into its own pane. Bare hosts and localhost:3000 resolve as addresses, free text becomes a search, and non-web schemes (javascript:, data:, file:) are refused. Hidden by default — enable it in Customize dashboard.
When Obsidian's core Web viewer is enabled, the panel offers to hand the current address to it, so browsing uses the history, favicons, ad blocking, and search engine you already configured in Obsidian rather than a parallel set of the plugin's own. Detection is guarded and falls back to the plugin's own view if the core viewer is off or refuses (src/ui/native-webviewer.ts).
On desktop this uses Electron's <webview>, the same mechanism as Obsidian's own Web viewer, so it browses the open web normally — including sites such as GitHub, MDN, Google, and Stack Overflow that send X-Frame-Options and would refuse to load in a plain iframe. Browsing state lives in its own isolated partition, separate from Obsidian's session. An Open externally button hands the current page to your system browser, which is the better route for logins, downloads, and anything needing a password manager.
The widget and the full-pane view are the same component, so behavior and fixes never diverge between them. Open browser reuses an existing browser leaf rather than opening a new split each time.
Note
Where <webview> is unavailable, the panel degrades to a sandboxed iframe and says so in the panel. In that limited mode only sites that permit framing will load; most major sites will not. Command Center is desktop-only, so this is an edge case rather than the normal path.
Important
This is a convenience reader, not a replacement for your browser. Sign-in flows are the weak spot: Google's login pages actively resist embedded browsers, and password managers and passkeys will not be available. Use Open externally for anything involving credentials — which is also the safer habit.
Any note in your vault becomes a dashboard card by adding cc-card: true to its frontmatter. There is no registry and no settings form: create the note and the card appears, delete it and the card is gone. Cards are reorderable alongside built-in widgets.
---
cc-card: true
cc-card-title: Morning review
cc-card-hint: What I committed to today
cc-card-icon: sunrise
cc-card-order: 1
---
## Focus
- [ ] Draft the quarterly summary
- [ ] Reply to the vendor thread
![[Active projects.base]]| Key | Purpose |
|---|---|
cc-card |
Required. true marks the note as a dashboard card. |
cc-card-title |
Display name; falls back to name, title, then the filename. |
cc-card-hint |
One-line description shown under the title. |
cc-card-icon |
Obsidian icon id. |
cc-card-order |
Sort order relative to other cards. |
Card bodies render through Obsidian's own Markdown renderer, so embedded .base views, Dataview blocks, callouts, images, and transclusions all work. Checkbox lines become interactive rows: ticking one writes back to the source note through the write gate, and the arrow button jumps to that exact line. Checkboxes inside fenced code blocks stay as code samples rather than becoming buttons.
Also on the dashboard
- Embedded Socratic discovery and onboarding, entirely optional
- Mutation approvals with target paths, diffs, live gate posture, and an append-only decision log
- Orchestrator chat with capability-aware tool calling
- Daemon Start / Stop / Restart controls
- Pending, running, completed, and failed queue counts
- Provider-normalized orchestrator output and per-task live output
- Task history, ReAct filters, debug stepping, and session export
- Daily-cycle controls and consolidated silent-start summaries
- Obsidian's built-in browser, opened in a split pane for documentation and research
- Per-vault widget ordering, sizing, collapse/visibility controls, and responsive layout persistence
- Review-before-send dictation plus opt-in audio cues, speech-to-text, and AI read-aloud
Run Command Center: Open Chat Panel and choose:
- Quick for provider-routed conversational work
- ReAct for orchestrated multi-agent execution
- Workflow to run a Markdown, Canvas, or Base-backed workflow
Use @Note Name, @folder/note.md, an active editor selection, or a .base reference to attach vault context. Suggested recent/active notes appear as dismissible pills; only retained pills are sent.
Open a Markdown note and run Execute agent task on current note. This command explicitly routes through the local Pi daemon and starts it automatically when possible.
The write gate is the boundary between the model and your vault. It is not advisory: every capability handed to an agent is wrapped so the gate runs inside the tool's execution path. A missed check at a call site cannot bypass it.
Capability wants to write
→ gate describes the change as a proposal
→ proposal appears in Mutation approvals
→ you click Approve
→ only then does the write occur
Defaults and controls
| Setting | Default | Effect |
|---|---|---|
| Auto write (global bypass) | Off | Off: every mutation waits for your click. On: approved capabilities write immediately. |
| Protected paths | Empty | Vault-relative folders that always require an explicit click, even when Auto write is on. |
Protected-path matching is prefix-exact, so Vault/Private never accidentally captures Vault/PrivateNotes. Paths are yours to define; the plugin assumes no folder names.
Guarantees
- Read-only capabilities never prompt.
- A capability reporting no mutation for its arguments never prompts.
- Rejection, timeout, and failure all leave files untouched.
- Dashboard task edits abort if the underlying line changed while awaiting approval.
- Writes use
Vault.process, so they are atomic and compatible with native File Recovery. - Every decision — approved, rejected, timed out, or auto-approved — is recorded in the on-dashboard log.
- Success is reported only after the write actually completes.
A workflow defines typed inputs and steps. Every synthesized step declares an assigned agent, required compute tier, fallback policy, and action type. Dependencies form a DAG; unknown dependencies and cycles are rejected before execution.
Conceptual example:
---
workflow:
name: Review incoming note
inputs:
tone:
type: dropdown
options: [concise, detailed]
steps:
- id: inspect
assigned_agent: researcher
required_tier: tier1_local
fallback_policy: configured
action_type: read
prompt: "Inspect {{inputs.targetPath}} using a {{inputs.tone}} style."
- id: summarize
dependsOn: [inspect]
assigned_agent: writer
required_tier: tier2_reasoning
fallback_policy: configured
action_type: write
prompt: "Summarize: {{steps.inspect.result}}"
---The exact accepted shape is validated by the native parser and may include input defaults, conditions, provider/Pi routing, and output metadata.
Open a Markdown workflow and run Export Active Workflow to Canvas. Parallel steps share a tier column, dependencies become directed edges, and executable step metadata is retained in text nodes.
A standalone .base file can reference a workflow. Open it and run Execute Workflow on Current Base Queue. Choose concurrency from 1–10 and an optional partial-run limit. Command Center:
- Resolves Obsidian's evaluated Base entries
- Excludes completed/failed notes
- Runs bounded independent target contexts
- Awaits frontmatter updates between tiers
- Refreshes and re-queries membership before continuing
This allows a Base to function as a live, self-draining agent queue.
The chat microphone and Command Center: Quick Voice Prompt use browser-native MediaRecorder:
- In-memory audio assembly
- Live timer and level meter (chat, voice prompt modal, and dashboard dictate button)
- Deterministic microphone-track cleanup
- OpenAI-compatible multipart transcription (per-provider model resolution — see below)
- Retry only for transient network/408/429/5xx failures
- Mic button disabled when no STT provider is configured, with tooltip feedback
- Spoken
@mentions and active-selection context resolution - Contextual delivery — the Quick Voice Prompt routes transcribed text by focus: into the active note at the cursor when a note is in focus, or into the chat input field (for review before send) when the chat panel is in focus or no note editor is active
The transcription fallback chain tries each enabled STT-capable provider in order (LM Studio, Ollama, Groq, OpenAI, DeepInfra, Mistral, OpenRouter, xAI, Cohere, Custom). Each provider uses its own model slug — set per-provider in Settings → Accessibility & Speech, or leave blank for the built-in default (whisper-1 for OpenAI, grok-stt for xAI, whisper-large-v3 for Groq, openai/whisper-large-v3-turbo for DeepInfra, voxtral-mini-latest for Mistral, openai/whisper-large-v3 for OpenRouter, cohere-transcribe-03-2026 for Cohere). A global model is no longer broadcast to every provider, so a foreign slug can no longer break a provider it wasn't meant for.
Audio is sent only to the transcription endpoint configured in your local settings. Review that provider's privacy policy before use.
Spoken output defaults to the browser's built-in speechSynthesis engine. When Text-to-speech engine is set to a provider (or Auto), Command Center routes the text through that provider's TTS endpoint instead:
- xAI:
POST /v1/tts(native, modelgrok-tts) - OpenAI:
POST /v1/audio/speech(modelgpt-4o-mini-tts) - OpenRouter:
POST /api/v1/audio/speech(routed slugs likeopenai/tts-1) - Mistral:
POST /v1/audio/speech(Voxtral TTS)
The returned audio plays through a hidden <audio> element. If the provider request fails, Command Center falls back to the browser engine so spoken output is never silently dropped. Set a per-provider TTS model and voice id (e.g. alloy, nova, coral) in Settings → Accessibility & Speech.
On Obsidian versions exposing native CLI registration:
command-center:morning
command-center:workflow
command-center:indexes
These handlers invoke service layers directly without opening views. They return structured JSON and use non-zero failure semantics. Morning automation assembles the configured note but never auto-approves inbox mutations.
Example shape:
obsidian command-center:morning --metrics '{"available_minutes":120}'
obsidian command-center:workflow --path '.command-center/workflows/example.md' --inputs '{}'
obsidian command-center:indexesConsult your installed Obsidian CLI's command syntax because host invocation details may vary by version.
For hosts without native CLI registration:
obsidian://command-center?operation=morning
obsidian://command-center?operation=indexes
The URI and CLI boundaries reject credential arguments, unsafe vault paths, malformed/oversized JSON, and execution before onboarding is complete.
Command Center is local software, but it uses the network when you select a cloud model or transcription provider, refresh a remote model catalog, or connect to a network-hosted custom endpoint. Supported remote services include OpenAI, Anthropic, Google Gemini, OpenRouter, Groq, DeepInfra, Mistral AI, and Cohere; requests are used only to provide the model, embedding, discovery, or transcription feature you invoke.
The desktop-only plugin also accesses files outside the vault in two explicit cases: it launches the separately installed Pi CLI as a child process, and it may read image attachments referenced by absolute paths so they can be sent to your selected vision provider. Ordinary note, configuration, memory, workflow, and index operations use Obsidian's vault APIs.
No client-side telemetry or advertising is included. Command Center does not self-update; installation and updates are handled by Obsidian and GitHub releases.
Depending on the mode and context you approve:
- Your prompt and bounded conversation history
- Selected note text or resolved
@attachments - Retrieved and cited vault snippets
- Relevant persistent memory entries
- Images explicitly referenced by the prompt
- Workflow inputs and prior step results
Use local Pi/Ollama/LM Studio/custom endpoints when content must remain on your network, and verify those services independently.
- Secrets are entered through Obsidian's built-in Secret Storage UI from the Command Center settings tab.
- Provider secrets persist in Obsidian Secret Storage under the
command-centernamespace. - Existing secrets are managed in place: replace them, remove them, or leave them unchanged.
- Interview, config generation, CLI/URI arguments, subprocess argv/environment, and examples prohibit credentials.
- Tool paths reject traversal, absolute paths, NUL bytes, and unsafe characters.
- Existing-note overwrites and bulk/destructive operations can require explicit approval.
- Shared FIFO locks coordinate all mutation paths.
- Prompt context, memory, traces, histories, Python subprocess output, and UI rows are bounded.
- All Python JSON-RPC responses, stderr, tracebacks, malformed output, and multi-agent merges pass through
DataNormalizer. .gitignoreexcludes runtime config, memory, audit traces, topology, generated assets, logs, environment files, and release/build outputs.scripts/sanitize-repo.mjsscans repository and release content for common secrets, private keys, absolute local paths, private IPs, NULs, and tracked runtime state.
Run before committing or publishing:
npm run sanitize # tracked + untracked public files
npm run sanitize:staged # staged Git blobs; suitable for pre-commit
npm run sanitize:release # repository plus current build/release assetsnpm run package automatically performs the release scan after packaging. CI and release workflows also run the sanitizer.
This repository follows the official Obsidian plugin documentation for lifecycle, workspace, settings, commands, modals, events, vault access, and submission requirements. When changing code, prefer Obsidian-native APIs over custom replacements, clean up event handlers on unload, and keep desktop-only code paths explicit where the plugin depends on them.
- Node.js 20, 22, or 24
- npm
- A desktop Obsidian vault for manual integration testing
git clone https://github.com/scrunchds/Command-Center.git
cd command-center
npm ci
npm run devnpm run dev starts esbuild watch mode. Reload Obsidian after bundle changes.
| Command | Purpose |
|---|---|
npm run typecheck |
Strict TypeScript check (including security, metacognition, execution, and diagnostic layers) |
npm run lint |
Zero-warning ESLint gate |
npm run test |
167 core + 153 ReAct + 22 provider = 342 total |
npm run benchmark |
Produce the standardized 10-metric report |
npm run benchmark:check |
Enforce the 25% core regression threshold |
npm run sanitize |
Scan public repository files for PII/secrets/runtime data |
npm run sanitize:staged |
Scan staged blobs for pre-commit use |
npm run build |
Typecheck and build minified production JS/CSS |
npm run package |
Build, create a clean release folder, and sanitize it |
npx obsidian-plugin-validator . |
Run community-submission manifest and source checks |
npm run package recreates release/command-center/ from scratch and permits exactly:
main.js
manifest.json
styles.css
License and attribution documents remain at repository level. Restricting the installable directory to Obsidian's three production files prevents stale development or documentation files from leaking into the plugin package.
- The chat view now supports switching between conversations via a dropdown selector.
- A future change could add the ability to delete or rename conversations from the selector.
- The chat view now shows a notice when images are pasted. A future change could save pasted images to the vault and attach them as multimodal context.
- The dashboard layout is directly manipulable: drag a panel by its grip to move it, drag its right edge to set width on a twelve-column grid, and drag its bottom edge to set height. Double-click either grip to restore that panel's default. Every panel also supports reorder, show/hide, collapse/expand, and size via the "Customize dashboard" button, and grips respond to arrow keys so arranging never requires a pointer (
src/ui/layout-model.ts,ensureWidgetChrome()). - A future enhancement could add a dashboard layout phase to the onboarding interview (e.g. extending the "style" phase, or adding a new phase after "confirmation").
- This would require:
- Adding
dashboardLayoutto theOnboardingConfigtype insrc/onboarding/OnboardingTypes.ts - Updating the interview system prompt in
src/onboarding/InterviewEngine.tsto ask about widget preferences - Applying the interview-derived layout after interview completion in
src/main.ts
- Adding
The OnboardingConfig already has a style.dailyNoteLayout field, so a style.dashboardLayout field would follow the same pattern.
- The dashboard now shows provider icons with green/red readiness dots. A future change could show live health check status (connected/error) next to each icon.
- The voice prompt modal now shows a warning when no transcription providers are configured. A future change could disable the mic button entirely, matching the chat view behavior.
The test suite currently contains 342 tests:
- 167 core tests — build integrity, parsers, byte-safe RPC framing, subprocess integration, task queue, recovery, provider fallback, capability registry, user memory, system prompts, project manager, composer fuzzy matching, @-mention engine, fallback pipeline, and STT/TTS adapters
- 153 ReAct and subsystem tests — roles, evaluation, traces, workflows, Bases, chat context, action cards, audio, JIT lifecycle, RAG, memory, CLI, locks, and stress scenarios
- 22 provider tests — XAI provider, OpenRouter model metadata, transcription candidates, and model matrix integration
CI runs on Windows, macOS, and Linux across Node 20, 22, and 24 with:
- Repository sanitization
- Typecheck
- Zero-warning lint
- Full tests
- Standardized benchmarks
- 25% performance-regression gate
- Production package validation
- Clean release-surface verification
Release automation repeats the validation, builds a clean three-file plugin package, attests artifact provenance with Sigstore attestations, verifies each published asset cryptographically, and creates a GitHub release. The package metadata and manifest version are currently 1.8.0, with Obsidian 1.13.0 as the minimum supported app version.
The local community-plugin validator currently passes with 0 errors.
Run:
pi --version
npm install -g @earendil-works/pi-coding-agentThen use Settings → Command Center → Core → Pi harness path and click 🔍 Detect (or type a custom path). Detection is non-blocking; the button shows ⏳ Detecting… while it runs and reports
- Confirm Ollama or LM Studio is running.
- Verify the base URL in the provider card.
- Click Refresh Models, then run the provider health check.
- Ensure the selected route references a model reported by the local server.
Run Command Center: Start Setup / Onboarding Interview and complete confirmation/synthesis. Both .command-center/config.json and .command-center/style-guide.md must validate before operational services start.
Check that:
- The active file is Markdown or Canvas and contains workflow metadata.
- Step IDs are unique.
- Every dependency exists and the graph is acyclic.
- Required inputs are supplied.
- Provider/Pi routes are enabled and healthy.
- A Base file references a valid workflow path.
Open the Command Center dashboard, inspect the Mutation approvals card's target list and diff preview, then choose Approve & apply or Reject. Closing the dashboard rejects pending confirmations safely.
STT model IDs are per-provider. The error The model 'openai/gpt-4o-mini-transcribe' does not exist means a slug meant for one provider (here, OpenRouter routing) was sent to another (e.g. xAI). Fix it in Settings → Accessibility & Speech → Per-provider speech-to-text models: set the slug each provider actually accepts, or leave the field blank to use that provider's built-in default (grok-stt for xAI, whisper-1 for OpenAI, etc.). The global Speech-to-text model field is no longer broadcast to every provider — it only applies to providers that have no built-in default.
The provider processed the audio successfully but returned an empty transcript (near-silent input, background noise, or a Whisper silence-hallucination artifact that was stripped). Speak closer to the microphone, or switch the Speech-to-text provider to one with a higher-quality STT model. Recording shorter than 500 ms is treated as an accidental mic tap and never sent.
The following features have infrastructure stubs and are ready for implementation when needed:
Command Center includes static URL builders for OpenRouter's video generation API:
POST /api/v1/videos— submit a video generation requestGET /api/v1/videos/{id}— poll generation statusGET /api/v1/videos/{id}/download— download generated video- Models are discovered dynamically through
/api/v1/models/userwhen they become available - Vault media ingestion stubs (video MIME types,
isVideoFile()) are ready inimage-utils.ts
Image generation models are registered in the OpenRouter provider (openai/gpt-5-image, google/gemini-3.1-flash-image, etc.) and the getImageGenerationUrl() helper returns POST /api/v1/images/generations.
xAI's realtime API (GET /v1/realtime WebSocket) supports voice-in/voice-out and function calling. The XAIProvider class (src/providers/xai.ts) implements chat completions plus native STT (POST /v1/stt) and TTS (POST /v1/tts, GET /v1/tts/voices). TTS is now wired into the spoken-output pipeline via TtsAdapter (see Text-to-speech above); the WebSocket realtime transport remains a future addition.
The newer POST /api/v1/responses format is a future migration target alongside the existing chat completions endpoint. Adopting it would enable streaming reasoning tokens, server-side tools (web search, code interpreter, MCP), and compaction; no Responses endpoint is wired up today.
- Read CONTRIBUTING.md before proposing changes or opening a pull request.
- Follow the Code of Conduct in all project spaces.
- Use GitHub Discussions for questions and community support; see SUPPORT.md.
- Report vulnerabilities privately according to SECURITY.md—never in a public issue.
Command Center is free and MIT-licensed. If it improves your workflow and you would like to thank the developer, you can make an optional donation:
The same link is available as a branded Buy Me a Coffee button in the support card at the bottom of Settings → Command Center. Donations are optional, do not unlock features, and are not required for support or updates.
Command Center is released under the MIT License.
Third-party projects remain under their respective licenses. See ATTRIBUTIONS.md for the audited dependency inventory and distribution boundaries, including:
- Obsidian API — MIT; host API/types, not bundled as Obsidian itself
- esbuild — MIT; build tooling
- Pi coding agent — MIT; optional external RPC companion
- TypeScript, ESLint, CodeMirror/Lezer, Node.js, Electron, and other development/host components
The lockfile audit found no GPL-family, SSPL, BUSL, or undeclared package licenses. Repository sanitization, credential-boundary checks, clean-room packaging, and provenance attestation are part of the publication workflow.
“Obsidian” is a trademark of Dynalist Inc. Command Center is an independent community plugin and is not endorsed by Dynalist Inc. or the Pi maintainers.