Push To Display
← Back to blog

Claude Code Hooks — Push AI Agent Activity to a Physical Display

Claude Code Hooks — Push AI Agent Activity to a Physical Display

Claude Code works autonomously. You give it a task, walk away, come back 20 minutes later — and then spend 5 minutes scrolling terminal output to figure out what happened.

For teams running multiple Claude Code sessions across different repos, the visibility problem compounds. Nobody knows what the AI agents are doing until someone checks manually.

What if every Claude Code session pushed its activity to a screen on your desk — task completions, errors, progress — the same way a CI dashboard shows pipeline status?

This tutorial shows you how to wire Claude Code's hook system into PushToDisplay so agent activity appears on any device in real time.

What you'll build

A 4-panel display where each panel shows a different aspect of Claude Code's activity:

PanelHook triggerContent
Panel 1Task completionSummary of what was built/fixed + files changed
Panel 2Error/blockedRed alert when the agent hits a failure or needs input
Panel 3Progress heartbeatCurrent file, step count, what's happening now
Panel 4Session summaryEnd-of-session stats: files, lines, duration

Your agent works. Your screen updates. You glance over and know exactly where things stand.

Prerequisites

  1. Claude Code installed and working (claude CLI available)
  2. PushToDisplay CLI installed: npm install -g pushtodisplay
  3. Authenticate: pushtodisplay auth login --api-key YOUR_KEY
  4. Set board layout to 2×2 Grid in the app (Settings → Layout → 2×2 Grid)

How Claude Code hooks work

Claude Code supports hooks — shell commands that execute at specific lifecycle points during a session. You configure them in your project's .claude/settings.json or globally in ~/.claude/settings.json:

{
  "hooks": {
    "postToolExecution": "~/.claude/hooks/post-tool.sh",
    "onError": "~/.claude/hooks/on-error.sh",
    "postSession": "~/.claude/hooks/post-session.sh"
  }
}

Each hook receives context via environment variables — the tool name, result, error message, file paths, etc. We'll use these to push structured updates to the display.

Hook 1: Task completion → Panel 1

When Claude Code completes a tool execution (file write, command run, test pass), push a summary to Panel 1.

Create ~/.claude/hooks/post-tool.sh:

#!/bin/bash

# Only push on significant completions (file writes, not every read)
if [[ "$CLAUDE_TOOL" != "write_file" && "$CLAUDE_TOOL" != "run_command" ]]; then
  exit 0
fi

# Determine status color
if [[ "$CLAUDE_EXIT_CODE" == "0" ]]; then
  BG="#0d7a3e"
  STATUS="✓ Done"
else
  BG="#c0392b"
  STATUS="✗ Failed"
fi

pushtodisplay send \
  --panel 1 \
  --background "$BG" \
  --block "{\"text\": \"$STATUS: $CLAUDE_TOOL\", \"size\": \"large\", \"weight\": \"bold\", \"color\": \"#ffffff\"}" \
  --block "{\"text\": \"$CLAUDE_FILE\", \"size\": \"medium\", \"color\": \"#ffffffcc\"}" \
  --block "{\"text\": \"$(date '+%H:%M:%S') • $CLAUDE_SESSION_ID\", \"size\": \"small\", \"color\": \"#ffffff99\"}"

Make it executable:

chmod +x ~/.claude/hooks/post-tool.sh

Now every time Claude Code writes a file or runs a command, your display shows what happened and whether it succeeded.

Hook 2: Error alert → Panel 2

When Claude Code hits an error — a test failure, a permission issue, or a blocked state — push a red alert to Panel 2.

Create ~/.claude/hooks/on-error.sh:

#!/bin/bash

pushtodisplay send \
  --panel 2 \
  --background "#c0392b" \
  --full-panel \
  --block "{\"text\": \"⚠️ Agent Blocked\", \"size\": \"large\", \"weight\": \"bold\", \"color\": \"#ffffff\"}" \
  --block "{\"text\": \"$CLAUDE_ERROR_MESSAGE\", \"size\": \"medium\", \"color\": \"#ffffffcc\"}" \
  --block "{\"text\": \"Needs attention • $(date '+%H:%M')\", \"size\": \"small\", \"color\": \"#ffffff99\"}"

This uses --full-panel so the error takes over the panel space with larger text — impossible to miss from across the room.

Hook 3: Progress heartbeat → Panel 3

For long-running sessions, push periodic progress to Panel 3 so you can see what Claude Code is working on right now.

Create ~/.claude/hooks/progress.sh:

#!/bin/bash

# Called periodically or on each tool execution
STEP_COUNT="${CLAUDE_STEP_COUNT:-?}"
CURRENT_FILE="${CLAUDE_FILE:-unknown}"
ELAPSED="${CLAUDE_ELAPSED:-0s}"

pushtodisplay send \
  --panel 3 \
  --background "#2c3e50" \
  --block "{\"text\": \"Working...\", \"size\": \"large\", \"weight\": \"bold\", \"color\": \"#ffffff\"}" \
  --block "{\"text\": \"$CURRENT_FILE\", \"size\": \"medium\", \"color\": \"#ffffffcc\"}" \
  --block "{\"text\": \"Step $STEP_COUNT$ELAPSED elapsed\", \"size\": \"small\", \"color\": \"#ffffff99\"}"

Glance at the screen — if it says "Working..." with a file name, the agent is still active. If the timestamp is stale, something might be stuck.

Hook 4: Session summary → Panel 4

When a Claude Code session ends, push a final summary to Panel 4 — what was accomplished overall.

Create ~/.claude/hooks/post-session.sh:

#!/bin/bash

# Collect session stats from environment
FILES_CHANGED="${CLAUDE_FILES_CHANGED:-0}"
LINES_ADDED="${CLAUDE_LINES_ADDED:-0}"
LINES_REMOVED="${CLAUDE_LINES_REMOVED:-0}"
DURATION="${CLAUDE_DURATION:-unknown}"
TASK="${CLAUDE_TASK_SUMMARY:-Session complete}"

pushtodisplay send \
  --panel 4 \
  --background "#1a5276" \
  --block "{\"text\": \"Session Complete\", \"size\": \"large\", \"weight\": \"bold\", \"color\": \"#ffffff\"}" \
  --block "{\"text\": \"$TASK\", \"size\": \"medium\", \"color\": \"#ffffffcc\"}" \
  --block "{\"text\": \"$FILES_CHANGED files • +$LINES_ADDED/-$LINES_REMOVED lines • $DURATION\", \"size\": \"small\", \"color\": \"#ffffff99\"}"

Come back from lunch and Panel 4 tells you: "Refactored auth module — 8 files, +142/-89 lines, 12 minutes."

Alternative: Use curl directly

If you prefer not to install the CLI in your hook scripts, call the REST API directly:

#!/bin/bash

curl -s -X POST https://api.pushtodisplay.com/v1/updates \
  -H "Content-Type: application/json" \
  -H "X-Api-Key: $PUSHTODISPLAY_API_KEY" \
  -d "{
    \"panelId\": 1,
    \"background\": \"#0d7a3e\",
    \"blocks\": [
      {\"text\": \"$STATUS\", \"size\": \"large\", \"weight\": \"bold\", \"color\": \"#ffffff\"},
      {\"text\": \"$CLAUDE_FILE\", \"size\": \"medium\", \"color\": \"#ffffffcc\"}
    ]
  }"

Same result, no dependency beyond curl.

Team setup: Multiple agents, one board

For teams with several developers running Claude Code simultaneously, assign each developer a panel — or use separate boards per developer with a shared overview board:

Option A — One board, one panel per dev:

# In each developer's hook config, set their panel
export PUSHTODISPLAY_PANEL=1  # Alice
export PUSHTODISPLAY_PANEL=2  # Bob
export PUSHTODISPLAY_PANEL=3  # Carol
export PUSHTODISPLAY_PANEL=4  # Dave

A mounted TV shows the whole team's AI agent activity at a glance — who's building, who's blocked, who's idle.

Option B — Consolidate with CI:

Combine with the GitHub Actions dashboard setup. Panels 1–2 show CI/CD status, Panels 3–4 show Claude Code activity. One screen, full pipeline + AI agent visibility.

Consolidate AI agent output with everything else

The power isn't just Claude Code visibility in isolation — it's consolidating AI agent activity alongside your other development signals:

  • Panel 1: GitHub Actions build/test results (from your CI workflow)
  • Panel 2: Claude Code task completions
  • Panel 3: Deploy status from Vercel/AWS
  • Panel 4: Claude Code errors/alerts

One screen. CI, CD, and AI agent activity — all consolidated. No context-switching between GitHub, terminal, and Slack.

Get started

  1. Install the CLI: npm install -g pushtodisplay
  2. Authenticate: pushtodisplay auth login --api-key YOUR_KEY
  3. Create the hook scripts above in ~/.claude/hooks/
  4. Add the hook paths to .claude/settings.json
  5. Start a Claude Code session and watch the panels update

Your AI agent's work — visible at a glance, without scrolling a terminal.


Related: GitHub Actions Dashboard tutorial · CLI docs · HTTP API reference · MCP Server for Claude Code