Project-level Plugins
Use project-level plugins to build a mini SaaS inside your repository: practical use cases, supported extension points, project binding, and source references.
A project-level plugin gives a repository its own tools inside Daintree: a release board, a content review queue, a data explorer, or an interface for the services that team operates. The plugin lives with the project, changes through the same Git review process, and appears only in that project's views.
Think of it as building your own mini SaaS inside a project. You can give recurring work a purpose-built interface, with actions, persistent state, and connections to your existing systems. Daintree supplies the surrounding habitat: projects, worktrees, panels, agent terminals, and review. Your plugin supplies the workflow and vocabulary specific to your team.
This is a local application extension. A plugin does not automatically provide web hosting, shared accounts, billing, a multi-user database, or access control for a remote service. If your workflow needs those, your own backend supplies them. A useful first version can work entirely from files already in the repository.
Choose the right kind of extension
| Need | Use | How it travels |
|---|---|---|
| A tool whose meaning comes from this repository | A project plugin in <projectRoot>/.daintree/plugins/, declaring "scope": "project" | Commit the manifest and loadable output alongside the source. |
| A tool you want available across unrelated projects | An installed plugin in ~/.daintree/plugins/, with no top-level scope | Install a .dntr archive or sideload a directory. |
| A repeatable set of terminals and startup commands | A recipe | Save the launch configuration; build a plugin when the workflow needs its own UI or ongoing behavior. |
A project plugin is identified by its manifest name, conventionally also its directory name, such as acme.release-board. Two projects may ship that same name, and an installed copy may coexist with them. Daintree gives each project copy a separate runtime identity. Use the SDK's host.pluginInfo and host.panelKindId() helpers instead of constructing those internal identifiers yourself.
What you could build
These are design examples using the current extension surfaces, not bundled products. Each starts with a concrete recurring task and can grow as the repository's needs change.
| Project tool | First useful version | How it could grow |
|---|---|---|
| Release desk | A panel combining version files, changelog drafts, build results, and a release checklist. | Fetch release status from your service, run a managed validation process, and expose a reviewed publishing action with explicit confirmation. |
| Content studio | Read repository content into a queue of drafts, missing metadata, broken references, and review assignments. | Open a record in a plugin panel, save an edit to its source file, and stage a focused writing or checking prompt in an agent terminal. |
| Data workbench | Browse local datasets and compare generated reports without remembering file paths and command flags. | Launch validation or transformation jobs, stream progress, and preserve a panel's selected dataset and filters across remounts. |
| Service environment board | Show health and configuration for the services this project needs. | Start managed child processes, link to their existing browser interfaces, and connect to a team API for remote status. |
| Agent review queue | Combine the project's worktree snapshots and changed-file counts into a queue for a human reviewer. | Open relevant panels through host actions and send prepared context to the project's active agent. Treat observed agent state as a hint, never proof a task passed. |
| Customer or operations console | A project-specific interface over an API your team already owns. | Add scoped credentials, local preferences, and explicit confirmation for mutations. The backend continues to authorize every operation. |
The key question is whether an interface would save people repeatedly reconstructing the same context. A button that runs one stable command may belong in a recipe. A release that involves inspecting several artifacts, comparing states, and choosing a next action can justify a plugin.
Build a small platform in layers
- Make the state visible. Start with one panel showing real project data. Read through
host.fs,host.git, or a service you control. PrefergetWorktreesResult()when an unavailable project must be distinguished from an empty one. - Add useful actions. Declare commands in the manifest so they can trigger lazy activation, then register their handlers in
activate(). Give a navigation commandrequires: []; declare the actual capabilities used by a mutation. - Keep people oriented. Use toolbar buttons or context menus for frequent entry points. A file-oriented command can open the panel with
initialArgs; use the panel'sworktreeIdto preserve its actual context. - Persist the right information. Put shared defaults in project settings, machine-specific paths in local settings, private working state in storage, and small view preferences in
persistState. - Give the project a starting screen. Once the tool is useful, an empty-canvas surface can make it the first thing people see when no panels are open.
A panel communicates with its worker through registered channels. Pull initial state when the view mounts, then subscribe to updates. Pushes are not buffered: broadcasting during activation alone does not initialize a view that has not mounted yet. Keep long-running jobs in the worker, with cleanup tied to their actual lifetime.
What project scope supports
Project plugins can contribute commands, panels, views, toolbar buttons, context menus, keybindings, settings, and surfaces. The host routes those contributions to the owning project's renderers. A background plugin cannot accidentally dispatch its action or show its prompt in a different project merely because focus changed.
The current schema rejects menuItems, agents, skills, recipes, fileDecorationProviders, processTools, mcpServers, and forgeProviders in project plugins. Their registries or transports cannot provide the necessary project scope yet. A project plugin can still use supported host APIs to observe agents, send input with consent, or manage child processes; those are different from contributing a new app-wide agent or MCP server.
The manifest schema gives the exact accepted fields and explains each project-scope rejection. The contribution reference maps the complete extension surface.
The project root is the load boundary
Daintree scans the registered project's root, not each worktree under it. A plugin authored in an agent's separate worktree does not replace the version running from the root checkout. Bring the reviewed change into that checkout before expecting its plugin to load there. Merely selecting the agent's worktree is insufficient.
The load contract is plugin.json plus the compiled files it names, normally under dist/. Daintree never runs npm install, a package script, or a compiler when opening the project. A checkout must therefore include all required runtime output. Rebuild and commit it with the source change.
Trust and operating the tool
Repository plugins start disabled. A trust banner offers session-only or remembered enabling. Existing trusted plugins reload after changes to their manifest or output without asking again; a previously unseen manifest id is staged for explicit activation. Review plugin changes as executable code, including changes made by agents.
Use Project settings → Plugins to inspect the project folder, manage trust, change settings, reload, or turn an individual project plugin off with Run here. The installed-plugin control Show here only changes which UI contributions appear in this project; it leaves that global plugin running. See Project Plugin Trust & Management for the distinction.
Source reading map
The links below are pinned to the implementation reviewed on September 5, 2026. Start with the public contract, then read the implementation or tests for the behavior you are building against.
- Plugin types and host API: identity, panels, actions, storage, and project contribution contracts.
- ProjectPluginController: discovery reconciliation, trust, staging, muting, and teardown.
- PluginHostFactory and its binding tests: which project a host call reaches.
- Sample plugins: existing implementations to inspect and adapt. Samples have different scopes; copying an installed manifest into a project requires changing its scope and removing unsupported contributions.