Rename before community plugin submission (plugin IDs are permanent). Updates plugin ID, display name, package name, all class names, CSS prefix (cc- → pf-), default folders (_claude → _context), built-in target ID, and all documentation. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
8.6 KiB
Promptfire – Obsidian Plugin
Project overview
An Obsidian community plugin that manages and copies vault context to clipboard for use with LLMs. Stores conventions, structure, and rules in a dedicated folder and provides one-hotkey copy with multi-LLM output formatting, prompt templates, frontmatter presets, granular section selection, and context history.
- Entry point:
src/main.ts→ compiled tomain.jsvia esbuild - Release artifacts:
main.js,manifest.json,styles.css(optional) - Plugin ID:
promptfire - Desktop only:
true(uses Node.jsfsandchild_processfor external sources)
Environment & tooling
- Runtime: Obsidian (Electron/Chromium)
- Language: TypeScript (
strict: true) - Package manager: npm
- Bundler: esbuild (config in
esbuild.config.mjs) - Target: ES2018, CommonJS output
- Dependencies: only
obsidian(latest) – no external runtime deps
Commands
npm install # Install dependencies
npm run dev # Watch mode (incremental, inline sourcemaps)
npm run build # Type-check + production build (minified, no sourcemaps)
Testing
Manual only – copy main.js, manifest.json, styles.css to <Vault>/.obsidian/plugins/promptfire/, reload Obsidian, enable plugin.
Source file structure
src/
├── main.ts # Plugin class, command registration, core copy logic
├── settings.ts # PromptfireSettings interface, defaults, settings tab UI
├── generator.ts # Context generator modal (vault structure setup wizard)
├── sources.ts # External context sources (freetext, file, folder, shell)
├── source-modal.ts # Modal for adding/editing context sources
├── presets.ts # Frontmatter preset parser & executor (ai-context block)
├── targets.ts # Multi-target output system (format, truncation, token limits)
├── target-modal.ts # Modal for adding/editing output targets
├── templates.ts # Prompt template engine & 5 starter templates
├── template-modal.ts # Modal for adding/editing templates + import/export
├── history.ts # Context history manager (save, cleanup, versioning)
├── history-modal.ts # History viewer modal (browse, diff, restore)
├── content-selector.ts # Heading/block tree parser for granular selection
├── file-selector-modal.ts # Modal for selecting files and sections
├── preview.ts # Preview modal before copying
Plugin commands
| ID | Name | Description |
|---|---|---|
copy-context |
Copy context to clipboard | Main command – copies all context files + sources |
copy-context-with-note |
Copy context with current note | Same as above but always includes active note |
copy-context-selective |
Copy context (select sections) | Opens file/heading selector modal |
copy-context-from-preset |
Copy context from frontmatter preset | Reads ai-context YAML block from active note |
generate-context |
Generate context files | Opens setup wizard to create initial context folder |
view-history |
View context history | Opens history browser with diff and restore |
Ribbon icon: clipboard-copy → triggers copy-context.
Settings (PromptfireSettings)
| Setting | Type | Default | Description |
|---|---|---|---|
contextFolder |
string |
'_context' |
Vault folder containing context .md files |
separator |
string |
'---' |
Text separator between files in output |
includeFilenames |
boolean |
true |
Add # === filename === headers |
showPreview |
boolean |
false |
Show preview modal before copying |
includeActiveNote |
boolean |
false |
Always append the currently open note |
excludedFiles |
string[] |
[] |
Filenames to skip (case-insensitive) |
sources |
ContextSource[] |
[] |
External context sources |
showSourceLabels |
boolean |
true |
Add position/name labels to source output |
promptTemplates |
PromptTemplate[] |
[] |
Prompt templates with placeholders |
defaultTemplateId |
string | null |
null |
Template applied automatically on copy |
history |
HistorySettings |
see below | History configuration |
targets |
OutputTarget[] |
[] |
Multi-LLM output targets |
primaryTargetId |
string | null |
null |
Target that goes to clipboard |
targetOutputFolder |
string |
'_context/outputs' |
Folder for secondary target files |
History settings
| Setting | Type | Default |
|---|---|---|
enabled |
boolean |
false |
storageFolder |
string |
'.context-history' |
maxEntries |
number |
50 |
autoCleanupDays |
number |
30 |
Architecture & key modules
Context sources (sources.ts)
Four source types, each with position: 'prefix' | 'suffix':
| Type | Config | Notes |
|---|---|---|
freetext |
{ content: string } |
Inline text snippets |
file |
{ path: string } |
External file (absolute path, requires Node.js fs) |
folder |
{ path: string; recursive: boolean; pattern?: string } |
Directory with optional glob filter |
shell |
{ command: string; args: string[]; cwd?: string; timeout?: number } |
Command output (default timeout 5s, max 1MB) |
Output targets (targets.ts)
Three built-in targets (can add custom):
| Name | Tokens | Format | Strategy |
|---|---|---|---|
| Promptfire | 200,000 | xml |
summarize-headers |
| GPT-4o | 128,000 | markdown |
summarize-headers |
| Compact (8k) | 8,000 | plain |
drop-sections |
Formats: markdown (default), xml (wraps in <file name="..."> tags), plain (strips markdown).
Truncation strategies: truncate (hard cut), summarize-headers (keep headers, collapse content), drop-sections (remove low-priority sections entirely).
Priority order for truncation: VAULT.md > context files > conventions > structure > active note > examples/templates.
Prompt templates (templates.ts)
Handlebars-like engine with variables: {{context}}, {{selection}}, {{active_note}}, {{active_note_name}}, {{date}}, {{time}}, {{datetime}}, {{vault_name}}. Supports {{#if var}}...{{else}}...{{/if}} conditionals.
Five starter templates: Code Review, Summary, Q&A, Continue Writing, Explain.
Frontmatter presets (presets.ts)
Reads ai-context YAML block from the active note's frontmatter:
ai-context:
template: "Template Name"
include-linked: true
link-depth: 2 # 0-10
include-tags: [tag1]
exclude-paths: [archive/]
exclude-tags: [draft]
max-tokens: 50000
include-active-note: true
Features: hierarchical tag matching, link traversal with cycle detection, token budgeting, full validation with errors/warnings.
Content selector (content-selector.ts)
Parses heading tree (H1–H6) and block IDs (^blockid) from markdown files. Enables partial file selection via FileSelectorModal. Output marks partial files with (partial) suffix.
History (history.ts)
Stores each generated context as JSON in vault. Tracks metadata: template used, included files/sources, active note, char/token counts, user notes. Auto-cleanup by age and entry count.
Coding conventions
main.tshandles plugin lifecycle and command registration – all feature logic lives in dedicated modules.- Each module exports its types/interfaces alongside implementation.
- Modals are in separate
*-modal.tsfiles, business logic in the corresponding.tsfile. - Settings are persisted via
loadData()/saveData()withObject.assignmerge pattern. - VAULT.md is always sorted first in context output.
- Token estimation:
chars / 4(rough approximation). - No external runtime dependencies – everything bundled into
main.js. - CSS class prefix:
pf-(e.g.pf-settings-tabs,pf-gen-modal).
Obsidian plugin conventions
- Add commands with stable IDs – never rename after release.
- Use
this.register*helpers for cleanup on unload. - No network calls without explicit user opt-in and documentation.
- No telemetry, no remote code execution.
- Keep
minAppVersionaccurate (0.15.0currently). - Bump
versioninmanifest.json(SemVer), updateversions.json, create GitHub release (tag = version, novprefix).
Manifest (manifest.json)
{
"id": "promptfire",
"name": "Promptfire",
"version": "1.0.0",
"minAppVersion": "0.15.0",
"description": "Copy vault context files to clipboard with one hotkey for any LLM.",
"author": "Luca",
"isDesktopOnly": true
}