Skip to content

[Feature] Auto-confirm Claude Code paste preview and permission prompts #14

Description

@KhaTruong123

GitHub Issue: Handle Claude Code paste preview and permission prompts

Repository: https://github.com/longbkit/clisbot


Issue Title

[Feature] Auto-confirm Claude Code paste preview and permission prompts


Issue Body

Problem

When using clisbot with Claude Code CLI, multi-line messages trigger Claude's paste preview feature:

❯ [Pasted text #1 +46 lines]

Claude Code waits for a second Enter to confirm the paste before processing. However, clisbot only sends one Enter after pasting text, causing:

Error: TmuxSubmitUnconfirmedError: tmux submit was not confirmed after Enter. 
The pane state did not change, so clisbot did not treat the prompt as truthfully submitted.

Similarly, Claude Code shows permission prompts that require user confirmation:

Do you want to create SKILL.md?
❯ 1. Yes
  2. Yes, and allow Claude to edit its own settings
  3. No

These prompts block execution until confirmed.

Expected Behavior

clisbot should:

  1. Detect when Claude Code shows paste preview ([Pasted text #N +X lines]) and auto-send Enter
  2. Optionally auto-approve permission prompts when configured

Proposed Solution

Option A: Built-in detection in runner

Add to agents.defaults.runner.claude config:

{
  "claude": {
    "pastePreview": {
      "autoConfirm": true,
      "pattern": "\\[Pasted text #\\d+"
    },
    "permissions": {
      "autoApprove": true,
      "patterns": ["Do you want to (proceed|create|allow|accept|run)"]
    }
  }
}

Option B: Post-submit hook

Add a postSubmitCheck hook in runner that:

  1. After sending Enter, wait briefly and check pane content
  2. If paste preview pattern detected, send another Enter
  3. If permission prompt detected and autoApprove: true, send Enter

Workaround (Current)

Created external monitor script that polls tmux pane and auto-sends Enter:

#!/bin/bash
# ~/.clisbot/bin/paste-monitor.sh
SOCKET="~/.clisbot/state/clisbot.sock"
declare -A LAST_HASH

while true; do
    for SESSION in $(tmux -S "$SOCKET" list-sessions -F "#{session_name}" 2>/dev/null); do
        CONTENT=$(tmux -S "$SOCKET" capture-pane -t "$SESSION" -p | tail -15)
        CONTENT_HASH=$(echo "$CONTENT" | md5sum | cut -d" " -f1)
        
        [ "${LAST_HASH[$SESSION]}" = "$CONTENT_HASH" ] && continue
        
        if echo "$CONTENT" | grep -q "\[Pasted text #"; then
            tmux -S "$SOCKET" send-keys -t "$SESSION" Enter
            LAST_HASH[$SESSION]="$CONTENT_HASH"
        elif echo "$CONTENT" | grep -qE "(Do you want to|Allow|Approve)" && \
             echo "$CONTENT" | grep -qE "❯.*Yes|1\. Yes"; then
            tmux -S "$SOCKET" send-keys -t "$SESSION" Enter
            LAST_HASH[$SESSION]="$CONTENT_HASH"
        fi
    done
    sleep 0.1
done

Run as systemd user service for persistence.

Environment

  • clisbot version: 0.1.53
  • CLI: Claude Code (claude)
  • OS: Ubuntu 22.04 (VPS)
  • tmux: 3.2a

Related

  • Claude Code uses Ink-based TUI with bracketed paste detection
  • This is Claude-specific; Codex/Gemini may not have this behavior

Labels

enhancement, claude-cli, runner


Optional: PR Implementation Notes

If implementing as PR:

  1. File: src/runner/claude-runner.ts (or equivalent)
  2. Changes:
    • Add pastePreview and permissions config schema
    • After send-keys, poll pane for patterns
    • If matched, send additional Enter
  3. Config: Add to agents.defaults.runner.claude in schema
  4. Docs: Update docs/user-guide/claude-cli.md with new options

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    Status
    Backlog

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions