Round 2 of Obsidian scanner fixes:
- Timer functions: window.setTimeout/clearTimeout (per scanner) instead of activeWindow.*
- utils/shell.ts: window.require instead of globalThis.require for Electron access
- Rename options.global -> options.globalInstall to bypass false-positive linter warning
- CSS: remove 8 !important rules via specificity bumps; merge 3 duplicate selectors
- eslint config: hoist ignores block (web/, assets/, scripts/, main.js)
Release workflow:
- .github/workflows/release.yml triggers on semver tag push
- Builds, signs main.js/manifest.json/styles.css with GitHub OIDC attestation
- Creates or updates release with the three signed assets
Surface deep link as primary install path:
- README + landing CTAs: "Open in Obsidian" (obsidian://show-plugin?id=agentfiles) primary, community page secondary
- Docs Installation: deep link first, community page as scorecard-first alternative
- README: surface community.obsidian.md/plugins/agentfiles + website + latest release at the top
- Replace "coming soon" install section with the new Add to Obsidian flow + deep link + manual fallback
- Landing CTAs now point to the canonical community page (scorecard + Add to Obsidian button)
- Docs Installation section rewritten around the community page, deep link, then manual
- Fix stale obsidian-agent-skills references in nav, footer, docs, and changelog
- Add 0.7.3 changelog entry
- Bump minAppVersion to 1.7.2 (Workspace.revealLeaf requirement)
- Type all JSON.parse + GitHub/skills.sh API responses
- Fix discriminated union narrowing in store filters (skill + conversation)
- Replace electron shell imports with typed utils/shell.ts helper
- Use createSvg instead of document.createElementNS for SVG creation
- Use activeWindow.setTimeout/clearTimeout and activeDocument for popout window compat
- Replace setTimeout(...,0) bootstrap with workspace.onLayoutReady
- Fix updateMenuBtn typo (renamed to updateMenuBtnState)
- onOpen/onClose return Promise<void> to match ItemView API
- Add createSvg/activeWindow/activeDocument to eslint globals
Swap plain textarea for standalone CM6 instance with line numbers,
syntax highlighting, fold gutters, and spec-compliant frontmatter
linting. Proper lifecycle cleanup on skill switch to prevent DOM leaks.
Both findSkillkitBin() and buildPath() now search additional package
manager directories. A dynamic fallback (pnpm/yarn/npm bin -g) runs
only when static paths find nothing, keeping the common case zero-cost.
Closes#18
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
- Replace old deep-toggle and menu-btn with shared as-conv-icon-btn
- Convert native Menu to custom dropdown with sort/filter sections
- Add has-active filled state for toggle feedback
- Remove dead CSS for as-deep-toggle and as-list-menu-btn
- Add sort toggle (recent/messages) and date range filter (1d/7d/30d/90d/all)
- Add tag multi-select dropdown with outside-click dismiss
- Move tag filtering from sidebar to inline toolbar
- Remove sidebar Tags section (now accessible via dropdown)
- Default to "today" date range on open
- Fix layout shift: render all 3 action buttons always, disable tag when loading
- Fix dropdown mutex: only one dropdown open at a time
Critical fixes:
- Async parser with streaming for large files (>5MB use readline)
- 500 line cap per file, batched processing (20 concurrent)
- Path traversal guard in saveToVault (resolve + startsWith check)
- sanitizeFilename strips '..' sequences
- renderComponent moved to instance field (no module-level leak)
Behavior fixes:
- Search now includes message content
- messageCount counts all messages, not just human turns
- Save requires message selection (no silent 10-msg fallback)
- readableProjectName uses last 2 path segments (more robust)
- Loading state shown during async refresh
- promptAddTag uses createEl instead of document.createElement
- typescript tag uses /typescript/i instead of /.ts\b/
- Removed dead firstMessage field from ConversationItem
Add CSS for conversation UI components: date group headers, conversation
cards with project badges and tag pills, message bubbles with role
indicators, selection state, tool call badges, save-to-vault bar,
resume command block, and custom tag input. Follows existing design
system using Obsidian CSS variables.
- main-view: add wrapper-based panel swapping to reuse grid cells for
both skill and conversation panels. Wire ConversationStore lifecycle,
toggle method, and event subscriptions
- sidebar: add Conversations entry to library section with message-circle
icon. Render project and tag filters when in conversation mode. Handle
mutual exclusion with dashboard and marketplace views
- ConversationListPanel: searchable list grouped by date with project
badges, auto-tags, favorite indicators, and message count
- ConversationDetailPanel: full message preview with markdown rendering,
per-message selection checkboxes for export, custom tag management,
save-to-vault action, and copy-resume-command button
- parser: reads ~/.claude/projects/*/*.jsonl files, extracts human and
assistant messages with timestamps and tool calls, deduplicates by
content hash
- tagger: auto-generates tags from user messages based on technology
mentions (3+ hits required), task type patterns (2+ hits), and MCP
tool calls. Strips <system-reminder> blocks to avoid false positives.
Only analyzes first 5 user messages to prevent meta-discussion noise
- store: reactive ConversationStore extending Obsidian Events with
filtering by project/tag/favorites/search. Persists custom tags and
favorites to ~/.claude/agentfiles-conversations.json
- note-exporter: generates Obsidian-compatible markdown notes with
YAML frontmatter, selected message snippets, and resume command
Add TypeScript interfaces for the conversation explorer feature:
- ConversationItem: represents a parsed Claude Code session
- ConversationMessage: individual message with role, text, timestamp
- ConversationFilter: union type for sidebar filtering
- ConversationTagData: persistence model for custom tags and favorites
- Replace 3 confusing icon buttons with 2 clear controls
- Deep search toggle: uses safe "file-search" icon, clear active state
- Filter+sort merged into one "sliders-horizontal" button that opens
Obsidian's native Menu with checkmarks for sort mode and filter
- Button highlights when filter or non-default sort is active
- Removes custom dropdown CSS in favor of native Menu component
- Fixes invisible icon bug (arrow-down-a-z not in all Obsidian versions)
Create modal now uses a 3-step flow:
1. Tool grid with real SVG icons and brand colors
2. Type cards (skill/command/agent) - skipped if tool has only one type
3. Name input with tool badge, monospace input, colored submit button
Also adds Amp (3 lightning bolts from official press kit) and
Antigravity (Google "A" arch shape) SVG icons to tool-icons.
- New "Create" button in sidebar below Marketplace
- Modal with name input + target dropdown (agent + type)
- Creates SKILL.md in directory for skills, flat .md for commands
- Auto-refreshes store and selects the new skill after creation
- Slugifies name for filesystem, validates for duplicates
Closes#17
The sidebar install prompt said `npm i -g skillkit` which installs
rohitg00's security scanner instead of `@crafter/skillkit` (our
analytics CLI). This caused `skillkit scan` to fail on Windows
because the wrong package requires a <path> argument.
scanDirectoryWithSkillMd only checked one level, missing grouped
structures like ~/.agents/skills/<group>/skills/<name>/SKILL.md
Now recurses into subdirs that don't contain SKILL.md, up to depth 3.
Also includes skillkit binary validation (isCrafterSkillkit).
Closes#16