Skip to content

Instantly share code, notes, and snippets.

@jedi4ever
Last active May 19, 2026 14:08
Show Gist options
  • Select an option

  • Save jedi4ever/75be19b1166020e8d476ef7e6f52f9f0 to your computer and use it in GitHub Desktop.

Select an option

Save jedi4ever/75be19b1166020e8d476ef7e6f52f9f0 to your computer and use it in GitHub Desktop.
Simple script to run claude headless without the -p (to avoid extra costs)
#!/usr/bin/env bash
# Usage: ./cs "your prompt"
# Runs Claude headlessly, suppresses the TUI, prints Claude's final reply on stdout.
set -uo pipefail
PROMPT="$*"
REPLY_FILE=$(mktemp)
SESSION_ID=$(uuidgen | tr 'A-Z' 'a-z')
ENC_CWD=$(pwd | sed 's|/|-|g')
SESSION_FILE="$HOME/.claude/projects/$ENC_CWD/$SESSION_ID.jsonl"
trap 'rm -f "$REPLY_FILE" "$SESSION_FILE"' EXIT
# PreToolUse: auto-approve every tool call so there's no interactive prompt.
PRE_CMD='echo "{\"hookSpecificOutput\":{\"hookEventName\":\"PreToolUse\",\"permissionDecision\":\"allow\"}}"'
# Stop: extract Claude's final reply from the hook payload and signal claude to exit.
STOP_CMD="jq -r .last_assistant_message > '$REPLY_FILE'; pid=\$PPID; while [ -n \"\$pid\" ] && [ \"\$pid\" != \"1\" ]; do name=\$(ps -p \$pid -o comm= 2>/dev/null); case \"\$name\" in *claude*) kill -INT \$pid; exit 0;; esac; pid=\$(ps -o ppid= -p \$pid 2>/dev/null | tr -d ' '); done"
SETTINGS=$(jq -nc --arg pre "$PRE_CMD" --arg stop "$STOP_CMD" '{
hooks: {
PreToolUse: [{hooks: [{type: "command", command: $pre}]}],
Stop: [{hooks: [{type: "command", command: $stop}]}]
}
}')
script -q /dev/null claude --settings "$SETTINGS" --session-id "$SESSION_ID" "$PROMPT" >/dev/null 2>&1 || true
cat "$REPLY_FILE"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment