16 KiB
Requirements - Obsidian Plugin
Automatically export outstanding tasks from Obsidian vault to CSV for ManicTime time tracking.
Overview
An Obsidian plugin that integrates task export functionality directly into Obsidian, providing both on-demand and automatic export capabilities with a native user experience.
Related Repository: markdown-task-export - C# Console Application (Iteration 1)
⚠️ REFERENCE IMPLEMENTATION: This plugin is a port of the working C# console application. Use the C# codebase as a reference:
src/MarkdownParser.cs- Complete parsing logic with all edge casessrc/CsvExporter.cs- CSV generation with compression and header controlsrc/TaskExtractor.cs- Customer/Project extraction and file enumerationsrc/Models/TaskItem.cs- Data structure for tasks
The TypeScript implementation should produce identical CSV output to the C# version.
Functional Requirements
1. Plugin Integration
Obsidian API Integration
- Use Obsidian Plugin API for all file operations
- Register as a community plugin (follows Obsidian guidelines)
- Compatible with Obsidian desktop (Windows, macOS, Linux)
- Minimal performance impact on Obsidian startup/runtime
Plugin Lifecycle
- Load settings on plugin activation
- Initialize file watchers conditionally (based on settings)
- Clean up resources on plugin deactivation
- Save settings changes immediately
2. User Interface Components
Command Palette Commands
- "Export Outstanding Tasks" - Trigger manual export
- "Toggle Auto-Export" - Enable/disable automatic mode
- "Open Export Settings" - Jump to settings panel
Ribbon Icon
- Add icon to left sidebar for quick export access
- Visual feedback on click (spinning/loading state)
- Tooltip: "Export Outstanding Tasks"
Status Bar Item
- Display last export timestamp: "Last export: 2 minutes ago"
- Show export status: ✅ success, ⚠️ error
- Clickable to trigger manual export
- Hide when plugin is disabled
Settings Tab
- Custom settings panel under Settings → Plugin Options
- Input fields for all configurable options
- Real-time validation of paths
- Reset to defaults button
Notifications
- Success: "Exported 49 tasks to outstanding_tasks.csv"
- Error: "Export failed: [error message]"
- Optional (configurable): Show/hide notifications
- Duration: 5 seconds (auto-dismiss)
3. Task Detection (Same as Console App)
Task Identification
- Find unchecked tasks:
- [ ] - Ignore completed:
- [x],✅ 2025-11-11 - Support nested/indented tasks
- Multi-line task descriptions
Parsing Logic
- Use same extraction rules as console app (reference:
MarkdownParser.cs) - Extract hierarchical headers (##, ###, ####, etc.) - unlimited depth
- Associate tasks with parent headers
- Handle nested task patterns
- Preserve hierarchy when parent tasks have sub-tasks
Key Parsing Details from C# Implementation:
- Headers start at
##(H2),#(H1) is ignored - Empty header levels are tracked to preserve structure
- Parent tasks (tasks with sub-tasks) become additional header levels
- Indentation-based nesting detection
- Skip tasks with checkmark emojis in the text
4. Export Functionality
Manual Export
- Triggered by user command
- Scans configured Customers folder
- Generates CSV immediately
- Shows progress for large exports (> 50 files)
- Displays notification on completion
Automatic Export
- Triggered by file events (save/modify)
- Debounced to avoid excessive exports (configurable delay)
- Only monitors files in Customers folder
- Runs in background (non-blocking)
- Updates status bar on completion
File Watching
- Monitor Obsidian vault file events:
file-modifiedeventfile-createdevent (if new .md files added)
- Filter events to only
.mdfiles in Customers folder - Implement debouncing (default: 3 seconds)
- Unsubscribe when auto-export disabled
5. Settings Management
Settings Schema
interface TaskExportSettings {
outputPath: string; // CSV output path (relative to vault)
customersFolder: string; // Root customer folder path
autoExport: boolean; // Enable auto-export
exportOnSave: boolean; // Trigger on file save
exportOnModify: boolean; // Trigger on file modify
showNotifications: boolean; // Show export notifications
compressLevels: boolean; // Remove empty hierarchy columns
includeHeader: boolean; // Include CSV header row
debounceDelay: number; // Debounce delay in seconds (1-30)
}
Default Values
- outputPath:
outstanding_tasks.csv - customersFolder:
Customers - autoExport:
false - exportOnSave:
true - exportOnModify:
false - showNotifications:
true - compressLevels:
false - includeHeader:
true - debounceDelay:
3
Settings Persistence
- Saved to
.obsidian/plugins/task-export-plugin/data.json - Load on plugin activation
- Save immediately on change
- Validate on load (use defaults if invalid)
6. CSV Output (Same as Console App)
Format
- Header:
CustomerName,ProjectName,Level1,Level2,Level3,...,Task - Dynamic columns: Unlimited depth support (Level1, Level2, Level3, etc.)
- Compression mode: Optional
compressLevelssetting to remove empty columns- When enabled: Each row only outputs non-empty levels (no padding)
- When disabled: All rows padded to maximum depth with empty columns
- Header control: Optional
includeHeadersetting to exclude header row - Proper CSV escaping (commas, quotes, newlines)
- UTF-8 with BOM encoding for Excel compatibility
CSV Escaping Rules (from C# implementation):
- Wrap in quotes if field contains: comma, quote, newline, or carriage return
- Double any quotes inside the field:
"becomes"" - Example:
Task with "quotes"becomes"Task with ""quotes"""
File Writing
- Use Obsidian's
vault.adapter.write()API (cross-platform compatible) - Atomic write (write to temp, then rename) - optional for reliability
- Handle write failures gracefully
- Output path relative to vault root (mobile-friendly)
- Support absolute paths on desktop only
7. Error Handling
User-Facing Errors
- Invalid paths (show notification)
- Write permissions issues
- No tasks found (info notification)
- File reading errors (skip file, continue)
Developer Errors
- Log to console for debugging
- Don't crash Obsidian
- Provide detailed error messages
- Graceful degradation
Error Recovery
- Retry failed operations once
- Fall back to manual export if auto-export fails
- Clear error state after successful export
Non-Functional Requirements
Performance
Target Metrics
- Plugin activation: < 100ms
- Manual export (100 files): < 2 seconds
- Auto-export after file change: < 500ms
- Memory footprint: < 10MB
- No noticeable UI lag
Optimization Strategies
- Cache parsed file content (invalidate on change)
- Async file operations (don't block main thread)
- Debounce file change events
- Process files in batches if needed
- Only watch configured folder
Compatibility
Obsidian Version
- Minimum: Obsidian 1.0.0
- Tested on latest stable release
- Full API compatibility across all platforms
Platforms (Cross-Platform Support)
- ✅ Windows 10/11
- ✅ macOS 11+
- ✅ Linux (major distributions)
- ✅ Android 8.0+
- ✅ iOS 13+
- ✅ Web version
- One codebase works on all platforms
Platform-Specific Considerations:
- Desktop: Full file system access (can save CSV outside vault)
- Mobile: Limited to vault directory only
- Use Obsidian's Vault API exclusively (not Node.js
fsmodule) - Detect platform with
Platform.isMobile,Platform.isDesktop
Vault Types
- Local vaults
- Synced vaults (Dropbox, OneDrive, iCloud, etc.)
- Git-based vaults
Usability
User Experience
- Intuitive settings interface
- Clear error messages
- Helpful tooltips
- Keyboard shortcuts (optional)
- Minimal clicks to export
Documentation
- README with installation instructions
- Settings descriptions
- Troubleshooting guide
- Example use cases
Security
File Access
- Only read files user has access to
- Only write to configured output path
- Don't expose sensitive file contents
- Validate all user inputs
Data Privacy
- No external network requests
- No telemetry/analytics
- All processing local
- No data leaves user's machine
Technical Requirements
Technology Stack
Development Environment
- Visual Studio Code - Primary IDE
- Microsoft Stack - Preferred tooling where applicable
- Extensions:
- ESLint - Code quality
- Prettier - Code formatting
- TypeScript - Language support
- Obsidian Plugin Dev Tools (if available)
Required
- TypeScript 4.0+
- Obsidian Plugin API (latest)
- Node.js 16+ (development only, not needed by users)
- esbuild (fast bundling, replaces Rollup)
Cross-Platform Compatibility
- ✅ Use Obsidian's Vault API exclusively
- ✅ Use
normalizePath()for path handling - ✅ Use
app.vault.adapter.read()for file reading - ✅ Use
app.vault.adapter.write()for file writing - ❌ Avoid Node.js modules:
fs,path,os(desktop-only) - ❌ Never use absolute paths outside vault on mobile
API Examples:
// ✅ Good - cross-platform
const content = await this.app.vault.adapter.read(filePath);
await this.app.vault.adapter.write(outputPath, csvContent);
const normalized = normalizePath(userPath);
// ❌ Bad - desktop only
import * as fs from 'fs';
fs.readFileSync(filePath);
Optional Libraries
- None required (use vanilla TypeScript/Obsidian API)
- Consider: Built-in CSV generation (no external dependencies)
Project Structure
Directory Layout:
obsidian-task-export-plugin/ ← Repository root
├── .vscode/ ← VS Code settings
│ ├── settings.json
│ └── extensions.json
├── src/ ← All source code here
│ ├── main.ts # Plugin entry, command registration
│ ├── settings.ts # Settings interface and tab
│ ├── exporter.ts # Core export logic
│ ├── parser.ts # Markdown parsing
│ ├── csv-writer.ts # CSV generation
│ ├── file-watcher.ts # File monitoring and debouncing
│ └── types.ts # TypeScript interfaces
├── tests/
│ ├── exporter.test.ts
│ ├── parser.test.ts
│ └── fixtures/ # Test markdown files
├── manifest.json ← Plugin metadata (root level)
├── versions.json ← Version compatibility (root level)
├── package.json ← Dependencies (root level)
├── tsconfig.json ← TypeScript config (root level)
├── esbuild.config.mjs ← Build configuration (root level)
├── styles.css ← Optional styling (root level)
├── .eslintrc.json ← Linting config
├── .prettierrc ← Formatting config
├── README.md
└── LICENSE
Project Structure Rules:
- ✅ All source code in
src/folder - ✅ Configuration files at root level
- ✅ No solution file needed (TypeScript project, not .NET)
- ✅ Use VS Code workspace for development
Build System
Development
npm run dev # Watch mode with source maps
Production
npm run build # Minified build for distribution
Testing
npm test # Run unit tests
npm run test:coverage # Generate coverage report
Build Tool: esbuild (fast, modern bundler)
Plugin Manifest
{
"id": "task-export-plugin",
"name": "Task Export Tool",
"version": "1.0.0",
"minAppVersion": "1.0.0",
"description": "Export outstanding tasks to CSV for time tracking",
"author": "Raoul Jacobs",
"authorUrl": "https://github.com/tailormade-eu",
"isDesktopOnly": false
}
Implementation Details
Core Classes
TaskExportPlugin (main.ts)
- Extends
Pluginclass - Registers commands, ribbon icon, status bar
- Manages file watcher lifecycle
- Handles settings loading/saving
- Reference C#
Program.csfor command-line argument patterns
TaskExportSettings (settings.ts)
- Extends
PluginSettingTab - Builds settings UI
- Validates user inputs
- Saves settings on change
TaskExporter (exporter.ts)
- Main export orchestration
- File enumeration via Obsidian API
- Calls parser for each file
- Aggregates results
- Writes CSV output
- Reference C#
TaskExtractor.csfor logic
MarkdownParser (parser.ts)
- Parses markdown content
- Extracts headers and tasks
- Maintains hierarchical context
- Returns structured data
- Port directly from C#
MarkdownParser.cs- proven logic with all edge cases
CsvWriter (csv-writer.ts)
- Formats data as CSV
- Handles escaping (use RFC 4180 standard)
- Writes to file via Obsidian API
- Implements compression mode
- Port directly from C#
CsvExporter.cs
FileWatcher (file-watcher.ts)
- Subscribes to file events
- Implements debouncing
- Filters relevant files
- Triggers exports
State Management
Plugin State
- Current settings
- Last export timestamp
- Export in progress flag
- Cached file content (optional)
No Persistent State Required
- All state derived from vault files
- Settings persisted by Obsidian
Event Handling
File Events
this.registerEvent(
this.app.workspace.on('file-modified', (file) => {
if (shouldExport(file)) {
debouncedExport();
}
})
);
Command Events
this.addCommand({
id: 'export-tasks',
name: 'Export Outstanding Tasks',
callback: () => this.exportTasks()
});
Testing Requirements
Unit Tests
Parser Tests
- Task detection patterns
- Header hierarchy extraction
- Nested task handling
- Edge cases (empty files, no tasks)
CSV Writer Tests
- Proper escaping (commas, quotes)
- Dynamic column generation
- UTF-8 encoding
Exporter Tests
- Customer/Project name extraction
- File enumeration
- Error handling
Integration Tests
Manual Export
- Command execution
- Progress indication
- Notification display
- File writing
Auto Export
- File watching activation
- Debouncing behavior
- Background processing
Test Fixtures
Sample vault structure:
test-vault/
├── Customers/
│ ├── Customer A/
│ │ └── Project 1.md
│ └── Customer B/
│ └── Project 2.md
└── outstanding_tasks.csv
Sample markdown files with:
- Various task patterns
- Different header structures
- Special characters
- Nested tasks
Publishing Requirements
Obsidian Community Plugin Submission
Required Files
manifest.json- Plugin metadatamain.js- Compiled plugin codestyles.css- Optional stylingREADME.md- DocumentationLICENSE- Open source license (MIT recommended)
Review Criteria
- Code quality and security
- No external network requests
- Proper error handling
- Clear documentation
- Follows Obsidian guidelines
Submission Process
- Create GitHub repository
- Add plugin to Obsidian community plugins list (PR)
- Wait for review and approval
- Plugin listed in Obsidian's plugin browser
Release Process
Version Tagging
- Follow semantic versioning:
v1.0.0 - Create GitHub release with:
- Release notes
- Attached
main.js,manifest.json,styles.css
Changelog
- Maintain
CHANGELOG.md - Document breaking changes
- List new features and fixes
Success Criteria
The plugin is successful if it:
- ✅ Installs and activates without errors
- ✅ Correctly exports all unchecked tasks from test vault
- ✅ Auto-export works reliably with file changes
- ✅ Settings persist across Obsidian restarts
- ✅ No performance impact on Obsidian UI
- ✅ Handles errors gracefully without crashing
- ✅ Compatible with latest Obsidian version
- ✅ CSV validates successfully in ManicTime
- ✅ Has 80%+ code coverage in tests
- ✅ Passes Obsidian plugin review (if submitted)
Future Enhancements (Out of Scope for v1)
- Mobile support (iOS/Android)
- Export templates (custom CSV formats)
- Multiple output formats (JSON, XML)
- Task filtering (by date, tags, priority)
- Statistics dashboard
- Direct ManicTime API integration
- Scheduled exports (daily, weekly)
- Export history viewer
- Task completion tracking
- Custom task patterns (beyond
- [ ])