Metadata-Version: 2.4
Name: daknode-cli
Version: 0.3.0
Summary: DakNode's email API from a terminal. JSON to stdout by default.
Project-URL: Homepage, https://daknode.com
Project-URL: Documentation, https://daknode.com/developers
Requires-Python: >=3.9
Description-Content-Type: text/markdown
Requires-Dist: daknode<0.4,>=0.3

# DakNode CLI

The API from a terminal. JSON to stdout by default, because the caller is as
likely to be a script as a person.

## Install

```bash
pipx install daknode-cli      # or: pip install daknode-cli
```

Get an API key with the two-request signup at <https://daknode.com/developers>.

```bash
export DAKNODE_API_KEY=…

daknode inboxes create
daknode threads list --inbox-id … --limit 10
daknode threads get <thread_id>
daknode messages list --inbox-id …
daknode messages get <message_id>
daknode search --query "invoice from stripe"
daknode send --inbox-id … --to … --subject … --body … [--thread-id …]
```

From a repository checkout, `python -m cli.main` runs the same commands.

`--format table` for reading. `--dry-run` on `send` prints the request and
exits without sending it — a command that emails a real person deserves a way
to be inspected first.

## Exit codes

| | |
| --- | --- |
| `0` | success |
| `2` | the API refused the request |
| `3` | the API could not be reached |
| `4` | `DAKNODE_API_KEY` is not set |

`2` and `3` are separate on purpose: a script retrying a network failure must
not retry a `422` forever.

## Two deliberate constraints

**No credential flag.** The key comes from the environment only. argv is visible
to every process through `ps`, and shells record it in history. A test walks the
parser and fails if any flag name contains `key` or `token`.

**No third-party dependency.** `argparse` from the standard library, plus the
first-party generated SDK. Click and Typer are nicer to write against — and one
day before this was written, installing `mcp` silently upgraded a pinned
`pydantic` and changed the API's published OpenAPI output. Every dependency here
is another chance to move a pin production depends on. A test enumerates the
imports and fails on anything new.

**`send --thread-id` replies into a conversation**; without it the message opens
a new one in the recipient's client.
