Metadata-Version: 2.5
Name: quaestor-cli
Version: 0.4.0
Summary: Command-line client for the Quaestor API — built for humans and agents.
Project-URL: Homepage, https://quaestor.app
Project-URL: Repository, https://github.com/neuromaxer/quaestor-lite
Project-URL: Documentation, https://github.com/neuromaxer/quaestor-lite/blob/main/apps/cli/README.md
Project-URL: Issues, https://github.com/neuromaxer/quaestor-lite/issues
Keywords: agent,ai,cli,habit-tracker,quaestor
Classifier: Development Status :: 4 - Beta
Classifier: Environment :: Console
Classifier: Intended Audience :: End Users/Desktop
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Utilities
Classifier: Typing :: Typed
Requires-Python: >=3.12
Requires-Dist: httpx>=0.27
Requires-Dist: typer>=0.16
Description-Content-Type: text/markdown

# quaestor-cli

`qst` — a command-line client for [Quaestor](https://quaestor.app), an agent-native
platform for diary-based life management. An evening diary becomes tracked habits,
quest progress, and a morning plan.

Built for two users at once: a person in a terminal, and an AI assistant acting on their
behalf. That second audience shapes most of the design — commands are task-shaped rather
than endpoint-shaped, streaks and quests are addressed by name, failures are
distinguishable by exit code, and the server's own error message is printed verbatim so
an agent can relay something true.

```bash
uv tool install quaestor-cli
```

## Setup

Create an API key in the Quaestor web app under **Profile → Developer Access**.
The CLI uses the hosted production API automatically. On macOS, copy the key and run:

```bash
pbpaste | qst auth login
qst doctor
```

On other systems, run `qst auth login`, paste the key, press Enter, then signal
end-of-input (Ctrl-D on Unix).

The key is stored at `~/.config/quaestor/credentials.json` with mode `0600`. The
CLI also supports `QUAESTOR_API_KEY`; an existing environment variable takes
precedence over the file, but it is not needed for this setup.

Logging in again replaces the key while preserving an existing server override.
`qst doctor` reports authentication as unknown when the server cannot verify it;
only an explicit authentication refusal means the key was rejected.

## The evening diary workflow

Spend 10–15 minutes writing or recording your day. Your agent uses `qst` to log
measured habits, record quest progress, and plan the work you want to do tomorrow.
It reports what changed and prepares a short morning plan with Main and Side Quests.

Keep the original diary with your agent or in a place you choose. The CLI stores
habit records and quest-specific notes in Quaestor, not a general diary entry.
Those original entries become a record of your progress and a story worth keeping.

## Commands

```
qst streaks                      List streaks with mode, unit and target
qst show <streak>                Full configuration plus per-day totals, including missed days
qst log <streak> <value>         Log a COUNT amount
qst log <streak> --minutes 45    Log a TIME block (45, 45m, 1h30m, 1.5h)
qst events <streak>              Individual entries, newest first, with the source of each
qst review                       Totals, active days and current streak per streak
qst timer start|stop|status      Control the single running timer
qst auth login|whoami|logout     Manage the stored credential
qst doctor                       Check URL, reachability, credential and granted scopes

qst agenda [--week|--days N]     Overdue, past deadline, ready to plan, and each day's quests
qst quests [words] [filters]     Find quests: --status, --overdue, --on, --from/--to,
                                 --deadline-by, --under <quest>, --archived, --sort, --limit
qst quest show <quest>           Status, dates, sub-quest progress, linked quests, its link, description, latest Quest Log
qst quest log <quest>            Quest Log entries, newest first (--date for one day)
qst quest add <title>            --under <quest> --on fri --due <date> --priority high --emoji 🚀 ...
qst quest edit <quest>           --title --emoji --priority --start/--due (or 'none') --under/--top-level
qst quest status <quest> <s>     backlog | todo | in-progress | done | archived
qst quest archive <quest>        Hide it and its sub-quests (there is no delete)
qst quest plan <quest> <day>...  Plan days; a Backlog quest becomes Todo
qst quest unplan <quest> <day>   Remove a planned day (never demotes)
qst quest reschedule <q> <from> [to]   Move one planned day (to today by default)
qst quest check <quest>          Check off a day (--date, --undo); starts Backlog/Todo quests
qst quest note <quest> <text>    Append to that day's Quest Log entry (--date, --replace)
qst quest link|unlink <quest> <streak>  Link a streak (context only, nothing syncs)
qst quest link-quest|unlink-quest <quest> <other>  Link two related quests (both list each other)
qst quest mention <quest>        Markdown link for a note or description; the app shows it as a chip
```

Every command takes `--json` for machine-readable output on stdout. Every write takes
`--dry-run`, which prints the request and writes nothing. `log` uses a read-only
streak lookup to validate the name, mode and `--unit` before printing the resolved
payload. A COUNT/TIME mismatch or wrong unit exits `1` without posting an event.

### Windows

`events`, `show` and `review` share one set of window flags: `--today`, `--week`
(default), `--days N`, or an explicit `--from` / `--to`. The explicit and relative forms
cannot be combined. Dates accept `today`, `yesterday`, a weekday (`mon`..`sun`, meaning
the most recent past one), `YYYY-MM-DD`, or an offset like `-3d`.

### Streaks are named, never UUIDs

`<streak>` is a name. Resolution tries exact match, then unique prefix, then unique
substring. On zero or multiple matches it exits `3`, lists the candidates, and writes
nothing — it never guesses.

```
$ qst log r 1
Streak 'r' is ambiguous — candidates: Reading, Running. Nothing was written.
```

### Quests are named too — by title or path

`<quest>` is a title, or a path of titles that names the parents as well:
`"Launch > Backend > Schema"` (`›` works too). The server resolves it — exact, then unique
prefix, then unique substring; archived quests only when nothing live matches — and on
zero or several matches `qst` exits `3`, prints the candidates' full paths, and writes
nothing.

```
$ qst quest check "write migration"
Quest 'write migration' is ambiguous — 2 quests match: Launch › Backend › Write migration;
Blog › Write migration. Use a path such as 'Launch > Backend > Write migration' to pick one.
Nothing was written.
```

With `--json`, the failure is one JSON document on stdout: `{"error": {"exit_code": 3,
"message": ..., "candidates": [...]}}`.

### Which way date words point

Where you plan (`add --on/--due/--start`, `plan`, a reschedule target, `agenda`/`quests
--from/--to`), a weekday means the **coming** one: `fri` on a Wednesday is this Friday,
and today if it is Friday; `next fri` is a week later; `+1w` is a week from today.
Where you record (`check --date`, `note --date`, streak commands), a weekday is the most
recent one and `last fri` is strictly before today; `check` refuses future days.
Where you name a day the quest already has (`reschedule`'s first day, `unplan`), a
weekday picks the quest's own date on that weekday within a week of today, in either
direction — so `qst quest reschedule report tue thu` works whether Tuesday was yesterday
or is next week.

### Retrying writes safely

Dropped connections are retried automatically with the same idempotency key. If a write
still fails with exit 4, the message includes the key; re-run with
`qst --idempotency-key <key> ...` (or set `QUAESTOR_IDEMPOTENCY_KEY`) and the server
replays the original write instead of creating a duplicate.

Quest reads send your local date (`today=`), so overdue and "today" match the web app.
Writes that change a status automatically say so (`Status: Todo → In progress.`).

### `--unit` is a safety check, not data

Units belong to the streak, not the event, so `--unit` is never sent to the API. It
asserts what you believe the streak measures and fails before writing if you are wrong —
which is what stops an assistant logging "5 miles" as 5 km.

```
$ qst log running 5 --unit miles
'Running' is measured in km, not miles.
```

## Exit codes

An agent's only reliable error channel, so they are stable:

| Code | Meaning |
| --- | --- |
| 0 | Success |
| 1 | Bad arguments or unparseable input |
| 2 | Authentication failed, or the key lacks the required scope |
| 3 | Unknown or ambiguous streak or quest |
| 4 | Server or network error |

On failure the server's `detail` message is printed verbatim to stderr.

## Scopes

A key only carries the permissions granted when it was created, and the server enforces
them. Insufficient scope returns a message naming what is missing, so it is clear whether
something is a bug or a deliberate restriction:

```
$ qst log reading 5
API key is missing required scope(s): events:write
```

Deleting a streak has no scope at all — it is web-app only, because it also destroys every
event, total and milestone beneath it. The same goes for deleting a quest or a Quest Log
entry: `qst` has no delete command, and a key can archive a quest instead.

Quest commands need `quests:read` (agenda, lists, show, log) and `quests:write`
(everything else, archive included). Both are pre-checked when a key is created; older
keys lack them, and `qst doctor` lists the scopes a key actually holds plus a hint naming
the quest commands that will fail.

## Using this with an AI assistant

The repository ships an [Agent
Skill](https://github.com/neuromaxer/quaestor-lite/blob/main/skills/quaestor/SKILL.md)
that teaches an assistant when and how to use these commands, following the
[agentskills.io](https://agentskills.io) format. Copy it to `~/.agents/skills/` (OpenClaw)
or `~/.hermes/skills/` (Hermes Agent).

Design notes and the security model are in the [feature
documentation](https://github.com/neuromaxer/quaestor-lite/blob/main/docs/features/agent-connect/agent-connect.md).

## Requirements

Python 3.12+. Depends only on `httpx` and `typer` — it speaks HTTP and never imports the
Quaestor backend, so it installs in seconds and tolerates version skew against the server.

## Developer configuration

Use `qst --dev doctor` to target `http://localhost:8000` for that invocation.
The development flag is hidden from normal help and never persists a local URL.

Staging and self-hosted deployments can still use `QUAESTOR_URL` or an existing
`base_url` in the credential store. Resolution order is `--dev`, environment, stored
URL, then the hosted production default. Ordinary hosted setup needs no override.

Quest links (`qst quest mention`, `show`) point at the web app: `https://quaestor.app` by
default, `http://localhost:3000` with `--dev`, or `QUAESTOR_APP_URL` for other deployments.

`qst` refuses to send a key over plain HTTP except to loopback. Set
`QUAESTOR_ALLOW_INSECURE=1` only for deliberate plaintext development deployments.
