# Local Script Setup

Any local tool can update Agent Signal Bar by calling the CLI wrapper from the project root. The wrapper prefers the installed release binary at `dist/bin/agent-signal` and falls back to the debug build when present.

Prefer passing a stable `--session` for real jobs so the menu can explain which process is active. Bare commands such as `./scripts/agent-signal working` are treated as a `manual` session and still respect aggregation priority, so a red permission or blocked session will not be overwritten by a manual working signal. `idle` and `reset` are the manual clear path.

The CLI is intentionally strict about options. A typo such as `--sesion` or a missing value after `--session` exits with an error instead of silently creating a `manual` session.

## Generic Script

If a local runner can emit JSON, use the generic hook. It recognizes common
fields such as `event`, `status`, `signal`, `agent`, `source`, `session_id`,
`task_id`, and `run_id`:

```bash
echo '{"event":"AgentStarted","agent":"local-runner","session_id":"job-1"}' \
  | ./scripts/generic-agent-signal-hook

echo '{"status":"failed","source":"local-runner","task_id":"job-1"}' \
  | ./scripts/generic-agent-signal-hook
```

```bash
./scripts/agent-signal working \
  --session nightly-build \
  --agent script \
  --event BuildStarted

./scripts/agent-signal done \
  --session nightly-build \
  --agent script \
  --event BuildFinished
```

Use `blocked` for failures:

```bash
./scripts/agent-signal blocked \
  --session nightly-build \
  --agent script \
  --event BuildFailed
```

If a script runs from another directory, resolve this project path first and quote it:

```bash
AGENT_SIGNAL_ROOT="/path/to/AgentSignalLight"
"$AGENT_SIGNAL_ROOT/scripts/agent-signal" working --session job --agent script --event Started
```

## Wrap Any Command

For simple jobs, let `agent-signal-run` set the light for you:

```bash
./scripts/agent-signal-run \
  --session nightly-build \
  --agent script \
  -- ./run-build.sh
```

It writes `working` before the command starts, `done` when the command exits `0`, and `blocked` when the command exits non-zero. The wrapped command's original exit code is preserved, so CI or shell scripts can still fail normally.

## Explicit Phase Commands

If a local workflow can run shell commands before and after agent work, map it
like this:

```bash
./scripts/agent-signal working \
  --session local-script-main \
  --agent local-script \
  --event AgentStarted

./scripts/agent-signal attention \
  --session local-script-main \
  --agent local-script \
  --event NeedsReview

./scripts/agent-signal done \
  --session local-script-main \
  --agent local-script \
  --event AgentFinished
```

`done` is a green completed state and automatically returns to idle after the completed TTL.

If the workflow can run one command around a job, use the wrapper instead:

```bash
./scripts/agent-signal-run \
  --session local-script-main \
  --agent local-script \
  --start-event AgentStarted \
  --done-event AgentFinished \
  --blocked-event AgentFailed \
  -- ./local-agent-command
```

## Machine-Readable Status

Use `--json` when another script needs to branch on the aggregate state:

```bash
status_json="$(./scripts/agent-signal status --json)"
display_state="$(printf '%s' "$status_json" | /usr/bin/python3 -c 'import json,sys; print(json.load(sys.stdin)["display_state"])')"

if [ "$display_state" = "blocked" ] || [ "$display_state" = "permission" ]; then
  echo "Agent needs attention"
fi
```

State-changing commands can also return JSON:

```bash
./scripts/agent-signal working \
  --session nightly-build \
  --agent script \
  --event BuildStarted \
  --json
```
