Obsidian 99 is a desktop-only Obsidian plugin inspired by ThePrimeagen's 99. It aims to stay small: a tight command surface, minimal settings, and no extra infrastructure beyond the OpenCode CLI.
The plugin wraps a few focused AI workflows behind Obsidian commands:
99: Open launcher: opens a fuzzy launcher for the main actions.99: Visual selection: sends the current selection and note context to OpenCode, then replaces the selection with the returned text.99: Search: asks OpenCode for structured note locations and opens them in the results pane.99: Search work: reuses a saved work description and finds the next likely locations to continue.99: Vibe: runs a broader agentic pass and stores the returned summary and logs in request history.99: Open last requestand99: Open request history: reopen earlier results or inspect detailed logs.99: Select modeland99: Select provider: queryopencode modelsand switch the active backend from inside Obsidian.
The plugin also keeps a clickable status item in the Obsidian status bar so you can reopen recent activity quickly.
- Obsidian desktop
1.6.0+ - A filesystem-backed vault
- OpenCode CLI installed and available on
PATH, or configured via an absolute/~/path - OpenCode authentication configured for at least one provider
Example bootstrap:
opencode auth login
opencode models- Build the plugin:
npm install
npm run build- Copy these files into
.obsidian/plugins/obsidian-99/inside your vault:
manifest.jsonmain.jsstyles.css
- Reload community plugins in Obsidian and enable
Obsidian 99.
If you want to develop against a real vault:
- Create or choose a desktop Obsidian vault.
- Create
.obsidian/plugins/obsidian-99/inside that vault. - Symlink or copy
manifest.json,main.js, andstyles.cssfrom this repo into that folder. - Run
npm run devin this repo. - Reload the plugin inside Obsidian after each rebuild.
| Command | Behavior |
|---|---|
99: Open launcher |
Opens the main fuzzy action picker. |
99: Visual selection |
Rewrites the current selection in place. |
99: Search |
Shows structured note/file hits in the results pane. |
99: Vibe |
Runs a broader editing-style request and stores the returned summary/logs. |
99: Search work |
Uses the saved work description as the request. |
99: Set work description |
Updates the persistent work item. |
99: Open last request |
Reopens the most recent completed request. |
99: Open request history |
Opens the searchable request log. |
99: Select model |
Picks a model from opencode models. |
99: Select provider |
Picks a provider grouped from opencode models. |
99: Cancel active requests |
Cancels all active OpenCode requests. |
OpenCode binary: executable name, absolute path, or~/...path. Defaults toopencode.Model: active provider/model string, such asopencode/claude-sonnet-4-5.Timeout (seconds): request timeout used for OpenCode API calls.History limit: number of request records kept in memory.Work description: persistent input used by99: Search work.
Obsidian does not support multi-stroke leader sequences directly, so the closest workflow is:
- bind
99: Open launcherto something likeMod+9 - bind
99: Visual selectiondirectly if you want the fastest selection-rewrite flow - bind
99: Searchor99: Vibedirectly if you prefer dedicated commands
- The plugin currently expects a local, filesystem-backed vault because it resolves absolute paths and opens files from disk.
- Search results only open files that resolve inside the active vault.
- Visual replacement assumes the target note still exists and is editable when the response returns.
- The plugin does not assign default hotkeys in code; configure them through Obsidian's Hotkeys settings.
Useful commands while working on the plugin:
npm run dev
npm run typecheck
npm test
npm run buildCurrent automated verification covers parser behavior, prompt generation, request-store transitions, result formatting, runner behavior, and OpenCode server startup/error handling.