Pimacs User Manual v0.2.0

Pimacs is an Emacs client for Pi Coding Agent. For release history, see the changelog.


Introduction

Pimacs is an Emacs client for Pi Coding Agent. It provides an interactive interface to the Pi Coding Agent directly from Emacs.


Setup

Install the Pi Agent

First, install the Pi agent using npm:

npm install -g --ignore-scripts @earendil-works/pi-coding-agent

Pimacs does not yet support authentication configuration. To configure your provider, run pi in a terminal, then run /login in Pi.

Install pimacs.el

Add the following to your Emacs configuration:

(use-package pimacs
  :ensure t
  :vc (:url "git@github.com:ananthakumaran/pimacs.el.git"
       :rev :newest)
  :commands (pimacs-chat))

Usage

Run M-x pimacs-chat from any file in your project to start a Pimacs chat session. Use a prefix argument (C-u M-x pimacs-chat) to open a transient where you can set a session name and root directory. Setting a root directory starts the chat there instead of using project.el to find the project root. Run M-x pimacs-switch-session to switch between any active chat sessions.

The chat buffer is read-only except for the prompt input area. Use RET to submit a prompt and C-j to insert a newline. Press i from anywhere in the chat buffer to move point to the prompt input area.


Slash Commands

Slash commands support completion in the prompt buffer. Type / and press C-M-i (or any key bound to completion) to see available commands.

In addition to the commands listed below, extension commands, prompt templates, and skills registered with the Pi agent can also be invoked via slash commands. These are fetched automatically from the agent and included in the completion list.

Angle brackets <> denote required arguments, square brackets [] denote optional arguments.

CommandArgumentsDescription
/compact[prompt]Manually compact context, optionally with custom instructions.
/cloneDuplicate the current active branch into a new session.
/copyCopy last assistant message to clipboard.
/cycle-modelCycle through available models.
/cycle-thinking-levelCycle through thinking levels.
/exitQuit pimacs.
/export[file]Export session to HTML.
/forkCreate a new session from a previous user message.
/modelSwitch models.
/name<name>Set session display name.
/newStart a new session.
/quitQuit pimacs.
/reloadReload extensions, skills and prompts.
/resumePick from previous sessions.
/sessionShow session file, ID, messages, tokens, and cost.
/set-auto-compactionSet auto compaction.
/set-auto-retrySet auto retry.
/set-follow-up-modeSet follow-up mode.
/set-steering-modeSet steering mode.
/set-thinking-levelSet thinking level.

File Name Completion

Type @ followed by a partial file path to trigger file name completion in the prompt buffer. The completion backend is controlled by pimacs-file-completion-backend.


Bash

Prefix a command with ! to run it in Bash. Use !! to run a command without adding it to the conversation context.

! echo "hello"

Sending Context

You can send contextual information from any buffer to the Pimacs chat prompt.

CommandDescription
pimacs-send-regionAppend the selected region to the prompt input.
pimacs-send-filenameAppend the current buffer’s filename (prefixed with @) to the prompt input.
pimacs-send-flycheck-errorsAppend the Flycheck errors at point to the prompt input. Falls back to all current errors in the buffer when there are none at point.

Images

You can attach images to your prompt to provide visual context to the agent. Images are displayed as thumbnail previews above the prompt input area and are sent along with your message. The agent may also render images inline in its responses, for example when using the read tool on a file that contains images.

Supported Formats

The following image formats are supported:

  • PNG
  • JPEG
  • GIF
  • WebP

Drag an image file from your file manager and drop it into the Pimacs chat buffer, or paste a supported image from the clipboard via yank-media. To remove an attached image, click on the thumbnail with the mouse, or place point on it and press backspace or delete.


State Lines

The header line displays session context and model information. The mode line displays the current agent state. Customize them with the pimacs-header-line-format and pimacs-mode-line-format defcustoms. Both accept strings and state components; use :spacer to right-align following components.

(setq pimacs-header-line-format
      '(:context_usage :spacer
        (:model face font-lock-function-name-face)))

See pimacs-header-line-format for available components. A component may also be a function that receives the current state plist.

Extension status text can be placed in either state line with a (:status STATUS-KEY ...) component. STATUS-KEY is the key used by the extension’s status update. Text properties after the key customize the status at that placement.

(setq pimacs-header-line-format
      '(:context_usage " " (:status "xyz-status" face font-lock-warning-face)
        :spacer :model))

By default, status text also appears beside the prompt. To display a status only in a state line, add its key to pimacs-status-widget-hidden-keys.

(setq pimacs-status-widget-hidden-keys '("xyz-status"))

Managing Sessions

Use pimacs-switch-session to switch between active Pimacs chat sessions using completion. Use pimacs-list-sessions to display all active chat sessions in a sortable tabulated list. Press RET to visit the session on the current line and g to refresh the list. Select a column header to sort by that column.

Customize the list’s columns and initial sort order with pimacs-list-sessions-table and pimacs-list-sessions-sort-key.


Sandbox

To run Pi inside a sandbox, customize pimacs-executable and pimacs-flags:

(setq pimacs-executable "nono")
(setq pimacs-flags '("run" "--silent" "--profile" "pi" "--allow-cwd" "--" "pi"
                 "--tools" "read,bash,edit,write,grep,find,ls"))

How It Works

Emacs starts Pi in RPC mode. In this setup, Pi handles the agent logic while Emacs provides the user interface. Some features, such as /login and /logout, are not supported because they are not currently exposed through the RPC API.


Keybindings

Chat Buffer Keybindings

KeyCommandDescription
RETpimacs-visit-itemJump to the source location at point; with a prefix argument, open in another window
C-gpimacs-abortAbort the current operation
TAB, C-ipimacs-toggle-sectionToggle visibility of the section at point
n, M-npimacs-goto-next-sectionMove to the next section
Npimacs-goto-next-user-messageMove to the next user message
p, M-ppimacs-goto-previous-sectionMove to the previous section
Ppimacs-goto-previous-user-messageMove to the previous user message
l, M-g lpimacs-goto-last-sectionJump to the most recent section
ipimacs-focus-promptFocus the prompt input field
qpimacs-quit-chatQuit the chat buffer

Prompt Input Keybindings

KeyCommandDescription
C-gpimacs-abortAbort the current operation
M-ppimacs-previous-promptRecall the previous prompt from history
M-npimacs-next-promptRecall the next prompt from history
C-rpimacs-search-promptSearch prompt history
RETwidget-field-activateSend the current prompt
M-RETpimacs-send-prompt-alternateSend the prompt using the alternate streaming behavior
M-g lpimacs-goto-last-sectionJump to the most recent section

Custom Variables

User Option: pimacs-status-widget-hidden-keys nil

Status keys to hide from the default status widget.

Hidden statuses remain available to (:status STATUS-KEY ...) components in pimacs-header-line-format and pimacs-mode-line-format.

User Option: pimacs-file-completion-backend 'project

Completion backend for prefixed file paths in prompts. project uses project-files to list files in the current project. file uses file-name-all-completions to list files under the project root.

User Option: pimacs-prompt-history-max-size 500

Maximum number of prompt history entries to keep.

User Option: pimacs-resume-max-sessions 100

Maximum number of recent sessions to list when resuming a session.

User Option: pimacs-prompt-streaming-behavior 'followUp

Default streaming behavior for prompts.

steer: Queue the message while the agent is running. It is delivered after the current assistant turn finishes executing its tool calls, before the next LLM call.

followUp: Wait until the agent finishes. Message is delivered only when agent stops.

User Option: pimacs-slash-commands
'(("model" pimacs-select-model 0 "Switch models")
  ("new" pimacs-new-session 0 "Start a new session")
  ("reload" pimacs-reload 0 "Reload extensions, skills and prompts")
  ("resume" pimacs-resume 0 "Pick from previous sessions")
  ("compact" pimacs-compact 1 "Manually compact context, optionally with custom instructions")
  ("set-auto-compaction" pimacs-set-auto-compaction 0 "Set auto compaction")
  ("set-auto-retry" pimacs-set-auto-retry 0 "Set auto retry")
  ("session" pimacs-session-stats 0 "Show session file, ID, messages, tokens, and cost")
  ("name" pimacs-set-session-name 1 "Set session display name")
  ("set-thinking-level" pimacs-set-thinking-level 0 "Set thinking level")
  ("cycle-model" pimacs-cycle-model 0 "Cycle through available models")
  ("cycle-thinking-level" pimacs-cycle-thinking-level 0 "Cycle through thinking levels")
  ("set-steering-mode" pimacs-set-steering-mode 0 "Set steering mode")
  ("set-follow-up-mode" pimacs-set-follow-up-mode 0 "Set follow-up mode")
  ("fork" pimacs-fork 0 "Create a new session from a previous user message")
  ("clone" pimacs-clone 0 "Duplicate the current active branch into a new session")
  ("copy" pimacs-copy 0 "Copy last assistant message to clipboard")
  ("export" pimacs-export 1 "Export session to HTML")
  ("quit" pimacs-quit-chat 0 "Quit pimacs")
  ("exit" pimacs-quit-chat 0 "Quit pimacs"))

Alist mapping slash command names to command specs.

Each entry is (NAME COMMAND MAX-ARGS DESCRIPTION) where NAME is the command string without the leading slash, COMMAND is a command symbol, MAX-ARGS is 0 or 1 indicating the number of optional string arguments the command accepts, and DESCRIPTION is a short description string.

User Option: pimacs-insert-tool-args-functions
'(("read" . pimacs--insert-read-args)
  ("write" . pimacs--insert-write-args)
  ("edit" . pimacs--insert-edit-args)
  ("bash" . pimacs--insert-bash-args)
  ("grep" . pimacs--insert-grep-args)
  ("find" . pimacs--insert-find-args)
  ("ls" . pimacs--insert-ls-args))

Alist mapping tool names to inserter functions.

Each entry is (TOOL-NAME . FUNCTION) where FUNCTION is called with ARGS plist to insert formatted tool call arguments.

User Option: pimacs-insert-tool-result-functions
'(("bash" . pimacs--insert-bash-result)
  ("read" . pimacs--insert-read-result)
  ("write" . pimacs--insert-write-result)
  ("edit" . pimacs--insert-edit-result)
  ("grep" . pimacs--insert-grep-result)
  ("find" . pimacs--insert-find-result)
  ("ls" . pimacs--insert-ls-result))

Alist mapping tool names to result inserter functions.

Each entry is (TOOL-NAME . FUNCTION) where FUNCTION is called with (CONTENT DETAILS ARGS) to insert the tool execution result. CONTENT is a list of content items. Use pimacs--insert-content to render it, or pimacs--content-text to extract text from content.

User Option: pimacs-visit-tool-result-functions
'(("read" . pimacs--visit-read-result)
  ("write" . pimacs--visit-write-result)
  ("edit" . pimacs--visit-edit-result)
  ("grep" . pimacs--visit-grep-result))

Alist mapping tool names to result visitor functions.

Each entry is (TOOL-NAME . FUNCTION) where FUNCTION is called with (DETAILS ARGS) to visit the relevant location of the tool result.

User Option: pimacs-visit-tool-call-functions
'(("read" . pimacs--visit-read-call)
  ("write" . pimacs--visit-write-call)
  ("edit" . pimacs--visit-edit-call))

Alist mapping tool names to call visitor functions.

Each entry is (TOOL-NAME . FUNCTION) where FUNCTION is called with (ARGS) to visit the relevant location of the tool call.

User Option: pimacs-insert-custom-message-functions '()

Alist mapping custom message types to inserter functions.

Each entry is (CUSTOM-TYPE . FUNCTION) where FUNCTION is called with the message plist to insert the custom message content.

User Option: pimacs-send-pop-to-chat t

Whether to pop to the chat buffer after sending region, filename or errors.

User Option: pimacs-chat-keep-input-at-bottom t

Whether to keep the input area at the bottom as new chat content is added.

User Option: pimacs-list-sessions-table
'(("Session" . (:session_name face font-lock-type-face))
  ("Provider" . :provider)
  ("Model" . :model)
  ("State" . (:agent_state face font-lock-constant-face))
  ("Context" . (:context_usage face shadow))
  ("Messages" . :total_messages)
  ("Cost" . (:cost face shadow))
  ("Project" . (:project_root face shadow)))

Columns displayed by pimacs-list-sessions.

Each entry is (HEADER . COMPONENT). COMPONENT uses the same format as an entry in pimacs-header-line-format.

User Option: pimacs-list-sessions-sort-key '("Session" . nil)

Initial sort order for pimacs-list-sessions.

The car is a header from pimacs-list-sessions-table. A non-nil cdr sorts in descending order.

User Option: pimacs-sync-request-timeout 2

The number of seconds to wait for a sync response.

User Option: pimacs-executable "pi"

Pi command executable name.

User Option: pimacs-process-environment '()

List of extra environment variables to use when starting pimacs.

User Option: pimacs-flags '()

List of additional flags to provide when starting pimacs.

User Option: pimacs-log-rpc nil

When non-nil, log all RPC JSON to pimacs-log-rpc-file.

User Option: pimacs-log-rpc-file (expand-file-name "pimacs.el.log" (temporary-file-directory))

File to write RPC JSON log entries to.

User Option: pimacs-use-ansi-colors t

Whether to render ANSI colors in widget and status output.

User Option: pimacs-header-line-format '(:context_usage " (" :compaction_mode ")" :spacer "(" :provider ") " :model " • " :thinking_level)

Format of the Pimacs chat header line.

Strings are displayed literally. Functions are called with the state plist and their returned values are displayed. A keyword component can include text properties using propertize syntax. For example: "(:model face font-lock-function-name-face)". A status component has form (:status STATUS-KEY PROPERTY VALUE...); it displays the text set by an extension with STATUS-KEY and accepts optional text properties. For example: (:status "xyz-status" face font-lock-warning-face).

The following keywords are replaced with state information.

Session state keywords:

:model

Model identifier.

:provider

Model provider.

:thinking_level

Thinking level.

:session_name

Session name.

:project_root

Project root directory.

:compaction_mode

auto or manual.

:message_count

Message count.

:pending_message_count

Pending message count.

Session statistics keywords:

:user_messages

User message count.

:assistant_messages

Assistant message count.

:tool_calls

Tool call count.

:tool_results

Tool result count.

:total_messages

Total message count.

:input_tokens

Input token count.

:output_tokens

Output token count.

:cache_read_tokens

Cache-read token count.

:cache_write_tokens

Cache-write token count.

:cache_hit_percent

Total cache hit percentage.

:total_tokens

Total token count.

:cost

Session cost.

:context_usage

Context tokens and context window.

:context_tokens

Context token count.

:context_window

Context window size.

UI keywords:

:agent_state

Current agent state.

:spinner

Active agent spinner.

:spacer

Space that right-aligns all following entries.

Status components: (:status STATUS-KEY ...) Extension status text for STATUS-KEY.

Use at most one :spacer.

User Option: pimacs-mode-line-format '(" Pimacs " :agent_state :spinner)

Format of the Pimacs mode-line entry.

See pimacs-header-line-format for available components.

User Option: pimacs-align-markdown-tables t

Whether to align markdown tables while rendering assistant output.

User Option: pimacs-section-autohide-count 2

Automatically hide older chat sections beyond this count. This helps reduce clutter by collapsing earlier responses when the conversation grows long. When nil, auto hiding is disabled and no sections are hidden automatically.

User Option: pimacs-section-padding "\n\n"

String inserted between sections to control the visual gap. Increase or decrease this value to adjust spacing between sections.

User Option: pimacs-section-visibility-indicators '(pimacs-section-fringe-bitmap> . pimacs-section-fringe-bitmapv)

Fringe bitmaps used to indicate section visibility.

The car is used for hidden sections and the cdr for visible sections. Set this to nil to disable fringe indicators.