Skip to content

Comments

Add auto-release on push to main for BRAT#531

Closed
ki-cooley wants to merge 48 commits intoglowingjade:mainfrom
ki-cooley:feature/brat-release
Closed

Add auto-release on push to main for BRAT#531
ki-cooley wants to merge 48 commits intoglowingjade:mainfrom
ki-cooley:feature/brat-release

Conversation

@ki-cooley
Copy link

@ki-cooley ki-cooley commented Feb 17, 2026

Summary

  • Triggers release workflow on push to main (in addition to tags)
  • Auto-generates version tags as {manifest_version}-{short_sha}
  • Attaches main.js, manifest.json, styles.css as release assets for BRAT compatibility

Test plan

  • Merge to main and verify a GitHub release is created
  • Install via BRAT using ki-cooley/claudsidian

🤖 Generated with Claude Code

Summary by CodeRabbit

Release Notes

  • New Features

    • Integrated Claude-backed backend agent for enhanced AI interactions.
    • Added activity tracking UI displaying tools, searches, and file operations in real-time.
    • Introduced edit history with undo/revert functionality for vault changes.
    • Added support for external resource directories.
    • Improved mobile keyboard handling in chat input.
    • Added collapsible code block display.
  • Bug Fixes

    • Enhanced auto-scroll detection to distinguish user scrolling from programmatic updates.
    • Improved conflict detection for concurrent file modifications.
  • Documentation

    • Added comprehensive project architecture and development guide.
  • Chores

    • Rebranded plugin from Smart Composer to Claudsidian.
    • Updated CI/CD pipeline and deployment configurations.
    • Updated Node.js support (18.x → 20.x).

claude and others added 30 commits January 7, 2026 05:45
Implements the backend WebSocket server that:
- Connects to Claude API with streaming support
- Exposes vault operation tools (read, write, search, list, delete)
- Uses bidirectional RPC protocol for vault operations
- Supports token-based authentication
- Includes Dockerfile for Railway deployment

The backend acts as a bridge between the Obsidian plugin and Claude,
handling the agent loop and tool execution.
- Add MOCK_MODE environment variable for testing without API key
- Add mock agent that simulates Claude responses with tool usage
- Add automated test suite with 6 tests covering:
  - Simple prompt/response streaming
  - vault_list, vault_search, vault_read, vault_write tools
  - Ping/pong keepalive
- Add interactive test client for manual testing
- Update package.json with dev:mock and test scripts

All tests pass: 6/6
- Add railway.toml at repo root to point to backend/Dockerfile
- Update Dockerfile to build from repo root context
- Build TypeScript inside container instead of expecting pre-built dist/
- Add /health and / endpoints that return JSON status
- Attach WebSocket server to HTTP server
- Update Dockerfile health check to use /health endpoint
- Set buildContext = 'backend' in railway.toml
- Fix Dockerfile COPY paths to be relative to backend dir
- Update healthcheckPath to /health
Implements additional Claude Agent SDK-like tools for more powerful
vault operations:
- vault_edit: Precise string replacement in files
- vault_grep: Regex search across file contents with line numbers
- vault_glob: File pattern matching with glob syntax
- vault_rename: Move/rename files with link updates

Also adds UI formatting for new tool results with clickable wikilinks.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Loads CLAUDE.md from vault root for project-specific instructions
- Loads .claude/instructions.md as alternative location
- Loads custom skills from .claude/skills/*.md
- Skills can be invoked by name (e.g., "/weekly-review")
- Updates system prompt with new tool capabilities

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add model field to PromptMessage protocol
- Pass selected model from BackendProvider to WebSocket
- Backend agent now uses model from request instead of hardcoded default
- Default still falls back to claude-opus-4-5-20250514 if not specified

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- claude-opus-4-5-20251101 (was 20250514)
- claude-sonnet-4-5-20250929
- claude-haiku-4-5-20251001
- claude-opus-4-1-20250805

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Collapsed file lists: show first 3 files with "+N more" instead of full lists
- Edit batching: suppress duplicate edit messages within 5 second window
- Clean up temp test scripts and debug files
- Add ConflictManager and instance singleton for backend
- Update various UI components for better integration

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Backend:
- Enable built-in Anthropic web_search tool for real-time web access
- Update system prompt to mention web search capability

Frontend:
- Add enterKeyHint="send" for mobile keyboard submit button
- Blur input after submit to hide mobile keyboard
- Add code block truncation (15 lines) with expand/collapse

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Enables the backend to connect to external MCP servers via SSE transport,
discover their tools, and forward tool calls from Claude. This allows
cookbook search tools (and any future MCP servers) to work through the
backend provider, which is required for mobile support.

- New src/mcp-client.ts: MCP client manager using @modelcontextprotocol/sdk
- Modified agent.ts: merges MCP tools with vault tools, routes tool calls
- Modified index.ts: initializes MCP client after server starts (non-blocking)
- Added @modelcontextprotocol/sdk dependency

Configured via MCP_SERVERS env var (JSON):
  {"server-name":{"type":"sse","url":"https://example.com/mcp/sse"}}

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace @anthropic-ai/sdk + manual agent loop with @anthropic-ai/claude-agent-sdk.
SDK's query() handles tool execution, message history, and MCP connections
automatically. Auth now supports CLAUDE_CODE_OAUTH_TOKEN (subscription) or
ANTHROPIC_API_KEY. Default model updated to claude-opus-4-6.

- Rewrite agent.ts: replace manual streaming loop with SDK query()
- New vault-tools.ts: Zod v4 schemas + tool() + createSdkMcpServer()
- Delete mcp-client.ts (SDK handles MCP connections internally)
- Delete mcp-tools.ts (replaced by vault-tools.ts)
- Update index.ts: remove MCP client init, dual auth check
- Upgrade zod ^3.23 → ^4.0 (Agent SDK peer dependency)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The Agent SDK CLI requires git at runtime. Also set HOME=/tmp/claude-home
for writable config directory in Docker, and log full error stacks.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…p diag

- Add stderr callback to query() to capture CLI subprocess errors
- Create /tmp/claude-home/.claude/ in Dockerfile so CLI has writable HOME
- Remove slow startup diagnostic that blocked module load

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The Agent SDK CLI refuses --dangerously-skip-permissions when running
as root. Create a 'claude' user and switch to it before running.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Tool names like "mcp__vault-tools__vault_read" are now cleaned to
just "vault_read" before sending to the plugin. This makes the
activity accordion show meaningful tool names instead of MCP internals.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The SDK handles external MCP tool execution internally, so we never
got tool_end events for tools like search_cookbooks. Now we track
pending tool starts and emit synthetic tool_end events when the SDK
moves to the next turn (text streaming or new assistant message).

This ensures the plugin's activity accordion correctly shows all
tool executions with proper start/end lifecycle.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replaces the old tool message display with a modern activity tracking system:
- ActivityAccordion: collapsible exploration summary (auto-expand during streaming)
- ActivityItem: individual activities with live timers, clickable file links
- EditDiffBlock: green/red diff display with Undo button for file changes
- EditHistory: singleton snapshot manager for revert functionality
- Full support for cookbook search tools (search_cookbooks, list_cookbook_sources)
- ActivityEvent type system with 13 activity types + generic fallback
- BackendProvider emits structured ActivityEvent objects during streaming
- tool-result-formatter parses raw results into structured diff/count/path data
- 320 lines of Obsidian-native CSS with theme variable integration
- Cleaned up debug logging artifacts from main.ts and settings.ts

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…tocol-level

Railway's proxy doesn't forward WebSocket ping/pong frames, causing the
server's protocol-level heartbeat to terminate connections after ~45 seconds.
Now tracks last message activity time and allows 90s of inactivity. The
plugin already sends application-level ping messages every 25s which keep
the connection alive through the proxy.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Tell the agent to always include exact page numbers and source names
when citing cookbook search results, preventing vague references.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Fix activity ID mismatch between BackendProvider and VaultRpcHandler
  that prevented undo from finding the correct snapshot. Track activity
  IDs from tool_start events and consume them in the RPC handler.
- Fix revert for new files: delete file instead of writing empty content.
- Add clickable file links in EditDiffBlock that open files in editor.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…MCP restriction

- Add externalResourceDir plugin setting for vault-relative PDF path
- Fix duplicate activity items by deduplicating editActivities by filePath+type
- Map search_cookbooks/list_cookbook_sources/web_search to proper activity types
- Remove blanket mobile MCP disable; let transports fail gracefully
- Update backend system prompt with source filter and citation format guidance
- Settings migration 12→13

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
ki-cooley and others added 18 commits February 12, 2026 01:21
LLM was stripping [[cookbooks/file.pdf#page=N]] wikilinks and reformatting
as plain text. Updated Cookbook Research Tools section to mark wikilink
preservation as CRITICAL with explicit examples and instructions.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
BackendProvider: Race message promise against abort signal so clicking
Stop immediately wakes the generator and sends cancel to backend.

WebSocketClient: Notify active stream handlers on disconnect so
generators don't hang forever when the connection drops.

server.ts: Send safety-net complete message in finally block so the
client never gets stuck waiting for a terminal event.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
When an external MCP server dies (e.g. cookbook-rag OOM), the SDK's
query() hangs forever waiting for a tool response. This wraps the
iterator with a 2-minute timeout that aborts the agent and yields
an error if no message arrives.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…, stream thinking tokens

- Replace 2-min withMessageTimeout (killed legitimate multi-tool turns) with
  activity-based approach: heartbeat updated by SDK messages, vault tool
  handlers, and stderr; 15s interval check; 5-min inactivity threshold
- Stream thinking_delta tokens in real time (Cursor-like UX)
- Emit tool_start from content_block_start stream events (earlier than
  waiting for full assistant message), with dedup against assistant fallback
- Add heartbeat callback to createVaultMcpServer, called by all 9 vault
  tool handlers on execution

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Revert early tool_start from content_block_start (sent empty input {},
  caused "Cookbook search: ''" in activity UI). Tool_start now emits from
  the assistant message which has the complete input parameters.
- Keep thinking_delta streaming from stream events (real-time thinking)
- Add pending tool cleanup in catch block so cancelled requests don't
  leave stuck "running" activities in the UI
- Remove unused streamStartedToolIds tracking

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Fix 2: Track completeSent flag in server.ts to prevent safety-net
  complete from racing with tool_end events. Delay handler deletion
  in WebSocketClient by 1s after complete.
- Fix 3: Enable extended thinking (budgetTokens: 10000) in SDK query.
  Add diagnostic logging for thinking block start and deltas.
- Fix 4: Increase maxTurns 10→25, inactivity timeout 5→10min,
  RPC timeout 30→60s. Add result logging for timeout diagnosis.
- Add interspersed layout spec doc for future implementation.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…on error

- Remove `thinking: { type: 'enabled', budgetTokens: 10000 }` option that
  was causing the Agent SDK CLI to fail silently (2s empty response + exit 1)
- Track `completedSuccessfully` flag to suppress the spurious "process exited
  with code 1" error the SDK throws after normal completion

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Root cause of empty responses was ANTHROPIC_API_KEY env var on Railway
overriding the working CLAUDE_CODE_OAUTH_TOKEN. The thinking option
itself is fine.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- maxTurns 25→50 to support complex multi-source research queries
- Detect error_max_turns and append truncation notice to response
- Add system prompt guidance: batch tool calls 5-8 at a time, present
  final synthesis instead of repeating findings in multiple formats

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace grouped activity layout (all activities at top, text at bottom)
with chronologically interspersed layout — text and activities appear
in the order they happen during agent execution, like Cursor.

Also restore rendered markdown preview in edit diff blocks with a
Raw/Rendered toggle button, defaulting to rendered view.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Strip [[]] from file names in edit diff headers, activity item links,
and activity accordion labels. The link styling already distinguishes
clickable filenames without needing bracket decoration.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add images field to PromptMessage protocol (both frontend and backend)
- Skip file reading/RAG in PromptGenerator for backend provider — pass
  file paths instead so the agent reads via vault_read
- Extract images from request in BackendProvider, send separately from
  prompt text via WebSocket
- Forward images through server.ts to agent.ts, construct multimodal
  Anthropic content blocks when images are present
- Add console.log tracing for image flow debugging

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Fix image inputs and @ file mentions for backend provider
- Fix streaming auto-scroll: use wheel/touchmove events to detect user
  scrolling instead of scroll events (which also fire on content growth),
  preventing false auto-scroll disable during streaming
- Add persistent memory via .claude/memory.md: auto-create on plugin
  load, load into prompt generator, agent can read/write via vault tools
- Fix dotfile support in VaultRpcHandler: use adapter API for paths
  containing dotfiles (.claude/) since Obsidian vault API doesn't index them
- Add mobile scroll CSS (overscroll-behavior, webkit-overflow-scrolling)
- Wrap autoScrollToBottom in requestAnimationFrame for DOM sync

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add auto-scroll fix, persistent memory, mobile UX, and dotfile support
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@ki-cooley ki-cooley closed this Feb 17, 2026
@coderabbitai
Copy link

coderabbitai bot commented Feb 17, 2026

Caution

Review failed

The pull request is closed.

📝 Walkthrough

Walkthrough

This pull request introduces a comprehensive Node.js backend system with WebSocket communication for the Obsidian Smart Composer plugin, rebrands the project to Claudsidian, adds activity tracking and content block UI components, and integrates a new backend LLM provider type with vault RPC operations.

Changes

Cohort / File(s) Summary
Backend Node.js Server
backend/package.json, backend/tsconfig.json, backend/.env.example, backend/.gitignore, backend/Dockerfile, backend/railway.json, backend/README.md, backend/src/index.ts, backend/src/agent.ts, backend/src/mock-agent.ts, backend/src/server.ts, backend/src/protocol.ts, backend/src/utils.ts, backend/src/vault-tools.ts, backend/test/...
Implements a complete Node.js backend service with WebSocket server, Claude agent integration via SDK, vault tool definitions, RPC protocol handling, Docker/Railway deployment configs, and automated test suite.
Frontend WebSocket & Backend Provider Integration
src/core/backend/WebSocketClient.ts, src/core/backend/BackendProvider.ts, src/core/backend/VaultRpcHandler.ts, src/core/backend/ConflictManager.ts, src/core/backend/EditHistory.ts, src/core/backend/protocol.ts, src/core/backend/tool-result-formatter.ts, src/core/backend/instance.ts
Adds WebSocket client for bidirectional backend communication, implements backend-backed LLM provider, vault RPC handler for Obsidian file operations, conflict detection, edit history tracking, and tool result parsing/formatting.
Activity Tracking & Content Rendering UI
src/components/chat-view/ActivityAccordion.tsx, src/components/chat-view/ActivityItem.tsx, src/components/chat-view/EditDiffBlock.tsx, src/components/chat-view/InterspersedContent.tsx
Introduces Cursor-style activity visualization with live-collapsible accordion, individual activity items with timing, file diffs with undo functionality, and interspersed chronological content block rendering.
Chat Response & Streaming Updates
src/components/chat-view/Chat.tsx, src/components/chat-view/AssistantToolMessageGroupItem.tsx, src/components/chat-view/useChatStreamManager.ts, src/components/chat-view/useAutoScroll.ts, src/utils/chat/responseGenerator.ts, src/utils/chat/promptGenerator.ts
Updates streaming response handling to support activity events and content blocks, implements interspersed rendering path, refines auto-scroll logic for user vs. programmatic scrolling, adds backend provider prompting, and integrates persistent memory.
Chat Input & Markdown Components
src/components/chat-view/chat-input/ChatUserInput.tsx, src/components/chat-view/chat-input/LexicalContentEditable.tsx, src/components/chat-view/chat-input/plugins/template/TemplatePlugin.tsx, src/components/chat-view/MarkdownCodeComponent.tsx, src/components/chat-view/ToolMessage.tsx
Adds image logging in input flow, mobile keyboard send-key hint, unifies slash-command sources (templates/skills/commands), adds code block expansion, and filters backend tool calls from visible UI.
Provider & Settings Configuration
src/constants.ts, src/types/provider.types.ts, src/types/chat-model.types.ts, src/settings/schema/setting.types.ts, src/settings/schema/migrations/12_to_13.ts, src/settings/schema/migrations/index.ts, src/settings/schema/settings.ts, src/core/llm/manager.ts, src/core/mcp/mcpManager.ts
Adds backend provider type with backendUrl and authToken fields, updates default models to backend-agent, creates settings migration for externalResourceDir, and extends LLM provider manager to instantiate BackendProvider.
Settings UI Modals
src/components/settings/modals/AddChatModelModal.tsx, src/components/settings/modals/AddEmbeddingModelModal.tsx, src/components/settings/modals/ProviderFormModal.tsx, src/components/settings/sections/ChatSection.tsx, src/components/settings/sections/ProvidersSection.tsx
Filters backend providers from chat/embedding model selection, adds backend-specific URL and auth token inputs in provider form, adds external resource directory setting, and reworks provider row UI with edit/delete separation.
Type Definitions & Protocols
src/types/chat.ts, src/types/llm/response.ts, docs/interspersed-layout-spec.md, .claude/settings.json
Introduces ActivityEvent and ContentBlock types for activity tracking, extends streaming choices with activity and contentBlock deltas, documents interspersed layout specification, and configures Claude Bash permissions.
Branding & UI Text
manifest.json, src/ChatView.tsx, src/components/modals/ErrorModal.tsx, src/components/modals/InstallerUpdateRequiredModal.tsx, src/components/settings/SettingsTabRoot.tsx
Renames project from Smart Composer to Claudsidian across manifest, display titles, error modal links, support messaging, and UI text.
Project Configuration & Styling
package.json, railway.toml, .github/workflows/release.yml, styles.css, src/hooks/useSkills.ts, src/main.ts, CLAUDE.md
Updates CI/CD workflow for automated release with tag-based versioning, adds comprehensive project documentation, introduces skills/commands loading hook, integrates backend lifecycle management in plugin main, and adds extensive styling for activity UI and interspersed layouts.

Sequence Diagram(s)

sequenceDiagram
    participant User as User Input
    participant Plugin as Obsidian Plugin<br/>(Frontend)
    participant WS as WebSocket Client
    participant Server as Node.js<br/>Backend Server
    participant Agent as Claude Agent
    participant Tools as Vault Tools

    User->>Plugin: Submit prompt + context
    Plugin->>WS: sendPrompt()
    WS->>Server: PromptMessage (via WebSocket)
    Server->>Agent: runAgent(prompt, context)
    Agent->>Agent: Generate response
    Agent->>Tools: Request vault operation
    Tools->>Server: Execute & emit tool_end
    Server->>WS: ToolEndMessage
    WS->>Plugin: onToolEnd() callback
    Plugin->>Plugin: Update activity tracking
    Agent->>Agent: Stream text deltas
    Server->>WS: TextDeltaMessage
    WS->>Plugin: onTextDelta() callback
    Plugin->>Plugin: Update message content
    Agent->>Agent: Complete response
    Server->>WS: CompleteMessage
    WS->>Plugin: onComplete() callback
    Plugin->>Plugin: Finalize assistant message<br/>with activities & content blocks
    Plugin->>User: Display interspersed<br/>content + activities
Loading
sequenceDiagram
    participant Plugin as Plugin
    participant VaultRPC as VaultRpcHandler
    participant RPC as RPC Handler
    participant Vault as Obsidian Vault
    participant History as EditHistory

    Plugin->>RPC: Receive rpc_request<br/>(vault_write, vault_edit, etc)
    RPC->>VaultRPC: handleRpc(method, params,<br/>activityId)
    alt Vault Write Operation
        VaultRPC->>History: recordBefore(path,<br/>content, activityId)
        History->>History: Save snapshot
        VaultRPC->>Vault: Create/modify file
        Vault-->>VaultRPC: Success
    else Vault Read Operation
        VaultRPC->>Vault: Read file content
        Vault-->>VaultRPC: Content
    end
    VaultRPC-->>RPC: Tool result
    RPC-->>Plugin: rpc_response
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~75 minutes

Possibly related PRs

Suggested reviewers

  • kevin-on

Poem

🐰 A rabbit hops through backend gates,
Where WebSockets and agents collaborate,
Claudsidian blooms with activities bright,
Interspersed content in Cursor's delight,
The vault now speaks through RPC streams!

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants