How to Use Goose's External Editor Mode for Composing Prompts

To use external editor mode in Goose, set the GOOSE_PROMPT_EDITOR environment variable or configuration key to your preferred editor (e.g., vim or code --wait), and Goose will open a temporary markdown file for each prompt instead of using the built-in REPL line editor.

The Goose CLI from block/goose supports an external editor mode that replaces the default line-based input with a full-featured text editor workflow. When enabled, Goose orchestrates a round-trip pipeline that creates a temporary markdown template, launches your configured editor, and extracts only your newly typed content while preserving conversation context. This allows you to compose complex prompts, code snippets, or multi-line instructions in familiar editing environments like vim, nano, or VS Code.

How External Editor Mode Works

According to the block/goose source code, enabling external editor mode triggers a six-step pipeline for every user turn. The implementation spans crates/goose-cli/src/session/input.rs and crates/goose-cli/src/session/editor.rs, with configuration defined in crates/goose/src/config/base.rs.

Step 1: Detecting the Editor Configuration

When the session loop needs input, input.rs checks for the GOOSE_PROMPT_EDITOR key using config.get_goose_prompt_editor() (lines 95–100). This method queries both the environment variable and the user configuration file, returning an Option<String> that determines whether to invoke external editor mode or fall back to the built-in readline implementation.

Step 2: Creating the Markdown Template

If an editor is configured, editor.rs::create_temp_file generates a temporary markdown file containing:

  • A title (# Goose Prompt Editor)

  • A # Your prompt: section where you type your message

  • A # Recent conversation for context section with the newest messages first (lines 9–24)

This template ensures you always see the latest exchange while drafting your next prompt.

To provide a stable path for editors that require specific file extensions or locations, Goose creates a symlink named .goose_prompt_temp.md pointing to the temporary file. The SymlinkCleanup RAII guard in editor.rs (lines 31–48) ensures this symlink is removed even if Goose panics or crashes.

The launch_editor function (lines 49–68) then constructs a std::process::Command from your configured editor string, passes the symlink path as an argument, and inherits stdio so the editor runs interactively.

Step 4: Extracting the User Input

After the editor process exits, Goose reads the file back and calls extract_user_input (lines 27–34, 56–60) to trim away the template. This function keeps only the text appearing after the # Your prompt: heading, discarding the conversation history and boilerplate. If the remaining text is non-empty, get_editor_input returns it as the prompt; otherwise, Goose falls back to the normal line editor (lines 101–107 in input.rs).

Configuring the External Editor

You can specify your editor via environment variable for temporary sessions or via configuration file for persistent settings.

Environment Variable (Session-Only)

Set GOOSE_PROMPT_EDITOR before starting Goose:


# Use vim for this session

export GOOSE_PROMPT_EDITOR=vim

# Or use VS Code (requires --wait to block until window closes)

export GOOSE_PROMPT_EDITOR="code --wait"

Configuration File (Persistent)

Add the key to ~/.config/goose/config.yaml:

GOOSE_PROMPT_EDITOR: nano

The configuration system uses the config_value! macro in crates/goose/src/config/base.rs (lines 60–61) to store this as an Option<String>. Environment variables override file settings.

Important: GUI Editor Requirements

For graphical editors like VS Code or Sublime Text, you must include a --wait (or equivalent) flag. Terminal editors like vim or nano block the terminal automatically, but GUI editors return immediately unless told to wait. Without this flag, Goose will read the file before you finish editing.

Practical Examples

Using vim for a Single Session

export GOOSE_PROMPT_EDITOR=vim
goose session

When prompted, vim opens a file resembling:


# Goose Prompt Editor

# Your prompt:

# Recent conversation for context (newest first):

## User: How do I list files?

## Assistant: You can use `ls -la`.

Type your message under # Your prompt:, save and quit. Goose extracts your input and continues the conversation.

Using VS Code Persistently

Edit ~/.config/goose/config.yaml:

GOOSE_PROMPT_EDITOR: "code --wait"

All future sessions open VS Code for prompt composition. The --wait flag ensures Goose pauses until you close the editor window.

Programmatic Usage (for Developers)

To invoke the editor logic directly in Rust code:

use goose_cli::session::editor::get_editor_input;

let recent = vec!["## Assistant: Sure!", "## User: List files?"];

let (prompt, ok) = get_editor_input("vim", &recent)?;
if ok {
    println!("Captured prompt: {}", prompt);
}

This opens the configured editor with the provided conversation history and returns the extracted user input.

Summary

  • External editor mode in Goose swaps the REPL line editor for any text editor by setting GOOSE_PROMPT_EDITOR.

  • The workflow creates a temporary markdown template with conversation context, launches your editor via a stable symlink (.goose_prompt_temp.md), and extracts content from the # Your prompt: section.

  • Configure via environment variable for one-off sessions or ~/.config/goose/config.yaml for permanent defaults.

  • GUI editors require a --wait flag; terminal editors block automatically.

  • Key implementation files: crates/goose-cli/src/session/editor.rs (orchestration), crates/goose-cli/src/session/input.rs (detection), and crates/goose/src/config/base.rs (configuration).

Frequently Asked Questions

What file format does Goose use for the external editor template?

Goose generates a temporary markdown file containing specific headings. The template includes # Goose Prompt Editor as a title, # Your prompt: where you type your input, and # Recent conversation for context with the latest messages injected for reference. After you save and close the editor, Goose parses this markdown to extract only the text under the prompt heading.

How do I use VS Code with Goose's external editor mode?

Set GOOSE_PROMPT_EDITOR to code --wait (including the quotes if your shell requires them). The --wait flag is mandatory because VS Code launches as a background process by default; the flag forces the CLI to block until you close the editor window, allowing Goose to read your changes. Without this flag, Goose would read an empty file immediately.

Where does Goose store the external editor configuration?

Goose stores the GOOSE_PROMPT_EDITOR key in the user configuration file at ~/.config/goose/config.yaml, or temporarily via the GOOSE_PROMPT_EDITOR environment variable. The configuration is defined in crates/goose/src/config/base.rs using a config_value! macro, and the resolution logic in input.rs checks the environment variable first, then the config file, then falls back to the built-in line editor if neither is set.

What happens if I save the external editor file without typing anything?

If you save the file but leave the section under # Your prompt: empty, Goose detects this condition via get_editor_input and returns a flag indicating the content is not meaningful. In this case, Goose automatically falls back to the normal line-based REPL flow, allowing you to enter a prompt directly in the terminal instead.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →