# Nyrut CLI

> Invoices, clients, expenses and a quarterly tax estimate, without leaving the shell. The same account, the same data and the same rules as the web app: an invoice created here opens in the browser as an ordinary invoice, because it is one.

Official command-line client for [Nyrut](https://www.nyrut.com/en). Node.js 20 or later. Package: npmjs.com/package/nyrut.

## Install and sign in

```
npm install -g nyrut
nyrut login
```

`nyrut login` opens a loopback server on 127.0.0.1 and sends you to the browser you're already signed into. The web app names the port and asks before handing the session over: a link alone is never enough.

The session is stored at `~/.config/nyrut/session.json` with mode 0600. `nyrut logout` removes it.

## Commands

### `nyrut invoices [options]`

List invoices, most urgent first.

- `--status <s>`: overdue · unpaid · draft · paid
- `--client <name>`: only this client (partial name is fine)
- `--limit <n>`: how many to show (default 20)
- `--all`: no limit
- `--json`: raw invoice objects, no formatting

```
nyrut invoices --status overdue
nyrut invoices --client etéreo --all
nyrut invoices --json | jq '.[].numero'
```

> Overdue first, then unpaid, then the rest. The footer is the point: what you are owed, and how much of it is late.

### `nyrut invoice <number>`

Draw one invoice.

Subcommands: `invoice new`, `invoice send`, `invoice pay`, `invoice link`, `invoice open`.

- `--plain`: no animation
- `--json`: the raw invoice object

```
nyrut invoice 2026-014
nyrut invoice 014
```

> A partial number works if it matches exactly one invoice; if it matches several, you are told which rather than guessed at. This is a preview — the PDF is made in the browser, see nyrut invoice open.

### `nyrut invoice new [options]`

Create an invoice.

- `--issuer <name>`: skip the issuer prompt
- `--client <name>`: skip the client prompt
- `--date <YYYY-MM-DD>`: issue date (default today)
- `--due <YYYY-MM-DD>`: due date (default from the client's terms)

```
nyrut invoice new
nyrut invoice new --client etéreo --issuer nafs
```

> It saves a DRAFT. The number is reserved, nothing is issued, and sending is a separate deliberate step. VAT and withholding come from where your workspace files and where the client is — not from a default.

### `nyrut invoice send <number> [options]`

Email the invoice to the client.

- `--to <email>`: someone other than the client's address
- `--subject <text>`: your own subject line
- `--yes`: skip the confirmation

```
nyrut invoice send 2026-014
nyrut invoice send 2026-014 --to pagos@cliente.com
```

> Shows recipient and total and asks first, because sending cannot be undone. A draft becomes issued the moment it leaves.

### `nyrut invoice pay <number> [options]`

Mark an invoice paid.

- `--date <YYYY-MM-DD>`: when it was actually paid (default today)
- `--undo`: back to unpaid

```
nyrut invoice pay 2026-014
nyrut invoice pay 2026-014 --date 2026-08-01
```

### `nyrut invoice link <number>`

Public link to share the invoice.

```
nyrut invoice link 2026-014
nyrut invoice link 2026-014 | pbcopy
```

> Creates the link the first time and reuses it after. Anyone holding it can see the invoice — the URL is the credential. The warning goes to stderr so piping copies only the link.

### `nyrut invoice open <number>`

Open the invoice in the browser.

```
nyrut invoice open 2026-014
```

> Where the PDF lives, and where you can edit it.

### `nyrut clients`

Your clients and what each still owes.

- `--json`: raw client objects

### `nyrut issuers`

Your issuing entities.

- `--json`: raw issuer objects

> The type column decides which tax forms apply: an individual files modelo 130, a company does not.

### `nyrut expenses [options]`

Expenses you have recorded.

- `--year <YYYY>`: only this year
- `--limit <n>`: how many (default 20)
- `--all`: no limit
- `--json`: raw expense objects

### `nyrut summary [options]`

VAT by quarter, for one issuer.

- `--year <YYYY>`: which year (default this one)
- `--issuer <name>`: which issuer (default the first)
- `--json`: the quarters as data

```
nyrut summary
nyrut summary --year 2025 --issuer nafs
```

> One issuer at a time, always: VAT is filed per tax ID, so adding two together produces a number matching no return anyone will ever file. Invoices in another currency are excluded and counted — converting them needs the ECB rate per date, which the app fetches. An estimate to check against, not a filing.

### `nyrut login`

Sign in through your browser.

> Opens a loopback server on 127.0.0.1 and sends you to the browser you are already signed into. The web app names the port and asks before handing anything over. The token is stored at ~/.config/nyrut/session.json with mode 0600.

### `nyrut logout`

Forget the session on this machine.

### `nyrut whoami`

Who you are signed in as.

## Scripting

- `--json` works on every listing, and it's a separate code path: no colour, no padding, no headers.
- Colour never carries meaning: every line reads correctly through `| cat`, on a dumb terminal and under `NO_COLOR`.
- Animation stops when nobody is watching: not a TTY, piped, `CI`, `NO_COLOR` or `--plain`.
- Spinners go to stderr, so `nyrut invoice link 2026-014 | pbcopy` copies the URL and nothing else.
- Unknown options are an error: `--stauts=paid` won't silently list every invoice.

## Taxes

`nyrut summary` runs the app's own 303 and 130 calculations, one issuer at a time (VAT is filed per tax ID). Invoices in another currency are excluded and counted, because converting them needs the ECB rate of each invoice's date. It's an estimate to check against, not a filing.
