Hermes Desktop Documentation

repository·main·Indexed 24 days ago

https://github.com/dodo-reach/hermes-desktop

A native macOS companion for the Hermes Agent providing a machine-first workbench to manage sessions, workflows, Kanban boards, and files. It supports both local operation on macOS 14+ and remote management via non-interactive SSH hosts, reading data directly from the active connection and profile.

Tokens
11.5K
Snippets
26
Records
73
Agent score
84%

What's inside Hermes Desktop

  1. SwiftTerm Features Overview

    main

    SwiftTerm supports a wide range of terminal capabilities:

    • Rendering: Unicode (Emoji, combining characters, grapheme clusters), ANSI, 256-color, and TrueColor. Optional GPU-accelerated rendering via Metal.
    • Text Attributes: Bold, italic, underline, strikethrough, dim/faint, blink, and inverse.
    • Graphics: Sixel, iTerm2-style inline images, and Kitty graphics protocol.
    • Input & Interaction: Mouse event reporting (X10, SGR, UTF-8, URxvt), terminal resizing, and hyperlink support (OSC 8).
    • Search & Selection: Built-in macOS find bar and programmable search APIs.
    • Session Management: Terminal session recording and playback with termcast.
  2. Overview of Graphics Support in SwiftTerm

    main

    SwiftTerm supports three inline graphics protocols that allow terminal applications to display images directly in the terminal output. Depending on the protocol used, the data is delivered to the front-end in different formats (raw RGBA pixels vs. encoded image data like PNG/JPEG).

    Supported protocols:

    • Sixel: An older protocol encoding images as six-pixel-tall rows. Delivered as raw RGBA pixel data.
    • iTerm2 Inline Images: Uses OSC 1337 to transmit Base64-encoded image data. Supports dimension specifications and aspect ratio preservation.
    • Kitty Graphics Protocol: The most advanced protocol. Supports chunked transmission, image referencing by ID, arbitrary positioning with z-ordering, virtual placements, and sub-image cropping.
  3. Connect a terminal to a custom data source (SSH, Sockets, etc.)

    main

    To connect SwiftTerm to a non-local data source like an SSH connection or a network socket, use TerminalView directly and implement the TerminalViewDelegate.

    The Core Pattern:

    • Outgoing Data: Implement TerminalViewDelegate/send(source:data:) to forward user keystrokes/input from the terminal to your backend (e.g., an SSH channel).
    • Incoming Data: When your backend receives data from the remote host, call TerminalView/feed(byteArray:) to display it in the terminal.

    This pattern works for both macOS (AppKit) and iOS (UIKit).

    class MyTerminalController: NSViewController, TerminalViewDelegate {
        var terminalView: TerminalView!
    
        override func viewDidLoad() {
            super.viewDidLoad()
            terminalView = TerminalView(frame: view.bounds)
            terminalView.terminalDelegate = self
            view.addSubview(terminalView)
        }
    
        func send(source: TerminalView, data: ArraySlice<UInt8>) {
            // Send data to your backend (SSH channel, socket, etc.)
        }
    
        // Feed incoming data from the backend into the terminal:
        func onDataReceived(_ data: ArraySlice<UInt8>) {
            terminalView.feed(byteArray: data)
        }
    
        func sizeChanged(source: TerminalView, newCols: Int, newRows: Int) {}
        func setTerminalTitle(source: TerminalView, title: String) {}
        func hostCurrentDirectoryUpdate(source: TerminalView, directory: String?) {}
        func scrolled(source: TerminalView, position: Double) {}
        func requestOpenLink(source: TerminalView, link: String, params: [String: String]) {}
        func clipboardCopy(source: TerminalView, content: Data) {}
        func rangeChanged(source: TerminalView, startY: Int, endY: Int) {}
    }
  4. How the Terminal class works

    main

    The Terminal class is the core VT100/Xterm terminal emulation engine. It manages the terminal buffer, processes escape sequences, tracks cursor state, and notifies a TerminalDelegate of events.

    Key characteristics:

    • UI-Agnostic: It can be used with bundled AppKit/UIKit views, a headless backend, or a custom renderer.
    • Thread-Safe: You can call feed(byteArray:) from a background queue, and the terminal will synchronize internally.
    • Input/Output Flow: All input is provided via the feed(buffer:) family of methods. Output is delivered through the TerminalDelegate/send(source:data:) callback.
  5. Understand Hermes Desktop state and storage

    main

    Data Source of Truth

    Hermes Desktop does not maintain a synchronized mirror of Hermes state. All core data—Sessions, Kanban, cron jobs, files, skills, and usage—is read directly from the active connection and profile on the machine where Hermes is running.

    • Direct-local mode: Uses your current macOS account's Hermes files.
    • SSH mode: Uses the files on the remote host.

    Local App State

    Local preferences and connection details are stored on your Mac under: ~/Library/Application Support/HermesDesktop

    This includes:

    • Connection profiles
    • Pinned sessions
    • Bookmarked files
    • Workflow presets
    • Sidebar order
    • Appearance preferences (terminal font/theme, background images)
  6. Use HeadlessTerminal for programmatic terminal automation

    main

    A HeadlessTerminal is a terminal emulator that runs a local process without a UI. It combines a Terminal engine with a LocalProcess, allowing you to run commands and inspect terminal output (including colors, cursor position, and escape sequences) programmatically. This is ideal for scripting, testing, and automation.

    To interact with the terminal, use the terminal property to read buffer contents. To control the running subprocess, use the process property.

  7. Manage files and workspace edits

    main

    File Browsing

    Hermes Desktop allows you to browse directories on the active Hermes machine and bookmark text files next to the canonical Hermes files. It supports editing text files up to 10 MB.

    Conflict Prevention

    To prevent accidental overwrites, the app performs a check before saving an edited workspace file or skill. If the file on the active Hermes machine has changed since you opened it, the save is blocked and your unsaved edits are preserved until you intentionally reload.

  8. Runtime dependencies for Hermes Desktop

    main

    For Hermes Desktop to function correctly at runtime, the following environment conditions must be met:

    • python3 must be available on the machine.
    • Hermes data must reside in ~/.hermes, a named profile, or a configured custom Hermes home.
    • hermes must be available in the app's prepared PATH (required for in-app chat, terminal resume, and workflow launches).

    Modes of Operation:

    • Direct-local mode: Commands run on the local Mac using the current macOS user's permissions.
    • SSH mode: Requires a working, non-interactive SSH path to the target host already configured on the Mac.
  9. How to wire a terminal view to an SSH channel

    main

    SwiftTerm does not include a built-in SSH library. To connect a TerminalView to a remote host, you must implement a bidirectional data flow pattern between the terminal and your chosen SSH library's channel.

    There are two directions of data flow:

    1. User input to SSH: Capture data from the terminal via TerminalViewDelegate/send(source:data:) and write those bytes to your SSH channel.
    2. SSH output to terminal: When your SSH channel receives data, deliver it to the terminal using TerminalView/feed(byteArray:).

    This pattern is consistent regardless of whether you use swift-nio-ssh, NMSSH, Shout, or BlueSocket.

    ┌──────────────┐   send(data:)    ┌──────────────┐
    │              │ ───────────────▶ │              │
    │ TerminalView │                  │  SSH Channel  │
    │              │ ◀──────────────  │              │
    └──────────────┘  feed(byteArray:) └──────────────┘
  10. Choose the right Hermes chat surface

    main

    Hermes Desktop provides multiple ways to interact with Hermes, depending on your needs. All surfaces run the actual Hermes engine on your selected machine (local or SSH), ensuring a single source of truth.

    • Chat (in Sessions view): Use this for the real Hermes TUI experience embedded in the app. It is a hosted hermes --tui session scoped to your active connection and profile.
    • Transcript (in Sessions view): Use this to inspect persisted history from the host without starting a live TUI session.
    • Terminal (embedded): Use this for heavy work requiring shell control, command approvals, long-running output, or manual review.
    • hermes --tui (CLI): Use this in any standard terminal if you want the Hermes TUI outside of the Hermes Desktop layout.