sidecar

repository·main·Indexed 21 days ago

https://github.com/marcus/sidecar

A terminal-based development workflow orchestrator and TUI dashboard designed for use with AI coding agents. It integrates task management via TD, Git operations, workspace management, and a unified conversation history for agents such as Claude Code, Cursor CLI, and GitHub Copilot CLI. Sidecar provides a system of 'skills' for AI agents to execute actionable workflows and includes plugins for monitoring tasks, managing isolated development environments, and tracking AI session history.

Tokens
89.2K
Snippets
197
Records
360
Agent score
77%

What's inside sidecar

  1. Overview of the Conversations Plugin

    main

    The Conversations plugin allows you to browse, search, and analyze AI coding sessions from various agents in a unified interface. It provides a two-pane layout:

    • Left pane: A session list with search and filtering capabilities.
    • Right pane: A message detail view with expandable turns and analytics.
    • Draggable divider: Allows you to resize the panes.

    Key features include session analytics (model usage, file impacts, tool counts), incremental updates that watch for new messages in real-time, and support for multiple AI agents.

  2. Understand the Embedded Terminal Audit and Feature Gaps

    main

    The Embedded Terminal Audit document outlines current limitations, bugs, and architectural recommendations for the sidecar terminal implementation. Key areas of concern include:

    • Interaction Issues: Lack of keyboard scrolling in interactive mode, missing scroll position indicators, and limited selection gestures (missing double-click, triple-click, and rectangular selection).
    • Performance & Reliability: High CPU usage due to continuous polling, potential data races in forwardClickToTmux, and slow scrolling performance.
    • Feature Gaps: No search functionality in scrollback, limited scrollback depth (500 lines vs tmux's potential 10,000), and lack of clickable URLs or file paths (path:line) in terminal output.
    • UI/UX: The terminal panel is treated as a 'second-class citizen' compared to the main workspace, and there is no visible indication of whether the application or the child app (e.g., tmux) owns the mouse.
  3. Overview of the Worktree Manager Plugin

    main

    The Worktree Manager Plugin is a sidecar plugin designed to orchestrate git worktrees for use with AI coding agents (such as Claude Code, Codex, Aider, or Gemini). It enables developers to run multiple agents in parallel on different features by providing isolated development environments.

    Key capabilities include:

    • Isolated Parallel Development: Uses git worktrees to prevent branch conflicts during concurrent agent tasks.
    • Process Isolation: Runs agents within tmux sessions.
    • Unified Monitoring: Provides a Terminal User Interface (TUI) to monitor all active agents.
    • Task Integration: Integrates with td for task tracking and handoffs.
  4. Configure Diff View Modes

    main

    You can toggle between two different ways of viewing code changes by pressing v:

    1. Unified: The traditional view showing changes inline.
    2. Side-by-side: A comparative view showing the 'Before' and 'After' versions in adjacent columns.

    Your preferred mode is persisted across sessions.

      function calculate() {
    -   return x + y;
    +   return x * y;
      }
  5. Communicate between plugins using the Event Bus

    main

    Plugins can interact with each other using a central Event Bus or by triggering commands that focus other plugins.

    1. Subscribing to Events: In your plugin's Init method, you can subscribe to specific event strings (e.g., git:status-changed) to trigger internal refreshes.

    2. Publishing Events: Use ctx.EventBus.Publish(topic string, data interface{}) to broadcast information to other plugins (e.g., worktree:agent-status).

    3. Navigating to other Plugins: You can programmatically switch focus to another plugin using app.FocusPlugin(name) combined with specific messages (e.g., filebrowser.NavigateToFileMsg or gitstatus.ShowDiffMsg).

    // Subscribing to events
    func (p *Plugin) Init(ctx *plugin.Context) error {
        if ctx.EventBus != nil {
            gitEvents := ctx.EventBus.Subscribe("git:status-changed")
            go func() {
                for range gitEvents {
                    // Trigger refresh
                }
            }()
        }
        return nil
    }
    
    // Publishing events
    p.ctx.EventBus.Publish("worktree:agent-status", map[string]interface{}{
        "worktree": wt.Name,
        "status":   wt.Status.String(),
    })
  6. Understand Sidecar's local data access and privacy model

    main
    Sidecar is a local-first terminal application. It operates primarily by interacting with your local filesystem and existing CLI tools. It does not collect telemetry, analytics, or usage tracking, and it does not require accounts or logins. Most data access is read-only, such as reading Git repositories or AI agent session histories, while write operations are typically user-initiated (e.g., editing a file, committing code, or managing notes).
  7. Understand the Conversations Plugin data sources

    main

    The Conversations Plugin surfaces data from several underlying Claude Code files to provide session intelligence and analytics.

    Data from JSONL files

    • message.model: The specific model used for a response (e.g., opus, sonnet, haiku).
    • Session Context: Includes cwd (current working directory), gitBranch, and version.
    • thinking blocks: The agent's internal reasoning (can be expanded/collapsed).
    • Tool Metadata: Includes full input parameters (file paths, content) and toolUseResult (structured output metadata like line counts).
    • Cost Data: cache_creation_input_tokens for tracking cache write costs.
    • Threading: parentUuid for message hierarchy and isSidechain for branched conversation paths.

    Data from ~/.claude/stats-cache.json

    This file provides global usage analytics, including:

    • Global Totals: totalSessions, totalMessages, and firstSessionDate.
    • Daily Activity: Breakdown of messages, sessions, and tool calls per day.
    • Model Breakdown: Token usage (input/output/cache) categorized by model and day.
    • Usage Patterns: hourCounts for peak activity hours and the longest session (ID, duration, and message count).

    Data from ~/.claude/history.jsonl

    Used as a session index containing:

    • Session metadata with associated project paths.
    • Message previews for search functionality.
    • A timestamp index for chronological sorting.
  8. Distinguish between Worktree and Project Switching

    main

    It is important to distinguish between the two types of context switching available in Sidecar:

    FeatureKeybindScopeModal Title
    Worktree SwitcherWWithin the same repository"Switch Worktree"
    Project Switcher@Between different repositories"Switch Project"

    Use W when you want to move between branches/worktrees of your current project, and @ when you want to open a completely different project folder.

  9. Use the TD Monitor plugin

    main

    The TD Monitor integrates with TD, a task management system for AI agents. It helps you monitor the progress of tasks being handled by agents across different context windows.

    Key Features:

    • Display of the currently focused task.
    • Scrollable task list with status indicators.
    • Activity log containing session context.
    • Quick review submission: Press r to submit a review.

    Note: This requires the td CLI to be installed and configured.

  10. How tmux resizing works in Sidecar

    main

    Sidecar does not act as a terminal emulator and does not use SIGWINCH to communicate size changes to child processes. Instead, it uses a declarative model via tmux commands.

    To resize a pane, Sidecar executes tmux resize-window -t <pane> -x W -y H (falling back to resize-pane for older versions). This ensures the child processes inside the tmux session receive the appropriate resize signals internally from tmux.

    Key Requirements for Resizing:

    • Manual Window Size: Before driving sizes from Sidecar, the tmux session must have window-size manual set. This prevents tmux from automatically shrinking the window to match the smallest attached client.
    • Debouncing: To prevent flicker and excessive tmux calls during interactive drags, resizing should be debounced (e.g., 500ms).
    • Verification: After a resize command, it is recommended to verify the new size using tmux display-message '#{pane_width},#{pane_height}' and trigger a fresh content capture to update the display.
    # Conceptual command used by Sidecar
    tmux resize-window -t <pane_id> -x <width> -y <height>
  11. How the embedded terminal works in Sidecar

    main

    Sidecar is not a terminal emulator. Instead, it acts as a poll-based input/output relay using tmux as the PTY (Pseudo-Terminal) backend.

    Input Flow

    When a user presses a key, the following sequence occurs:

    1. The keypress is captured.
    2. MapKeyToTmux maps the key to a tmux command.
    3. A tmux send-keys subprocess is invoked to send the keystroke to the session.

    Output Flow

    To display content, Sidecar follows a polling loop:

    1. Debounce: A 20ms keystroke debounce is applied.
    2. Capture: Sidecar runs tmux capture-pane -p -e -S -600 (to capture the last 600 lines) and tmux display-message #{cursor_x},... via subprocesses.
    3. Update: The OutputBuffer.Update method processes the captured data using a hash gate to prevent unnecessary updates.
    4. Render: The system renders the lines and overlays a glyph to represent the cursor.
    5. Repeat: The loop repeats based on a tea.Tick interval (typically between 50ms and 500ms).

    Implementation Variants

    Sidecar uses four distinct implementations of this polling loop depending on the consumer:

    ConsumerPoll driverBufferCursor
    Workspace agent panescheduleInteractivePoll / pollGenerationworkspace.OutputBufferworkspace.renderWithCursor
    Workspace shell panescheduleShellPollByName / shellPollGenerationworkspace.OutputBufferworkspace.renderWithCursor
    Workspace terminal panelscheduleTermPanelPoll / termPanelGenerationworkspace.OutputBufferworkspace.renderWithCursor
    filebrowser + notes inline edittty.Model.schedulePolltty.OutputBuffertty.RenderWithCursor
    keypress ──► MapKeyToTmux ──► `tmux send-keys` (subprocess)
                                         │
                keystroke debounce (20 ms) ▼
                 `tmux capture-pane -p -e -S -600` (subprocess)
                 `tmux display-message #{cursor_x},…` (subprocess)
                                         │
                            OutputBuffer.Update (hash gate)
                                         │
                          render lines + overlay a ▉ glyph
                                         │
                          tea.Tick(50–500ms) ──► repeat
  12. Manage transitive dependencies during Charm upgrades

    main

    When upgrading Charm UI libraries (like lipgloss or bubbletea), allow Go's module system to handle transitive dependencies automatically. Do not manually pin or bump transitive dependencies.

    Expected Changes

    After running go mod tidy, you should observe the following in your go.mod and go.sum files:

    New dependencies (pulled by lipgloss v2):

    • ultraviolet
    • clipperhouse/displaywidth

    Pruned dependencies:

    • Any v1-only Charm UI libraries (e.g., older versions of glamour).

    Note on x/cellbuf: It may drop from the indirect list but must remain in the direct require list because Sidecar imports it explicitly.