opencode icon indicating copy to clipboard operation
opencode copied to clipboard

Feature Request: Add Background Bash Execution (Like Claude Code’s Ctrl+b)

Open elloydfetch opened this issue 4 months ago • 10 comments

Feature Request: Support Long-Running Bash Processes in the Background (Async Execution)

Summary

Claude Code includes a feature that allows developers to run bash commands in the background without blocking the agent/chat interface. This enables long-running tasks (e.g., builds, servers, data processing) to continue running while the developer interacts with the AI for other tasks.

I propose adding similar functionality to OpenCode.

Motivation

Currently, when a bash command is run in OpenCode via the bash tool, the session is blocked until the command completes. This makes workflows involving:

  • Development servers
  • Continuous monitoring scripts
  • Large builds or data processing jobs

…slow and cumbersome, since you can’t continue using the AI assistant while those commands are still running.

Background execution would:

  • Keep the AI assistant responsive
  • Allow parallel workstreams
  • Reduce the need to switch out of OpenCode to manage long-running jobs in a separate shell

Reference: Claude Code’s Implementation

Claude Code provides Background Commands with a simple shortcut (Ctrl+b) to run bash processes asynchronously.
Reference: Claude Code FAQ – Background Commands

“Background commands allow you to run bash processes in the background using Ctrl+b, enabling Claude to continue working on other tasks while long-running processes execute. Great for development servers and monitoring.”

Proposed Design Ideas

  • Syntax Option: Add a background: true parameter to the bash tool.
  • Shortcut Key: Similar to Claude Code, provide a hotkey to run the currently typed bash command as a background job.
  • Job Management: Include a simple job list/kill command to view or stop background processes.
  • Output Handling: Stream or store background process logs for later inspection.

Workarounds Today

  • Using & or nohup inside the bash tool sometimes works, but behavior is inconsistent and often tied to the session lifecycle.
  • Running tasks outside of OpenCode in a multiplexer (tmux, screen)—but this defeats the purpose of integrated AI-assisted workflows.

Impact

Implementing this feature would make OpenCode far more usable for developers with mixed workloads and align it with modern AI coding assistants’ capabilities.


Related links:

elloydfetch avatar Aug 15 '25 18:08 elloydfetch

This issue might be a duplicate of existing issues. Please check:

  • #1852: Commands that need sudo access break the UI and make the agent hang (addresses UI hanging with certain bash commands)
  • #1955: bash tool missing tree-sitter-bash.wasm and it will cause the process to become stuck (addresses bash tool getting stuck)
  • #1868: Request to make Bash line output configurable (related to bash tool behavior and output handling)

While these issues address different aspects of bash tool problems (hanging, getting stuck, output handling), none specifically address background/async execution like your feature request. Your proposal for background bash execution appears to be a new and distinct feature request.

github-actions[bot] avatar Aug 15 '25 18:08 github-actions[bot]

idk if it helps but this is what i had created a while ago to handle running dev servers without the agent trying to start multiple, getting stuck by not realizing its an infinite process, and being able to look at logs as needed while we work.

this is just for "dev" mode but conceptually it could be used for other processes besides a dev server.

#!/bin/bash

# Generic development process manager
# Usage: ./dev.sh start "your dev command here"
PID_FILE=".dev.pid"
LOG_FILE=".dev.log"

run() {
    case "$1" in
        start)   shift; start "$@" ;;
        stop)    stop ;;
        restart) shift; restart "$@" ;;
        logs)    shift; logs "$@" ;;
        status)  status ;;
        *)       echo "Usage: $0 {start|stop|restart|logs|status} [command]" ;;
    esac
}

start() {
    if [ $# -eq 0 ]; then
        echo "Usage: $0 start \"command to run\""
        return 1
    fi
    
    if [ -f "$PID_FILE" ]; then
        if kill -0 $(cat "$PID_FILE") 2>/dev/null; then
            echo "Process already running (PID: $(cat $PID_FILE))"
            return 1
        else
            echo "Removing stale PID file"
            rm "$PID_FILE"
        fi
    fi
    
    echo "Starting: $*"
    echo "=== Started at $(date) ===" > "$LOG_FILE"
    "$@" >> "$LOG_FILE" 2>&1 &
    PID=$!
    echo $PID > "$PID_FILE"
    echo "Process started (PID: $PID)"
    
    # Give it a moment to start
    sleep 2
    
    # Verify it's still running
    if kill -0 "$PID" 2>/dev/null; then
        echo "Process is running. Logs: ./dev.sh logs"
    else
        echo "Process failed to start. Check logs: ./dev.sh logs"
        rm "$PID_FILE"
    fi
}

stop() {
    if [ -f "$PID_FILE" ]; then
        PID=$(cat "$PID_FILE")
        if kill -0 "$PID" 2>/dev/null; then
            echo "Stopping process (PID: $PID)"
            kill "$PID"
            rm "$PID_FILE"
        else
            echo "Process not running"
            rm "$PID_FILE"
        fi
    else
        echo "No PID file found"
    fi
}

restart() {
    if [ $# -eq 0 ]; then
        echo "Usage: $0 restart \"command to run\""
        return 1
    fi
    stop
    sleep 1
    start "$@"
}

logs() {
    if [ ! -f "$LOG_FILE" ]; then
        echo "No log file found"
        return 1
    fi
    
    case "${1:-tail}" in
        tail|follow)
            echo "Following logs (Ctrl+C to exit)..."
            tail -f "$LOG_FILE"
            ;;
        recent)
            lines="${2:-50}"
            echo "Last $lines lines:"
            tail -"$lines" "$LOG_FILE"
            ;;
        clear)
            > "$LOG_FILE"
            echo "Log file cleared"
            ;;
        all)
            cat "$LOG_FILE"
            ;;
        search)
            if [ -z "$2" ]; then
                echo "Usage: $0 logs search <pattern>"
                echo "Example: $0 logs search ERROR"
                return 1
            fi
            echo "Searching for: $2"
            grep -n --color=auto "$2" "$LOG_FILE"
            ;;
        *)
            echo "Usage: $0 logs [tail|recent|clear|all|search] [args]"
            echo "  tail/follow     - Follow logs in real-time (default)"
            echo "  recent [N]      - Show last N lines (default: 50)"
            echo "  clear           - Clear log file"  
            echo "  all             - Show entire log"
            echo "  search <pattern> - Search logs with grep"
            echo ""
            echo "Examples:"
            echo "  $0 logs recent 100    # Last 100 lines"
            echo "  $0 logs search ERROR  # Find error messages"
            echo "  $0 logs search 'POST.*ws' # Find WebSocket POST requests"
            ;;
    esac
}

status() {
    if [ -f "$PID_FILE" ]; then
        PID=$(cat "$PID_FILE")
        if kill -0 "$PID" 2>/dev/null; then
            echo "Process running (PID: $PID)"
            echo "Log file: $LOG_FILE"
        else
            echo "Process not running (stale PID file)"
        fi
    else
        echo "Process not running"
    fi
}

run

the-vampiire avatar Aug 15 '25 20:08 the-vampiire

Agreed that tmux is a workaround but would be nice to have this built in to be on part with claude code

ironbelly avatar Oct 09 '25 21:10 ironbelly

yeah makes sense

rekram1-node avatar Oct 09 '25 21:10 rekram1-node

I built an MCP server for this, which is a solid alternative for now:

https://github.com/waylaidwanderer/background-process-mcp

waylaidwanderer avatar Nov 28 '25 23:11 waylaidwanderer

tmux works really well for running commands in background

it can

  • start bash commands (sessions) in background with a name
  • list sessions
  • kill sessions
  • get last N logs for a session

that's all you need, with the added advantage that you can attach to these sessions yourself to send interactive commands yourself! something that Claude Code does not have

you can give this document to your agent to let it know the commands to use https://github.com/remorses/AGENTS.md/blob/main/tmux.md

remorses avatar Dec 06 '25 17:12 remorses

yeah makes sense

hi @thdxr & @rekram1-node Could you share the estimated completion time for this feature?

junmediatek avatar Dec 18 '25 08:12 junmediatek

no official timeline I guess we would prolly roll out experimental version first and see how it does

rekram1-node avatar Dec 18 '25 17:12 rekram1-node

no official timeline I guess we would prolly roll out experimental version first and see how it does

@rekram1-node So when will the experimental version be released?

junmediatek avatar Dec 18 '25 22:12 junmediatek

you can also use opencode-pty plugin, it does exactly that and more: https://github.com/shekohex/opencode-pty

shekohex avatar Dec 19 '25 00:12 shekohex