OpenAgent Project Map
This is the fastest way to understand what this repository is, which folders matter, and how the pieces fit together in day-to-day work.
Read this before diving into source if you are new to the repo.
One-Sentence Summary
OpenAgent turns an Obsidian Canvas selection into a local Codex task, streams the run through a local daemon, and writes the answer back into the canvas as graph content.
What We Are Building Here
The primary product in this repo is a local-first workflow for repo work:
- Obsidian Canvas is the planning and context surface.
- OpenAgent reads selected nodes from that canvas.
- A local daemon turns that selection into a durable task and runs Codex Desktop against a real repo on disk.
- The plugin keeps task state visible in Obsidian and syncs the final assistant output back into the graph.
This repo is optimized for:
- macOS
- Obsidian Desktop
- Codex Desktop
- local repo workflows where the canvas is the main working surface
The Real Product Surface
The product is mostly implemented in three places:
apps/obsidian-plugin
The Obsidian plugin.
It is responsible for:
- reading the active canvas and selected nodes
- resolving text nodes and markdown file nodes into prompt context
- letting the user choose a repo workspace inside the vault
- launching or reconnecting to the local daemon
- rendering the OpenAgent side panel
- syncing running/completed node colors
- writing assistant result nodes and edges back into
.canvasfiles
Important note: the current plugin implementation is still concentrated in one large file, apps/obsidian-plugin/main.js.
apps/openagent-daemon
The local HTTP daemon.
It is responsible for:
- creating and reusing tasks from canvas selections
- persisting task state in
~/.openagent/daemon-state.json - validating that Codex Desktop is available
- starting or resuming Codex threads
- sending turns to the Codex runtime
- collecting runtime notifications into task messages
- exposing task routes and server-sent event streams to the plugin
Main entry point: apps/openagent-daemon/src/server.js
packages/core
Shared domain helpers used by both the plugin and daemon.
It holds the common rules for:
- normalizing canvas selections
- building prompts from selected canvas context
- generating stable task ids and selection keys
- normalizing
canvasBinding - creating the canonical persisted task shape
Main entry point: packages/core/src/index.js
How The Main Flow Works
The normal product flow is:
- A workspace in the Obsidian vault points to a real repo on disk.
- The user opens a canvas in that workspace.
- The user selects one or more nodes.
- The plugin resolves those nodes into a normalized
selectionContext. - The plugin asks the daemon to create or reuse a task for that selection and repo.
- The daemon starts or resumes a Codex thread.
- Runtime notifications become task messages.
- The plugin updates its panel UI and writes the latest assistant answer back into the canvas as a result node.
For follow-ups, the plugin can treat a new text node connected to an older result node as a continuation of the same task/thread, while moving the active canvas source node forward.
The repo binding comes from the workspace folder, not from a .canvas file alone. In practice, any canvas under the same workspace folder resolves to the same repo because the plugin maps the canvas path back to that workspace's workspace.json.
Repository Map
These are the tracked folders that matter most:
apps/obsidian-pluginProduction Obsidian plugin source and assets.apps/openagent-daemonProduction local daemon source.packages/coreShared task/canvas helpers used by both sides.scriptsSetup, linking, sync, CLI, and smoke-test automation.fixtures/obsidian-smokeChecked-in fixture vault content used by headless and plugin smoke tests.skills/openagent-canvas-bootstrapCodex bootstrap skill for wiring a repo into OpenAgent quickly.docsUser, architecture, dev, and maintenance documentation..github/workflowsCI that currently runs repo checks.
Important tracked single files:
README.md: product-level entry pointdocs/getting-started/user-guide.md: user workflow inside Obsidiandocs/engineering/architecture.md: plugin/daemon/core architecturedocs/notes/safe-skill-sandbox-mvp.md: cloud-first product spec for safely testing third-party AI skillsdocs/engineering/plugin-development.md: local plugin development workflowdocs/engineering/plugin-release.md: plugin packaging and GitHub release workflowpackage.json: workspace scripts and top-level commands
What Is Source Code vs. Local Working State
This repo can look bigger than it really is because it is often used inside a live Obsidian/Codex working environment.
Source of truth in git:
apps/packages/scripts/fixtures/docs/skills/
Local or generated state that should not be mistaken for product source:
node_modules/.openagent/in the user home directory- vault runtime files under
.obsidian/except the tracked.hotreloadmarker - workspace output under
Workspaces/ - smoke output under
OpenAgent Smoke/
The top-level repo may also contain personal vault folders or working directories on one machine. Those are environment artifacts unless they are actually tracked by git.
Scripts And What They Are For
Top-level scripts defined in package.json:
pnpm run checkRuns syntax plus hygiene checks.pnpm run check:syntaxParses all.jsand.mjsfiles with Node's syntax checker.pnpm run check:hygieneBlocks common secrets and machine-specific path leaks from being committed.pnpm run dev:daemonStarts the local daemon.pnpm run link:obsidian-pluginSymlinks plugin files from the repo into the current Obsidian vault.pnpm run sync:obsidian-pluginCopies plugin files into the vault instead of symlinking.pnpm run test:obsidian-smokeGeneral plugin smoke path.pnpm run test:obsidian-markdown-new-threadVerifies markdown-file-only new-thread behavior.pnpm run test:obsidian-follow-up-chainVerifies task/thread reuse and follow-up result sync.pnpm run test:obsidian-node-colorsVerifies running/completed canvas color behavior.pnpm run test:obsidian-ui-smokeExercises the command-palette/UI path.
There is also a small CLI at scripts/openagent-cli.mjs that helps with setup and repo bootstrap.
Key Contracts Worth Knowing
These rules show up across the codebase and explain a lot of the implementation choices:
Task identity is selection-based
The daemon builds a stable task identity from:
canvasPath- sorted selected
nodeIds - repo working directory
That means the same selection in the same repo can reuse the same task unless the caller forces a fresh task.
The daemon owns canonical task state
The daemon is the source of truth for:
- task status
- thread id
- turn id
- task messages
- runtime config
- canonical
canvasBinding
Plugin state in data.json is a local UI cache, not the canonical binding owner.
canvasBinding is the glue between task state and graph state
The current binding keeps track of:
- which canvas the task belongs to
- which original nodes define the root of the conversation
- which node is the active follow-up source
- which result node belongs to which source node
That is what makes follow-up chains and safe result sync possible.
Result sync is timestamp-aware
The plugin checks activeSourceUpdatedAt so an older assistant message does not get written onto a newer follow-up source node.
The repo is local-first
The main workflow assumes local apps, local files, and a local daemon. This is not a hosted SaaS architecture.
Current Shape Of The Code
Today the codebase is functional and reasonably understandable, but still early in a few ways:
- the plugin is feature-rich but still centralized in one large
main.js - the daemon is small and direct, with task state persisted to local JSON
- the shared core package is intentionally thin and focused on normalization and identity
- CI currently verifies repository checks, not the full Obsidian integration stack
There is also one small legacy-looking signal in the repo: the root package.json description still mentions XMTP, and the daemon still exposes an XMTP channel bind route. That is not the main documented product flow today.
Recommended Reading Order
If you want to understand the repo quickly, use this order:
README.md- this document
docs/getting-started/user-guide.mddocs/engineering/architecture.mddocs/engineering/plugin-development.mdapps/obsidian-plugin/main.jsapps/openagent-daemon/src/server.jspackages/core/src/index.js
If You Need To Change Something
A practical rule of thumb:
- changing selection parsing or prompt building usually touches plugin resolver logic and
packages/core - changing task identity, task persistence, or runtime execution usually touches the daemon and
packages/core - changing canvas result sync or node colors usually touches plugin write-back logic and often needs a smoke test
- changing bootstrap/setup usually touches
scripts/and sometimes the bootstrap skill
When behavior affects real Obsidian flows, prefer running the smallest relevant smoke test instead of stopping at syntax-only checks.