# Diagnostic Recipe: Dashboard Card Says "X Down" / "Offline"

When the user opens a dashboard (Agentic OS, Mission Control, or any agent-status UI) and a card shows `Offline`, `X down`, `Error`, or `---`, the card is *reporting that it tried to reach a service and got nothing*. The card is correct — the question is "which piece is actually down." The pieces are usually:

1. A **binary or proxy** the card polls (e.g. `fcc-server`, `ollama serve`, `n8n`)
2. A **config file** telling the binary which model / provider / endpoint to use
3. A **backend service** the binary talks to (e.g. Ollama, a remote API, a local model server)

Confirming "X is set up" usually means confirming all three. The installer often only does step 1.

## The protocol

**First: confirm the dashboard process itself is running.** A "card 404" or "card Offline" can come from a dashboard that died (Next.js production build served by `npm start` is a separate process from the bot gateway; if it crashed or was killed, *every* card will 404). Check this before chasing card-specific causes — otherwise you can waste time debugging the card when the actual problem is the dashboard.

```powershell
# Is the dashboard process even alive?
Get-NetTCPConnection -LocalPort <dashboard-port> -State Listen -ErrorAction SilentlyContinue
# If empty, the dashboard is down. Start it (e.g. `cd <dashboard-source> && npm start`).
# If non-empty, the dashboard is up — proceed to card-specific diagnosis below.
```

Once the dashboard is confirmed up, run these in order, in parallel where possible:

```powershell
# 1. Is the binary installed at all?
Get-Command <binary> -ErrorAction SilentlyContinue     # on PATH?
Test-Path "<configured-path-from-config>"              # at the path the dashboard expects?

# 2. Is the binary currently running?
Get-Process | Where-Object { $_.Name -like "*<binary>*" } | Select-Object Id, Name, StartTime
Get-NetTCPConnection -LocalPort <port-it-listens-on> -ErrorAction SilentlyContinue

# 3. Does the config file exist and point to something real?
Test-Path "<config-path>"
Get-Content "<config-path>"     # look for: model name, API key, base URL

# 4. What does the dashboard's code actually expect? (this is the most important step)
#    Find the page.tsx or component for the card, then find the URL/port it polls.
Select-String -Path "<dashboard-source>/<card-folder>" -Pattern "<keyword>" -ErrorAction SilentlyContinue
```

The fourth step is the one most people skip, and it's the one that tells you "is the card even checking the right thing?" A card labeled "Free Claude" might be polling `localhost:8082/admin`; if your proxy is on a different port, the card is doing its job — your config is wrong.

**For the FCC / free-claude-code case specifically:** the README says the Admin UI runs at `http://127.0.0.1:8082/admin`, but `fcc-server` picks its port at startup and the line `INFO: Admin UI: http://127.0.0.1:<port>/admin` is what the user actually needs to read. Don't trust the README default. If the user says "I opened 8082 and got 404," the cause is almost always one of three things, in this order: (1) the dashboard process on its own port (e.g. 3737) is down, in which case *every* route 404s not just /freeclaude; (2) the FCC server isn't running at all, in which case its port is free; (3) the FCC server is running on a different port than 8082, in which case the user's `http://127.0.0.1:8082/admin` returns nothing and the dashboard's `/api/fcc` poll returns nothing. Confirm all three before assuming a config bug.

## Worked example: "Free Claude" card shows Offline

User's Agentic OS dashboard shows a "Free Claude" card with `Offline / fcc-server down`. Diagnosis order:

1. `Get-Command fcc-server` → `not recognized`. The user only ran the installer (`irm https://...install.ps1 | iex`), which places the binary on PATH. Verify PATH was updated, or check `%USERPROFILE%\.local\bin\fcc-server.exe`.
2. `Get-Process | Where-Object {$_.Name -like "*fcc*"}` → none. Binary exists but not running.
3. `Test-Path "$env:USERPROFILE\.fcc"` → `False`. Config dir never created. Confirms binary was installed but never configured.
4. The dashboard source has a route at `/api/fcc` that polls a local proxy on `127.0.0.1:8082`. So the card is right: the proxy is not running, so the card is `Offline`.

Fix: run `fcc-server` (the proxy), open the Admin UI URL that `fcc-server` prints (NOT necessarily 8082 — read the startup log), set `OLLAMA_BASE_URL=http://localhost:11434` and `MODEL=ollama/llama3.2:latest`, click **Validate**, then **Apply**. The card flips green.

## The "but the user insists it's set up" case

A specific pitfall in the Agentic OS / Julian-Goldie-install-pack world: the user ran the *install* script and considers the tool "set up." The install script often only does step 1 (places binaries, creates shortcuts, writes start-menu entries). The user has the *means* to set it up, but no service is running and no config is written. When the card still says down after the install, the user is right that they "did the install" and the agent is right that it's not working — the gap is "install ≠ configured-and-running."

**Diagnostic shortcut:** before doing the full protocol, just `Get-Process` for the binary. If it's not running, the card is correct and you can stop the deeper diagnosis. The fix is "start the service," not "find a config bug."

## When the binary IS running but the card is still Offline

Then the config is the suspect. Three sub-failures:

1. **Wrong model name** — the model field doesn't match anything the backend has. `ollama list` to see what's available; match it exactly in the config.
2. **Wrong base URL** — the config points at `http://localhost:11434` but Ollama is bound to `127.0.0.1:11434` (or vice versa). Curl-test from the same machine: `curl http://localhost:11434/api/tags` should return a JSON list of models.
3. **Auth header missing/wrong** — many proxies need `Authorization: Bearer <key>` even for local backends. Test with a direct curl: `curl -H "Authorization: Bearer <key>" <proxy>/admin`.

For the FCC case specifically, the Admin UI has a **Validate** button that runs all three checks. Use it before debugging by hand.

## Pitfalls

- **"I set up Free Claude" usually means "I ran the installer."** Verify before agreeing.
- **A 30-second polling-conflict warning right after a service start is not a "down" state.** Telegram/Discord hold long-polls for ~20-30s after a process dies; the new gateway waits it out. This is the same shape as "card Offline right after restart" and self-resolves.
- **The card's label may not match the binary.** "Free Claude" = `fcc-server`. "Memory" = an Obsidian vault scan. "Hermes" = the `hermes` CLI. If you grep the dashboard source for the binary's actual name and get no hits, you're looking at the wrong thing.
- **A child process with `--session-key <sid>` is the TUI backend, not the gateway.** Don't kill it as part of "fix the gateway" — you'll end the active chat session.
- **`Restart=always` services come back in 10 seconds.** If you `Stop-Process` the proxy and see it back 10 seconds later, you haven't fixed the service, you've just delayed it. Find the supervisor (systemd unit, Windows scheduled task, or whatever) and disable the supervisor first.
- **The "build is stale" trap when a card 404s on a Next.js production dashboard.** If a route 404s and you assume the source has changes the pre-built `.next/` doesn't, the fix is `npm run build` then `npm start`. But before you rebuild, check two cheaper things first: (1) is the dashboard process even running (`Get-NetTCPConnection -LocalPort <port> -State Listen`)? A dead dashboard 404s every route, not just one. (2) is the build actually older than the source, or newer? In a real session, `.next/` was dated 7/9 and `page.tsx` was dated 6/16 — the build was *newer* than the source, so rebuild would have done nothing. The dashboard just needed to be restarted. Always compare mtimes before rebuilding.
