# Show the current task in the Claude Code status line

> A 24-line script that puts the Taskhold task in progress, its progress bar and the running step in the Claude Code status line. Uses curl and jq.

Source: https://taskhold.com/docs/claude-code-status-line
Last updated: 2026-10-26

Claude Code runs a command of your choice for its status line. This script asks Taskhold for the task in progress and prints one line: title, a ten-block bar, steps done and the step that's running. It caches the answer for 10 seconds.

Prefer one command with no script to maintain? The [Taskhold CLI](/install) sets up the same line with taskhold-mcp statusline --install. This page is for building it into a status line of your own.

## Before you begin

- curl and jq on your PATH.
- A Taskhold API key from Settings, saved where the script can read it:

```bash
mkdir -p ~/.config/taskhold && printf '%s' 'API_KEY' > ~/.config/taskhold/key && chmod 600 ~/.config/taskhold/key
```

Replace API_KEY with your atd_sk_ key, or export TASKHOLD_API_KEY instead.

## Add the script

Save this as ~/.claude/taskhold-statusline.sh and make it executable (chmod +x):

```bash
#!/bin/bash
# ~/.claude/taskhold-statusline.sh: the task in progress, its bar and the running step.
# Needs curl and jq. Key from TASKHOLD_API_KEY or ~/.config/taskhold/key.
cat > /dev/null  # Claude Code sends session JSON on stdin; this script doesn't need it
key=${TASKHOLD_API_KEY:-$(cat ~/.config/taskhold/key 2>/dev/null)}
base=${TASKHOLD_API_URL:-https://taskhold.com/api}
cache="${TMPDIR:-/tmp}/taskhold-statusline.txt"
now=$(date +%s)
if [ -f "$cache" ]; then
  read -r stamp < "$cache"
  if [ $((now - stamp)) -lt 10 ]; then tail -n +2 "$cache"; exit 0; fi
fi
line=$(curl -s --max-time 2 "$base/tasks/current" -H "Authorization: Bearer $key" | jq -r '
  .task // empty
  | (.overall_progress // 0) as $p
  | (($p / 10) | floor) as $f
  | (([range(0; $f)] | map("█") | join("")) + ([range($f; 10)] | map("░") | join(""))) as $bar
  | (((.subtasks // []) | map(select(.status == "in_progress")) | .[0].title) // .progress_message // "") as $now
  | "\(.title)  \($bar) \($p)%"
    + (if (.subtask_counts.total // 0) > 0 then "  \(.subtask_counts.done)/\(.subtask_counts.total) steps" else "" end)
    + (if $now != "" then "  > \($now)" else "" end)' 2>/dev/null)
line=${line:-No task in progress}
printf '%s\n%s\n' "$now" "$line" > "$cache"
echo "$line"
```

Then point Claude Code at it in ~/.claude/settings.json:

```json
{
  "statusLine": {
    "type": "command",
    "command": "~/.claude/taskhold-statusline.sh",
    "refreshInterval": 10
  }
}
```

refreshInterval keeps the line current while the session is idle and another agent is working.

## What you'll see

```text
Deploy v2.4 to staging  ███░░░░░░░ 33%  1/3 steps  > Run migrations
```

With nothing in progress the line reads "No task in progress". To check the script by hand, run it with echo '{}' piped in.

## Related

- [Install the Taskhold CLI: terminal board and status line](https://taskhold.com/install.md)
- [Claude Code hook: start every session with your replies](https://taskhold.com/docs/claude-code-hooks.md)
- [Taskhold REST API: tasks, steps, progress, curl examples](https://taskhold.com/docs/rest-api.md)
