feat: rename plugin from "Claude Context" to "Promptfire"

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>
This commit is contained in:
Luca G. Oelfke 2026-02-06 12:42:16 +01:00
parent 72f64bcbd9
commit cc2d196911
No known key found for this signature in database
GPG key ID: E22BABF67200F864
16 changed files with 161 additions and 160 deletions

View file

@ -1,4 +1,4 @@
# Claude Context Obsidian Plugin
# Promptfire Obsidian Plugin
## Project overview
@ -6,7 +6,7 @@ An Obsidian community plugin that manages and copies vault context to clipboard
- **Entry point**: `src/main.ts` → compiled to `main.js` via esbuild
- **Release artifacts**: `main.js`, `manifest.json`, `styles.css` (optional)
- **Plugin ID**: `claude-context`
- **Plugin ID**: `promptfire`
- **Desktop only**: `true` (uses Node.js `fs` and `child_process` for external sources)
## Environment & tooling
@ -28,14 +28,14 @@ npm run build # Type-check + production build (minified, no sourcemaps)
### Testing
Manual only copy `main.js`, `manifest.json`, `styles.css` to `<Vault>/.obsidian/plugins/claude-context/`, reload Obsidian, enable plugin.
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 # ClaudeContextSettings interface, defaults, settings tab UI
├── 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
@ -64,11 +64,11 @@ src/
Ribbon icon: `clipboard-copy` → triggers `copy-context`.
## Settings (`ClaudeContextSettings`)
## Settings (`PromptfireSettings`)
| Setting | Type | Default | Description |
|---------|------|---------|-------------|
| `contextFolder` | `string` | `'_claude'` | Vault folder containing context `.md` files |
| `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 |
@ -81,7 +81,7 @@ Ribbon icon: `clipboard-copy` → triggers `copy-context`.
| `history` | `HistorySettings` | see below | History configuration |
| `targets` | `OutputTarget[]` | `[]` | Multi-LLM output targets |
| `primaryTargetId` | `string \| null` | `null` | Target that goes to clipboard |
| `targetOutputFolder` | `string` | `'_claude/outputs'` | Folder for secondary target files |
| `targetOutputFolder` | `string` | `'_context/outputs'` | Folder for secondary target files |
### History settings
@ -111,7 +111,7 @@ Three built-in targets (can add custom):
| Name | Tokens | Format | Strategy |
|------|--------|--------|----------|
| Claude | 200,000 | `xml` | `summarize-headers` |
| Promptfire | 200,000 | `xml` | `summarize-headers` |
| GPT-4o | 128,000 | `markdown` | `summarize-headers` |
| Compact (8k) | 8,000 | `plain` | `drop-sections` |
@ -162,6 +162,7 @@ Stores each generated context as JSON in vault. Tracks metadata: template used,
- 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
@ -176,11 +177,11 @@ Stores each generated context as JSON in vault. Tracks metadata: template used,
```json
{
"id": "claude-context",
"name": "Claude Context",
"id": "promptfire",
"name": "Promptfire",
"version": "1.0.0",
"minAppVersion": "0.15.0",
"description": "Copy .claude/ context files to clipboard with one hotkey.",
"description": "Copy vault context files to clipboard with one hotkey for any LLM.",
"author": "Luca",
"isDesktopOnly": true
}

View file

@ -1,6 +1,6 @@
<div align="center">
# Claude Context
# Promptfire
[![Obsidian](https://img.shields.io/badge/Obsidian-Plugin-7C3AED?logo=obsidian&logoColor=white)](https://obsidian.md)
[![TypeScript](https://img.shields.io/badge/TypeScript-5.8-3178C6?logo=typescript&logoColor=white)](https://www.typescriptlang.org/)
@ -49,7 +49,7 @@ When working with AI assistants on your Obsidian vault, you constantly need to e
</div>
**Claude Context** is a comprehensive context management system that:
**Promptfire** is a comprehensive context management system that:
1. **Stores your vault's conventions** in a dedicated folder
2. **Copies everything** to clipboard with one hotkey
@ -91,7 +91,7 @@ Your folder structure here...
| Target | Tokens | Format | Strategy |
|--------|--------|--------|----------|
| **Claude** | 200,000 | XML | Summarize headers |
| **Promptfire** | 200,000 | XML | Summarize headers |
| **GPT-4o** | 128,000 | Markdown | Summarize headers |
| **Compact** | 8,000 | Plain | Drop sections |
@ -258,7 +258,7 @@ Click **"Generate"** and your context files are created instantly.
### From Community Plugins (Recommended)
1. Open **Settings > Community Plugins**
2. Click **Browse** and search for "Claude Context"
2. Click **Browse** and search for "Promptfire"
3. Click **Install**, then **Enable**
### From Source
@ -266,10 +266,10 @@ Click **"Generate"** and your context files are created instantly.
```bash
# Clone into your vault's plugins folder
cd /path/to/vault/.obsidian/plugins
git clone https://github.com/yourusername/obsidian-claude-context.git claude-context
git clone https://github.com/yourusername/obsidian-promptfire.git promptfire
# Install and build
cd claude-context
cd promptfire
npm install
npm run build
@ -293,19 +293,19 @@ npm run dev # Watch mode with hot reload
### 1. Generate Context Files
```
Ctrl+P > "Claude Context: Generate context files"
Ctrl+P > "Promptfire: Generate context files"
```
Configure your preferences and click **Generate**.
### 2. Add Built-in Targets
Go to **Settings > Claude Context > Output Targets** and click **"Add Built-in Targets"**.
Go to **Settings > Promptfire > Output Targets** and click **"Add Built-in Targets"**.
### 3. Copy Context
```
Ctrl+P > "Claude Context: Copy context to clipboard"
Ctrl+P > "Promptfire: Copy context to clipboard"
```
Or click the clipboard ribbon icon.
@ -337,7 +337,7 @@ The context is now in your clipboard. Paste it into Claude, ChatGPT, or any AI a
| Setting | Description | Default |
|---------|-------------|---------|
| **Context folder** | Folder with context files | `_claude` |
| **Context folder** | Folder with context files | `_context` |
| **Separator** | Text between files | `---` |
| **Include filenames** | Add `# === file.md ===` headers | On |
| **Show preview** | Preview before copying | Off |
@ -497,9 +497,9 @@ MIT License - see [LICENSE](LICENSE) for details.
</div>
- **Bug reports:** [GitHub Issues](https://github.com/yourusername/obsidian-claude-context/issues)
- **Feature requests:** [GitHub Discussions](https://github.com/yourusername/obsidian-claude-context/discussions)
- **Documentation:** [Wiki](https://github.com/yourusername/obsidian-claude-context/wiki)
- **Bug reports:** [GitHub Issues](https://github.com/yourusername/obsidian-promptfire/issues)
- **Feature requests:** [GitHub Discussions](https://github.com/yourusername/obsidian-promptfire/discussions)
- **Documentation:** [Wiki](https://github.com/yourusername/obsidian-promptfire/wiki)
---

View file

@ -1,9 +1,9 @@
{
"id": "claude-context",
"name": "Claude Context",
"id": "promptfire",
"name": "Promptfire",
"version": "1.0.0",
"minAppVersion": "0.15.0",
"description": "Copy .claude/ context files to clipboard with one hotkey.",
"description": "Copy vault context files to clipboard with one hotkey for any LLM.",
"author": "Luca",
"isDesktopOnly": true
}

4
package-lock.json generated
View file

@ -1,11 +1,11 @@
{
"name": "obsidian-claude-context",
"name": "obsidian-promptfire",
"version": "1.0.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "obsidian-claude-context",
"name": "obsidian-promptfire",
"version": "1.0.0",
"license": "MIT",
"dependencies": {

View file

@ -1,7 +1,7 @@
{
"name": "obsidian-claude-context",
"name": "obsidian-promptfire",
"version": "1.0.0",
"description": "Copy .claude/ context files to clipboard",
"description": "Copy vault context files to clipboard for any LLM",
"main": "main.js",
"type": "module",
"scripts": {

View file

@ -1,5 +1,5 @@
import { App, Modal, TFile, TFolder } from 'obsidian';
import ClaudeContextPlugin from './main';
import PromptfirePlugin from './main';
import {
ContentSelector,
FileSelection,
@ -14,7 +14,7 @@ export interface FileSelectionResult {
}
export class FileSelectorModal extends Modal {
plugin: ClaudeContextPlugin;
plugin: PromptfirePlugin;
selector: ContentSelector;
selections: FileSelection[] = [];
onConfirm: (result: FileSelectionResult) => void;
@ -24,7 +24,7 @@ export class FileSelectorModal extends Modal {
constructor(
app: App,
plugin: ClaudeContextPlugin,
plugin: PromptfirePlugin,
onConfirm: (result: FileSelectionResult) => void
) {
super(app);
@ -36,7 +36,7 @@ export class FileSelectorModal extends Modal {
async onOpen() {
const { contentEl } = this;
contentEl.empty();
contentEl.addClass('claude-context-file-selector');
contentEl.addClass('promptfire-file-selector');
contentEl.style.minWidth = '500px';
contentEl.createEl('h2', { text: 'Select Context Content' });

View file

@ -1,5 +1,5 @@
import { App, Modal, Notice, Setting, TFile, TFolder } from 'obsidian';
import ClaudeContextPlugin from './main';
import PromptfirePlugin from './main';
import { createFreetextSource, SourcePosition } from './sources';
import { estimateTokens } from './history';
import { OutputTarget, OutputFormat, getTargetIcon, formatTokenCount } from './targets';
@ -77,7 +77,7 @@ const DEFAULT_CONFIG: ContextConfig = {
};
export class ContextGeneratorModal extends Modal {
plugin: ClaudeContextPlugin;
plugin: PromptfirePlugin;
config: ContextConfig;
// Additional context state
@ -102,7 +102,7 @@ export class ContextGeneratorModal extends Modal {
private statusFormat: HTMLElement | null = null;
private targetsHeadingEl: HTMLElement | null = null;
constructor(app: App, plugin: ClaudeContextPlugin) {
constructor(app: App, plugin: PromptfirePlugin) {
super(app);
this.plugin = plugin;
this.config = JSON.parse(JSON.stringify(DEFAULT_CONFIG));
@ -119,21 +119,21 @@ export class ContextGeneratorModal extends Modal {
onOpen() {
const { contentEl } = this;
contentEl.empty();
contentEl.addClass('claude-context-generator');
this.modalEl.addClass('cc-gen-modal');
contentEl.addClass('promptfire-generator');
this.modalEl.addClass('pf-gen-modal');
contentEl.createEl('h2', { text: 'Context Generator' });
// === STATUS BAR ===
const statusBar = contentEl.createDiv({ cls: 'cc-gen-statusbar' });
const statusBar = contentEl.createDiv({ cls: 'pf-gen-statusbar' });
this.statusFileCount = statusBar.createEl('span', { cls: 'cc-statusbar-item' });
statusBar.createEl('span', { cls: 'cc-statusbar-sep', text: '\u00B7' });
this.statusTokens = statusBar.createEl('span', { cls: 'cc-statusbar-item cc-statusbar-tokens' });
statusBar.createEl('span', { cls: 'cc-statusbar-sep', text: '\u00B7' });
this.statusTarget = statusBar.createEl('span', { cls: 'cc-statusbar-item cc-statusbar-clickable' });
statusBar.createEl('span', { cls: 'cc-statusbar-sep', text: '\u00B7' });
this.statusFormat = statusBar.createEl('span', { cls: 'cc-statusbar-item cc-statusbar-clickable' });
this.statusFileCount = statusBar.createEl('span', { cls: 'pf-statusbar-item' });
statusBar.createEl('span', { cls: 'pf-statusbar-sep', text: '\u00B7' });
this.statusTokens = statusBar.createEl('span', { cls: 'pf-statusbar-item pf-statusbar-tokens' });
statusBar.createEl('span', { cls: 'pf-statusbar-sep', text: '\u00B7' });
this.statusTarget = statusBar.createEl('span', { cls: 'pf-statusbar-item pf-statusbar-clickable' });
statusBar.createEl('span', { cls: 'pf-statusbar-sep', text: '\u00B7' });
this.statusFormat = statusBar.createEl('span', { cls: 'pf-statusbar-item pf-statusbar-clickable' });
// Click target label → scroll to Output Targets section
this.statusTarget.addEventListener('click', () => {
@ -158,9 +158,9 @@ export class ContextGeneratorModal extends Modal {
this.updateStatusBar();
// === TWO-ZONE GRID LAYOUT ===
const layout = contentEl.createDiv({ cls: 'cc-gen-layout' });
const selectionZone = layout.createDiv({ cls: 'cc-gen-zone cc-gen-selection' });
const configZone = layout.createDiv({ cls: 'cc-gen-zone cc-gen-configuration' });
const layout = contentEl.createDiv({ cls: 'pf-gen-layout' });
const selectionZone = layout.createDiv({ cls: 'pf-gen-zone pf-gen-selection' });
const configZone = layout.createDiv({ cls: 'pf-gen-zone pf-gen-configuration' });
// =============================================
// SELECTION ZONE (left) "What to include"
@ -263,7 +263,7 @@ export class ContextGeneratorModal extends Modal {
const fileCount = this.app.vault.getFiles().length;
const folderCount = this.config.folders.length;
selectionZone.createDiv({
cls: 'cc-gen-stat',
cls: 'pf-gen-stat',
text: `${folderCount} folders, ${fileCount} total files in vault`,
});
@ -495,19 +495,19 @@ export class ContextGeneratorModal extends Modal {
// PREVIEW PANE (full-width, between grid and footer)
// =============================================
const previewSection = contentEl.createDiv({
cls: `cc-section cc-preview-section${this.previewOpen ? '' : ' is-collapsed'}`,
cls: `pf-section pf-preview-section${this.previewOpen ? '' : ' is-collapsed'}`,
});
const previewHeader = previewSection.createDiv({ cls: 'cc-section-header' });
const previewHeader = previewSection.createDiv({ cls: 'pf-section-header' });
const previewTitle = previewHeader.createEl('span', {
text: this.previewOpen ? 'Hide Preview' : 'Show Preview',
cls: 'cc-section-title',
cls: 'pf-section-title',
});
previewHeader.createEl('span', { text: '\u203A', cls: 'cc-section-chevron' });
previewHeader.createEl('span', { text: '\u203A', cls: 'pf-section-chevron' });
const previewBody = previewSection.createDiv({ cls: 'cc-section-content cc-preview-body' });
this.previewContent = previewBody.createEl('pre', { cls: 'cc-preview-code' });
this.previewLineInfo = previewBody.createDiv({ cls: 'cc-preview-line-info' });
const previewBody = previewSection.createDiv({ cls: 'pf-section-content pf-preview-body' });
this.previewContent = previewBody.createEl('pre', { cls: 'pf-preview-code' });
this.previewLineInfo = previewBody.createDiv({ cls: 'pf-preview-line-info' });
previewHeader.addEventListener('click', async () => {
this.previewOpen = !this.previewOpen;
@ -530,7 +530,7 @@ export class ContextGeneratorModal extends Modal {
// =============================================
// FOOTER (full-width, below both zones)
// =============================================
const footer = contentEl.createDiv({ cls: 'cc-gen-footer' });
const footer = contentEl.createDiv({ cls: 'pf-gen-footer' });
const copyButtonContainer = footer.createDiv();
copyButtonContainer.style.display = 'flex';
@ -664,7 +664,7 @@ export class ContextGeneratorModal extends Modal {
const tokens = Math.ceil(totalChars / 4);
container.createDiv({
cls: 'cc-gen-stat',
cls: 'pf-gen-stat',
text: `Estimated tokens: ~${tokens.toLocaleString()} (from existing context files)`,
});
}

View file

@ -1,5 +1,5 @@
import { App, Modal, Notice, Setting } from 'obsidian';
import ClaudeContextPlugin from './main';
import PromptfirePlugin from './main';
import {
HistoryEntry,
HistoryManager,
@ -10,12 +10,12 @@ import {
} from './history';
export class HistoryModal extends Modal {
plugin: ClaudeContextPlugin;
plugin: PromptfirePlugin;
historyManager: HistoryManager;
entries: HistoryEntry[] = [];
selectedEntries: Set<string> = new Set();
constructor(app: App, plugin: ClaudeContextPlugin, historyManager: HistoryManager) {
constructor(app: App, plugin: PromptfirePlugin, historyManager: HistoryManager) {
super(app);
this.plugin = plugin;
this.historyManager = historyManager;
@ -28,7 +28,7 @@ export class HistoryModal extends Modal {
async loadAndRender() {
const { contentEl } = this;
contentEl.empty();
contentEl.addClass('claude-context-history-modal');
contentEl.addClass('promptfire-history-modal');
contentEl.createEl('h2', { text: 'Context History' });
@ -218,14 +218,14 @@ export class HistoryModal extends Modal {
}
class HistoryDetailModal extends Modal {
plugin: ClaudeContextPlugin;
plugin: PromptfirePlugin;
historyManager: HistoryManager;
entry: HistoryEntry;
onUpdate: () => void;
constructor(
app: App,
plugin: ClaudeContextPlugin,
plugin: PromptfirePlugin,
historyManager: HistoryManager,
entry: HistoryEntry,
onUpdate: () => void
@ -240,7 +240,7 @@ class HistoryDetailModal extends Modal {
onOpen() {
const { contentEl } = this;
contentEl.empty();
contentEl.addClass('claude-context-history-detail');
contentEl.addClass('promptfire-history-detail');
contentEl.createEl('h2', { text: 'History Entry Details' });
@ -364,7 +364,7 @@ class HistoryDiffModal extends Modal {
onOpen() {
const { contentEl } = this;
contentEl.empty();
contentEl.addClass('claude-context-history-diff');
contentEl.addClass('promptfire-history-diff');
contentEl.createEl('h2', { text: 'Compare Contexts' });

View file

@ -1,5 +1,5 @@
import { MarkdownView, Notice, Plugin, TFile, TFolder } from 'obsidian';
import { ClaudeContextSettings, ClaudeContextSettingTab, DEFAULT_SETTINGS } from './settings';
import { PromptfireSettings, PromptfireSettingTab, DEFAULT_SETTINGS } from './settings';
import { ContextGeneratorModal } from './generator';
import { PreviewModal } from './preview';
import { SourceRegistry, formatSourceOutput } from './sources';
@ -21,8 +21,8 @@ import {
saveTargetToFile,
} from './targets';
export default class ClaudeContextPlugin extends Plugin {
settings: ClaudeContextSettings;
export default class PromptfirePlugin extends Plugin {
settings: PromptfireSettings;
historyManager: HistoryManager;
async onload() {
@ -30,7 +30,7 @@ export default class ClaudeContextPlugin extends Plugin {
this.historyManager = new HistoryManager(this.app, this.settings.history);
// Ribbon icon
this.addRibbonIcon('clipboard-copy', 'Copy Claude context', () => {
this.addRibbonIcon('clipboard-copy', 'Copy Promptfire context', () => {
this.copyContextToClipboard();
});
@ -70,7 +70,7 @@ export default class ClaudeContextPlugin extends Plugin {
callback: () => this.copyContextFromPreset()
});
this.addSettingTab(new ClaudeContextSettingTab(this.app, this));
this.addSettingTab(new PromptfireSettingTab(this.app, this));
}
openFileSelector() {

View file

@ -15,7 +15,7 @@ export class PreviewModal extends Modal {
onOpen() {
const { contentEl } = this;
contentEl.empty();
contentEl.addClass('claude-context-preview');
contentEl.addClass('promptfire-preview');
contentEl.createEl('h2', { text: `Preview (${this.fileCount} files)` });

View file

@ -1,5 +1,5 @@
import { App, Notice, PluginSettingTab, Setting, TFile, TFolder } from 'obsidian';
import ClaudeContextPlugin from './main';
import PromptfirePlugin from './main';
import { ContextSource, getSourceIcon, SourceRegistry } from './sources';
import { SourceModal } from './source-modal';
import { PromptTemplate, STARTER_TEMPLATES } from './templates';
@ -8,7 +8,7 @@ import { HistorySettings, DEFAULT_HISTORY_SETTINGS } from './history';
import { OutputTarget, BUILTIN_TARGETS, getTargetIcon } from './targets';
import { TargetModal } from './target-modal';
export interface ClaudeContextSettings {
export interface PromptfireSettings {
contextFolder: string;
separator: string;
includeFilenames: boolean;
@ -28,8 +28,8 @@ export interface ClaudeContextSettings {
generatorPreviewOpen: boolean;
}
export const DEFAULT_SETTINGS: ClaudeContextSettings = {
contextFolder: '_claude',
export const DEFAULT_SETTINGS: PromptfireSettings = {
contextFolder: '_context',
separator: '---',
includeFilenames: true,
showPreview: false,
@ -42,7 +42,7 @@ export const DEFAULT_SETTINGS: ClaudeContextSettings = {
history: DEFAULT_HISTORY_SETTINGS,
targets: [],
primaryTargetId: null,
targetOutputFolder: '_claude/outputs',
targetOutputFolder: '_context/outputs',
lastSettingsTab: 'general',
collapsedSections: [],
generatorPreviewOpen: false,
@ -65,17 +65,17 @@ class CollapsibleSection {
parent: HTMLElement,
id: string,
title: string,
plugin: ClaudeContextPlugin,
plugin: PromptfirePlugin,
) {
const isCollapsed = plugin.settings.collapsedSections.includes(id);
const wrapper = parent.createDiv({ cls: `cc-section${isCollapsed ? ' is-collapsed' : ''}` });
const wrapper = parent.createDiv({ cls: `pf-section${isCollapsed ? ' is-collapsed' : ''}` });
const header = wrapper.createDiv({ cls: 'cc-section-header' });
header.createEl('span', { text: title, cls: 'cc-section-title' });
header.createEl('span', { text: '\u203A', cls: 'cc-section-chevron' });
const header = wrapper.createDiv({ cls: 'pf-section-header' });
header.createEl('span', { text: title, cls: 'pf-section-title' });
header.createEl('span', { text: '\u203A', cls: 'pf-section-chevron' });
this.contentEl = wrapper.createDiv({ cls: 'cc-section-content' });
this.contentEl = wrapper.createDiv({ cls: 'pf-section-content' });
header.addEventListener('click', async () => {
const nowCollapsed = wrapper.hasClass('is-collapsed');
@ -91,12 +91,12 @@ class CollapsibleSection {
}
}
export class ClaudeContextSettingTab extends PluginSettingTab {
plugin: ClaudeContextPlugin;
export class PromptfireSettingTab extends PluginSettingTab {
plugin: PromptfirePlugin;
private activeTab: SettingsTabId;
private searchQuery = '';
constructor(app: App, plugin: ClaudeContextPlugin) {
constructor(app: App, plugin: PromptfirePlugin) {
super(app, plugin);
this.plugin = plugin;
this.activeTab = (plugin.settings.lastSettingsTab as SettingsTabId) || 'general';
@ -110,7 +110,7 @@ export class ClaudeContextSettingTab extends PluginSettingTab {
const searchInput = containerEl.createEl('input', {
type: 'text',
placeholder: 'Search settings...',
cls: 'cc-settings-search-input',
cls: 'pf-settings-search-input',
});
searchInput.value = this.searchQuery;
@ -122,7 +122,7 @@ export class ClaudeContextSettingTab extends PluginSettingTab {
if (wasSearching !== nowSearching) {
// Mode transition (tabs ↔ all): re-render and refocus
this.display();
const refocused = containerEl.querySelector('.cc-settings-search-input') as HTMLInputElement;
const refocused = containerEl.querySelector('.pf-settings-search-input') as HTMLInputElement;
if (refocused) {
refocused.focus();
refocused.selectionStart = refocused.selectionEnd = refocused.value.length;
@ -141,7 +141,7 @@ export class ClaudeContextSettingTab extends PluginSettingTab {
}
});
const content = containerEl.createDiv({ cls: 'cc-settings-tab-content' });
const content = containerEl.createDiv({ cls: 'pf-settings-tab-content' });
if (this.searchQuery) {
// Search mode: render all tabs with group headings
@ -154,21 +154,21 @@ export class ClaudeContextSettingTab extends PluginSettingTab {
];
for (const tab of tabRenderers) {
const group = content.createDiv({ cls: 'cc-settings-search-group' });
group.createEl('h4', { text: tab.label, cls: 'cc-settings-search-heading' });
const group = content.createDiv({ cls: 'pf-settings-search-group' });
group.createEl('h4', { text: tab.label, cls: 'pf-settings-search-heading' });
tab.render(group);
}
this.filterSettings(content);
} else {
// Normal mode: tab navigation
const nav = containerEl.createEl('nav', { cls: 'cc-settings-tabs' });
const nav = containerEl.createEl('nav', { cls: 'pf-settings-tabs' });
containerEl.insertBefore(nav, content);
for (const tab of SETTINGS_TABS) {
const btn = nav.createEl('button', {
text: tab.label,
cls: 'cc-settings-tab',
cls: 'pf-settings-tab',
});
if (tab.id === this.activeTab) {
btn.addClass('is-active');
@ -203,7 +203,7 @@ export class ClaudeContextSettingTab extends PluginSettingTab {
});
// Force-expand all collapsible sections, hide ones with no visible settings
content.querySelectorAll('.cc-section').forEach(el => {
content.querySelectorAll('.pf-section').forEach(el => {
const section = el as HTMLElement;
section.classList.remove('is-collapsed');
const hasVisible = Array.from(section.querySelectorAll('.setting-item'))
@ -213,7 +213,7 @@ export class ClaudeContextSettingTab extends PluginSettingTab {
// Hide tab groups with no visible settings
let totalVisible = 0;
content.querySelectorAll('.cc-settings-search-group').forEach(el => {
content.querySelectorAll('.pf-settings-search-group').forEach(el => {
const group = el as HTMLElement;
const visibleCount = Array.from(group.querySelectorAll('.setting-item'))
.filter(s => (s as HTMLElement).style.display !== 'none').length;
@ -222,12 +222,12 @@ export class ClaudeContextSettingTab extends PluginSettingTab {
});
// Show "no results" message
let noResults = content.querySelector('.cc-settings-no-results') as HTMLElement;
let noResults = content.querySelector('.pf-settings-no-results') as HTMLElement;
if (totalVisible === 0) {
if (!noResults) {
noResults = content.createEl('p', {
text: `No settings matching "${this.searchQuery}"`,
cls: 'cc-settings-no-results',
cls: 'pf-settings-no-results',
});
} else {
noResults.textContent = `No settings matching "${this.searchQuery}"`;
@ -242,7 +242,7 @@ export class ClaudeContextSettingTab extends PluginSettingTab {
setting.descEl.empty();
setting.descEl.appendText(base);
if (dynamic) {
setting.descEl.createSpan({ text: ` (${dynamic})`, cls: 'cc-dynamic-desc' });
setting.descEl.createSpan({ text: ` (${dynamic})`, cls: 'pf-dynamic-desc' });
}
}
@ -278,7 +278,7 @@ export class ClaudeContextSettingTab extends PluginSettingTab {
const contextFolderSetting = new Setting(el)
.setName('Context folder')
.addText(text => text
.setPlaceholder('_claude')
.setPlaceholder('_context')
.setValue(this.plugin.settings.contextFolder)
.onChange(async (value) => {
this.plugin.settings.contextFolder = value;
@ -527,10 +527,10 @@ export class ClaudeContextSettingTab extends PluginSettingTab {
const outputFolderSetting = new Setting(oc)
.setName('Output folder')
.addText(text => text
.setPlaceholder('_claude/outputs')
.setPlaceholder('_context/outputs')
.setValue(this.plugin.settings.targetOutputFolder)
.onChange(async (value) => {
this.plugin.settings.targetOutputFolder = value || '_claude/outputs';
this.plugin.settings.targetOutputFolder = value || '_context/outputs';
await this.plugin.saveSettings();
this.describeOutputFolder(outputFolderSetting, this.plugin.settings.targetOutputFolder);
}));

View file

@ -1,5 +1,5 @@
import { App, Modal, Notice, Setting } from 'obsidian';
import ClaudeContextPlugin from './main';
import PromptfirePlugin from './main';
import {
ContextSource,
SourceType,
@ -12,7 +12,7 @@ import {
} from './sources';
export class SourceModal extends Modal {
plugin: ClaudeContextPlugin;
plugin: PromptfirePlugin;
sourceType: SourceType;
existingSource: ContextSource | null;
onSave: () => void;
@ -38,7 +38,7 @@ export class SourceModal extends Modal {
constructor(
app: App,
plugin: ClaudeContextPlugin,
plugin: PromptfirePlugin,
sourceType: SourceType,
existingSource: ContextSource | null,
onSave: () => void
@ -80,7 +80,7 @@ export class SourceModal extends Modal {
onOpen() {
const { contentEl } = this;
contentEl.empty();
contentEl.addClass('claude-context-source-modal');
contentEl.addClass('promptfire-source-modal');
const title = this.existingSource ? 'Edit Source' : 'Add Source';
const typeLabel = this.getTypeLabel();

View file

@ -1,5 +1,5 @@
import { App, Modal, Notice, Setting } from 'obsidian';
import ClaudeContextPlugin from './main';
import PromptfirePlugin from './main';
import {
OutputTarget,
OutputFormat,
@ -8,7 +8,7 @@ import {
} from './targets';
export class TargetModal extends Modal {
plugin: ClaudeContextPlugin;
plugin: PromptfirePlugin;
target: OutputTarget | null;
isNew: boolean;
onSave: () => void;
@ -25,7 +25,7 @@ export class TargetModal extends Modal {
constructor(
app: App,
plugin: ClaudeContextPlugin,
plugin: PromptfirePlugin,
target: OutputTarget | null,
onSave: () => void
) {

View file

@ -39,8 +39,8 @@ export function generateTargetId(): string {
export const BUILTIN_TARGETS: OutputTarget[] = [
{
id: 'builtin_claude',
name: 'Claude',
id: 'builtin_promptfire',
name: 'Promptfire',
maxTokens: 200000,
format: 'xml',
strategy: 'summarize-headers',

View file

@ -1,5 +1,5 @@
import { App, Modal, Notice, Setting } from 'obsidian';
import ClaudeContextPlugin from './main';
import PromptfirePlugin from './main';
import {
PromptTemplate,
generateTemplateId,
@ -8,7 +8,7 @@ import {
} from './templates';
export class TemplateModal extends Modal {
plugin: ClaudeContextPlugin;
plugin: PromptfirePlugin;
existingTemplate: PromptTemplate | null;
onSave: () => void;
@ -19,7 +19,7 @@ export class TemplateModal extends Modal {
constructor(
app: App,
plugin: ClaudeContextPlugin,
plugin: PromptfirePlugin,
existingTemplate: PromptTemplate | null,
onSave: () => void
) {
@ -38,7 +38,7 @@ export class TemplateModal extends Modal {
onOpen() {
const { contentEl } = this;
contentEl.empty();
contentEl.addClass('claude-context-template-modal');
contentEl.addClass('promptfire-template-modal');
const title = this.existingTemplate ? 'Edit Template' : 'New Template';
contentEl.createEl('h2', { text: title });
@ -188,7 +188,7 @@ export class TemplateModal extends Modal {
// Import/Export Modal
export class TemplateImportExportModal extends Modal {
plugin: ClaudeContextPlugin;
plugin: PromptfirePlugin;
mode: 'import' | 'export';
onComplete: () => void;
@ -196,7 +196,7 @@ export class TemplateImportExportModal extends Modal {
constructor(
app: App,
plugin: ClaudeContextPlugin,
plugin: PromptfirePlugin,
mode: 'import' | 'export',
onComplete: () => void
) {

View file

@ -1,5 +1,5 @@
/* Settings search */
.cc-settings-search-input {
.pf-settings-search-input {
width: 100%;
padding: 8px 12px;
margin-bottom: 8px;
@ -10,16 +10,16 @@
font-size: 14px;
}
.cc-settings-search-input:focus {
.pf-settings-search-input:focus {
border-color: var(--interactive-accent);
outline: none;
}
.cc-settings-search-input::placeholder {
.pf-settings-search-input::placeholder {
color: var(--text-faint);
}
.cc-settings-search-heading {
.pf-settings-search-heading {
font-size: 13px;
font-weight: 600;
color: var(--text-muted);
@ -30,23 +30,23 @@
border-bottom: 1px solid var(--background-modifier-border);
}
.cc-settings-search-group:first-child .cc-settings-search-heading {
.pf-settings-search-group:first-child .pf-settings-search-heading {
margin-top: 0;
}
.cc-settings-no-results {
.pf-settings-no-results {
color: var(--text-muted);
font-style: italic;
text-align: center;
padding: 20px 0;
}
.cc-dynamic-desc {
.pf-dynamic-desc {
color: var(--text-faint);
}
/* Tab navigation for settings */
.cc-settings-tabs {
.pf-settings-tabs {
display: flex;
gap: 0;
border-bottom: 1px solid var(--background-modifier-border);
@ -58,7 +58,7 @@
padding-top: 4px;
}
.cc-settings-tab {
.pf-settings-tab {
padding: 8px 16px;
border: none;
background: none;
@ -69,22 +69,22 @@
transition: color 0.15s ease, border-color 0.15s ease;
}
.cc-settings-tab:hover {
.pf-settings-tab:hover {
color: var(--text-normal);
}
.cc-settings-tab.is-active {
.pf-settings-tab.is-active {
color: var(--text-normal);
border-bottom-color: var(--interactive-accent);
font-weight: 600;
}
/* Collapsible sections */
.cc-section {
.pf-section {
margin-bottom: 8px;
}
.cc-section-header {
.pf-section-header {
display: flex;
align-items: center;
padding: 8px 4px;
@ -93,27 +93,27 @@
user-select: none;
}
.cc-section-header:hover {
.pf-section-header:hover {
background: var(--background-modifier-hover);
}
.cc-section-title {
.pf-section-title {
flex: 1;
font-weight: 600;
font-size: 14px;
}
.cc-section-chevron {
.pf-section-chevron {
font-size: 16px;
transition: transform 0.2s ease;
transform: rotate(90deg);
}
.cc-section.is-collapsed .cc-section-chevron {
.pf-section.is-collapsed .pf-section-chevron {
transform: rotate(0deg);
}
.cc-section-content {
.pf-section-content {
max-height: 2000px;
overflow: hidden;
transition: max-height 0.25s ease, opacity 0.2s ease;
@ -121,26 +121,26 @@
padding-top: 4px;
}
.cc-section.is-collapsed .cc-section-content {
.pf-section.is-collapsed .pf-section-content {
max-height: 0;
opacity: 0;
padding-top: 0;
}
/* Generator modal */
.cc-gen-modal {
.pf-gen-modal {
width: 70vw;
max-width: 900px;
}
.cc-gen-modal .modal-content {
.pf-gen-modal .modal-content {
max-height: 80vh;
overflow-y: auto;
display: flex;
flex-direction: column;
}
.cc-gen-layout {
.pf-gen-layout {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 20px;
@ -148,28 +148,28 @@
min-height: 0;
}
.cc-gen-zone {
.pf-gen-zone {
overflow-y: auto;
max-height: 60vh;
padding-right: 8px;
}
.cc-gen-selection {
.pf-gen-selection {
border-right: 1px solid var(--background-modifier-border);
padding-right: 20px;
}
.cc-gen-zone h3 {
.pf-gen-zone h3 {
margin-top: 0;
}
.cc-gen-footer {
.pf-gen-footer {
border-top: 1px solid var(--background-modifier-border);
padding-top: 12px;
margin-top: 12px;
}
.cc-gen-stat {
.pf-gen-stat {
font-size: 12px;
color: var(--text-muted);
padding: 6px 10px;
@ -179,7 +179,7 @@
}
/* Generator status bar */
.cc-gen-statusbar {
.pf-gen-statusbar {
display: flex;
align-items: center;
gap: 8px;
@ -192,38 +192,38 @@
color: var(--text-muted);
}
.cc-statusbar-item {
.pf-statusbar-item {
white-space: nowrap;
}
.cc-statusbar-sep {
.pf-statusbar-sep {
color: var(--text-faint);
user-select: none;
}
.cc-statusbar-clickable {
.pf-statusbar-clickable {
cursor: pointer;
border-radius: 3px;
padding: 1px 4px;
transition: background 0.15s ease, color 0.15s ease;
}
.cc-statusbar-clickable:hover {
.pf-statusbar-clickable:hover {
background: var(--background-modifier-hover);
color: var(--text-normal);
}
.cc-statusbar-tokens.is-warning {
.pf-statusbar-tokens.is-warning {
color: var(--text-warning, #e0a526);
font-weight: 600;
}
/* Generator preview pane */
.cc-preview-section {
.pf-preview-section {
margin-top: 12px;
}
.cc-preview-body {
.pf-preview-body {
border: 1px solid var(--background-modifier-border);
background: var(--background-secondary);
border-radius: 4px;
@ -232,7 +232,7 @@
padding: 10px;
}
.cc-preview-code {
.pf-preview-code {
font-family: var(--font-monospace);
font-size: 11px;
white-space: pre-wrap;
@ -241,7 +241,7 @@
margin: 0;
}
.cc-preview-line-info {
.pf-preview-line-info {
font-size: 11px;
color: var(--text-muted);
font-style: italic;
@ -251,20 +251,20 @@
/* Stack on narrow viewports */
@media (max-width: 768px) {
.cc-gen-modal {
.pf-gen-modal {
width: 90vw;
}
.cc-gen-layout {
.pf-gen-layout {
grid-template-columns: 1fr;
}
.cc-gen-selection {
.pf-gen-selection {
border-right: none;
border-bottom: 1px solid var(--background-modifier-border);
padding-right: 0;
padding-bottom: 16px;
max-height: none;
}
.cc-gen-zone {
.pf-gen-zone {
max-height: none;
}
}