# Coding companion

Nur phones you when Claude Code or Codex finishes, answers your questions, runs what you ask for in the same session and calls back. Call or text its code line to get work done, or its live line to talk.

Start a task with your coding agent and walk away. When it finishes, Nur calls
your phone: what you asked for, what the agent did, the files it touched and
how the code moved. Ask it anything about the run. Ask for more work, and when
you hang up Nur runs it in the same agent session, then calls you back with
what it did, or with why it could not run. Say "that's all" and Nur hangs up.

| Line | Number | |
| --- | --- | --- |
| Nur Code | +1 (437) 782-2633 (437-782-CODE) | Call or text to get work done on your code, with `eesi companion listen` running |
| Nur | +1 (437) 782-2634, next door to the code line | Call or text to talk with Nur. Anyone can: no setup |

## Set up

<Steps>
<Step title="Install the SDK">
It puts an `eesi` command on your path.

```bash
uv tool install git+https://github.com/eesi-ai/eesi-sdk-python
# or: pipx install git+https://github.com/eesi-ai/eesi-sdk-python
```
</Step>
<Step title="Confirm your number">
Your API key comes from the API keys page of the EESI console. Nur texts the
number a six-digit code (`--by call` reads it on a call instead); enter it.

```bash
eesi companion setup --phone +14155550123 --name Sam --api-key sk-eesi-...
eesi companion confirm 482917
```

The settings are kept in `~/.eesi/companion.json`, readable by you only.
</Step>
<Step title="Connect your agent">
<CodeGroup>
```text Claude Code
/plugin marketplace add eesi-ai/eesi-sdk-python
/plugin install nur-companion@eesi
```

```toml Codex (~/.codex/config.toml)
notify = ["eesi", "companion", "codex-notify"]
```
</CodeGroup>

In Claude Code, `/nur-companion:setup` does the second step from inside the
session, and `/nur-companion:call-me` asks for an update now.
</Step>
</Steps>

`eesi companion status` shows the settings and the confirmed numbers.

## When Nur calls

By default, after a turn of at least three minutes and when a session ends.
`eesi companion setup --call-on stop` calls after every turn, `never` turns it
off, and `min_minutes` sets the threshold. The hook returns at once and the
call runs in the background, so the agent never waits.

## What Nur knows

A briefing written on your machine from the session's transcript and `git`:
what you asked for, what the agent said when it finished, the files it wrote,
the commands it ran and how many steps failed, lines added and removed since
the last commit, new files, commits today and languages by lines. It is the
call's instructions, so it is kept with the call like any session of your
organization.

## Follow-ups and call backs

After the call, what you asked for is read off its transcript and run in the
same session: `claude -p --resume <session>` (flags in `claude_args`, default
`--permission-mode acceptEdits`) or `codex exec resume <thread>` (`codex_args`,
default `--sandbox workspace-write` with approvals off). The companion waits
for it, up to `follow_up_minutes` (60), and calls back with what the agent
said, or with why it could not run (the agent's command line missing or signed
out, say). A call back can bring the next request; the loop ends on a call that
asks for nothing more. Turn follow-ups off with `follow_up: false`.

## Call Nur: the code line

You can also call Nur. Start the listener beside your repository:

```bash
eesi companion listen            # Claude Code; --agent codex for Codex
```

It prints the code line's number (437-782-CODE). Call it from your confirmed
phone and say what to build. When you hang up, what you asked for is queued and run in one
coding session, each task resuming the last, and Nur calls you when a task is
done (unless `call_on` is `never`). Call again any time. Nur knows what is
running and its latest steps (the files it edited, the commands it ran), what
is queued, what is done and how the code moved. Ask for more and it joins the
queue.

The listener keeps briefing the line every few seconds; everything about your
code stays on your computer until a brief carries it to a call. Only the phone
the listener answers for (`eesi companion setup --phone`) hears about your
code: anyone else your organization confirmed reaches Nur, never the code.
Caller ID can be forged, so the code line talks only when the phone carrier
vouches for the caller (STIR/SHAKEN). Otherwise Nur says it will call you right
back, hangs up, and calls your confirmed number, which a forger cannot answer.
Nur calls a number back at most three times an hour.

## Talk to Nur: the live line

The live line, 437-782-2634, is Nur with nothing to report: call or text it any
time to talk, in any language. Anyone can, with no setup: a caller nobody
confirmed gets five calls a day of up to ten minutes and thirty texts, paid by
EESI. A confirmed caller the carrier does not vouch for is called back, like on
the code line. Where one number serves both lines, it is your coding companion while
`eesi companion listen` runs, and Nur to talk to when it does not.

## Text Nur

Both lines take texts from your confirmed phone. Text the code line to ask how
it is going ("is the login page done?") or to add work ("also add a logout
button"): Nur answers from the listener's live facts. A text's sender can be
forged, so work asked for by text waits for a six-digit code Nur texts back:
reply with it from the same phone within fifteen minutes and the work is
queued like a request on a call. Text the live line to chat; Nur keeps the
day's texts in mind.

`eesi companion listen --notify text` texts you when a task is done instead of
calling (`both` does both). Reply to that text and it reaches Nur.

Texts to the lines need the numbers set up for messaging with the carrier
(`POST /v1/phone/messages/inbound` is the inbound webhook). A number that texts
a line more than 60 times an hour stops getting replies, and an organization
sends at most 200 texts a day; `POST /v1/phone/messages` texts a confirmed
number from the code line.

## Confirmed numbers

On the shared EESI line, Nur calls and texts only numbers confirmed with a code,
so an API key can make Nur call its owner and never a stranger. The code comes
by text, or read by the phone carrier's own voice on a call (a text the carrier
refuses becomes a call); either way it never reaches a transcript. A number gets
one code a minute and five a day from all organizations together, an
organization five a day, and a code lasts ten minutes and five tries (fifteen
a day for a number, whoever makes them). An organization places at most thirty
calls an hour on the shared line. Organizations that call through their own carrier account confirm
nothing for the calls they place. The code line answers only confirmed
numbers; the live line answers anyone.

## Calls from your own code

The companion is built on one API: have Nur call a confirmed number about
anything.

```python
await nur.verify_phone_number("+14155550123")              # Nur texts a code
await nur.confirm_phone_number("+14155550123", "482917")
call = await nur.call("+14155550123", instructions="You are Nur... the facts: ...", greeting="Hi Sam, it's Nur.")
ended = await nur.wait_for_call(call.id)                    # status, duration and transcript
```

`POST /v1/phone/calls` places a call and `GET /v1/phone/calls/{id}` reads it
back; `/v1/phone/numbers` lists, confirms and forgets numbers. Nur can end the
calls it places: when the conversation is over or the person asks, it says
goodbye and hangs up.
