Feature updates#77
Conversation
Research and spec document for bringing GitHub Issues into Ledger. Includes: - Full gh CLI command reference and JSON output fields - TypeScript interface definitions - IPC API design following PR service patterns - UI wireframes for list and detail panels - Implementation plan with phased approach - Integration points with branches, PRs, and commits
Research and incorporate design patterns from Taska (taska.now), a native Mac app for GitHub/GitLab issues: - Inline editing (title, assignees, labels on one line) - Multi-select bulk edit with Inspector panel - Priority as first-class citizen (P1-P4, Agile, Simple systems) - Grouping by milestone/label/assignee - Live search with debounced as-you-type - Quick actions (checkbox to close, etc.) Updated implementation plan to 5 phases with Taska-inspired features.
New feature for non-developers to quickly create GitHub issues: - macOS menu bar icon with open issue count badge - Click to open minimal popover with auto-screenshot - Single text field for description, quick label/priority pickers - Submit creates issue and shows notification - Global keyboard shortcut (⌘+Shift+I) Future extensibility: - Linear tickets via linear CLI - Notion pages via API - Jira issues via CLI/API - TicketProvider abstraction layer Added Phase 6 & 7 to implementation plan and new files to create.
Add full GitHub Issues support following the existing PR implementation pattern: - Service layer: issue functions in git-service.ts using gh CLI - IPC handlers: registerIssueHandlers with conveyor typed IPC - API layer: IssueApi class for renderer process - UI components: IssueList and IssueDetailPanel - Types: Issue, IssueDetail, IssueComment interfaces - Canvas integration: issue handlers, data, and selection state Features: - List issues with state/search/sort filters - View issue details with body, comments, linked PRs - Close/reopen issues with reason selection - Add comments to issues - Create development branches from issues - Priority detection from labels (P1-P4, agile systems) - Label display with GitHub colors
Implement the Quick Capture feature from the Issues spec - a macOS menu bar widget for fast issue creation: Infrastructure: - lib/main/tray.ts: Electron Tray with programmatic ticket icon, click handlers - lib/main/quick-capture-window.ts: Popover BrowserWindow with vibrancy - lib/services/quick-capture/: Service layer for screenshots and issue creation IPC: - lib/conveyor/handlers/quick-capture-handler.ts: IPC handlers for quick capture - lib/preload/quick-capture-preload.ts: Minimal preload exposing quickCapture API UI: - app/quick-capture/QuickCaptureApp.tsx: React component with: - Auto-screenshot capture on open - Single text field (first line = title, rest = body) - Repository selector dropdown - Quick label/priority selection - Keyboard shortcuts (Cmd+Enter submit, Escape close) - app/quick-capture/quick-capture.css: macOS-native styling with dark mode Build: - electron.vite.config.ts: Added quick-capture entries for preload and renderer Features: - Left-click tray icon: Opens quick capture popover - Right-click: Context menu (Open Ledger, Refresh Count, Quit) - Badge: Shows open issue count next to icon - Auto-hide on blur (click outside)
|
@claude review |
|
Claude finished @peterjthomson's task in 2m 29s —— View job PR Review — Feature Updates (GitHub Issues + Quick Capture Tray)
Overall this is a well-structured addition — clean service layer, proper context isolation for the tray window, good use of the conveyor/typed IPC pattern, and solid error handling throughout. A few issues need attention before merging, one of which is a real security bug. 🔴 Critical — Shell Injection in
|
| Severity | Issue |
|---|---|
| 🔴 Critical | Shell injection in createQuickIssue — use safeExec |
| 🔴 Security | XSS in renderMarkdown via unescaped dangerouslySetInnerHTML |
| 🟠 Bug | editIssue label/assignee clearing (--remove-label '') is invalid |
| 🟠 Bug | Screenshot local path embedded in issue body won't upload; leaked temp file on error |
| 🟡 Quality | LabelBadge + detectPriority duplicated; getRecentRepos stub; tray guard missing |
| 🟡 Privacy | autoScreenshot: true by default captures screen on every popover open |
The two 🔴 issues should be fixed before merging. The 🟠 bugs are functional regressions that affect the screenshot and label-editing features. The 🟡 items are lower priority but worth addressing.
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 4 potential issues.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 8ef0d50. Configure here.
| } else { | ||
| // Inline code | ||
| const processed = line.replace(/`([^`]+)`/g, '<code>$1</code>') | ||
| elements.push(<p key={i} dangerouslySetInnerHTML={{ __html: processed }} />) |
There was a problem hiding this comment.
XSS vulnerability via dangerouslySetInnerHTML in markdown renderer
High Severity
The renderMarkdown function inserts user-controlled content (issue bodies and comments from GitHub) using dangerouslySetInnerHTML after only converting backtick-wrapped text to <code> tags. Any HTML in the line — such as <img src=x onerror=alert(1)> — is rendered as live HTML. In an Electron app this is especially dangerous as it could enable code execution via crafted issue or comment content.
Reviewed by Cursor Bugbot for commit 8ef0d50. Configure here.
| let cmd = `gh issue create --title "${options.title.replace(/"/g, '\\"')}"` | ||
|
|
||
| if (options.body) { | ||
| cmd += ` --body "${options.body.replace(/"/g, '\\"')}"` |
There was a problem hiding this comment.
Shell command injection via unescaped metacharacters in execAsync
High Severity
Multiple issue functions construct shell commands via string interpolation with execAsync (which uses child_process.exec, executing through a shell). Only double quotes are escaped (.replace(/"/g, '\\"')), but shell metacharacters like $(), backticks, and \ remain active inside double-quoted strings. Input containing $(command) would trigger command execution. This affects createIssue, editIssue, closeIssue, reopenIssue, and commentOnIssue.
Additional Locations (1)
Reviewed by Cursor Bugbot for commit 8ef0d50. Configure here.
| ))} | ||
| {issue.labels.length > 4 && ( | ||
| <span className="issue-labels-more">+{issue.labels.length - 4}</span> | ||
| )} |
There was a problem hiding this comment.
Label overflow count uses wrong array length
Low Severity
The "+N more labels" indicator uses issue.labels.length (the unfiltered total) for both the threshold check and the overflow count, but the displayed labels come from a filtered array that excludes the priority label. When a priority label exists, the overflow count is off — it may show "+N" when fewer (or zero) labels are actually hidden.
Reviewed by Cursor Bugbot for commit 8ef0d50. Configure here.
| } from 'lucide-react' | ||
| const GitHubIcon = ({ size = 24 }: { size?: number }) => ( | ||
| <svg width={size} height={size} viewBox="0 0 24 24" fill="currentColor"><path d="M12 2C6.477 2 2 6.477 2 12c0 4.42 2.865 8.17 6.839 9.49.5.092.682-.217.682-.482 0-.237-.009-.866-.013-1.7-2.782.604-3.369-1.34-3.369-1.34-.454-1.156-1.11-1.463-1.11-1.463-.908-.62.069-.608.069-.608 1.003.07 1.531 1.03 1.531 1.03.892 1.529 2.341 1.087 2.91.831.092-.646.35-1.086.636-1.336-2.22-.253-4.555-1.11-4.555-4.943 0-1.091.39-1.984 1.029-2.683-.103-.253-.446-1.27.098-2.647 0 0 .84-.269 2.75 1.025A9.578 9.578 0 0112 6.836c.85.004 1.705.115 2.504.337 1.909-1.294 2.747-1.025 2.747-1.025.546 1.377.203 2.394.1 2.647.64.699 1.028 1.592 1.028 2.683 0 3.842-2.339 4.687-4.566 4.935.359.309.678.919.678 1.852 0 1.336-.012 2.415-.012 2.743 0 .267.18.578.688.48C19.138 20.167 22 16.418 22 12c0-5.523-4.477-10-10-10z"/></svg> | ||
| ) |
There was a problem hiding this comment.
Duplicate GitHubIcon component across two files
Low Severity
The GitHubIcon SVG component is defined identically in both PluginSettingsPanel.tsx and RepositoryManagerPanel.tsx (replacing the removed Github import from lucide-react). This duplicated component could be extracted into a shared icon utility to avoid maintaining two copies.
Additional Locations (1)
Reviewed by Cursor Bugbot for commit 8ef0d50. Configure here.


Note
Medium Risk
Adds new main-process IPC and
ghCLI execution paths plus a persistent macOS tray window, which can affect app stability and security boundaries if misconfigured. Most changes are additive but touch core app refresh/repo switching and new renderer/preload entrypoints.Overview
Adds GitHub Issues integration end-to-end: new typed
Issuemodels and IPC channels, main-processgh-backed issue operations (list/detail/comments/create/edit/close/reopen/comment/develop-branch), and new UI panels (IssueList,IssueDetailPanel) wired into the canvas system and app refresh flow.Introduces a macOS menu-bar tray with a
Quick Capturepopover (separate renderer + preload + IPC handlers) to create issues quickly, optionally auto-capturing/retaking a screenshot, and shows an open-issue count badge viagh.Includes small UX/refactor tweaks: centralizes repo-switch state reset/open logic in
App, allows renaming custom canvas column labels in Settings, and replaceslucide-reactGithubicon usage with an inlineGitHubIconSVG.Reviewed by Cursor Bugbot for commit 8ef0d50. Bugbot is set up for automated code reviews on this repo. Configure here.