# tuipub A terminal [Micropub](https://micropub.spec.indieweb.org/) client for posting notes to your IndieWeb site. It logs in with [IndieAuth](https://indieauth.spec.indieweb.org/) and is built with Rust and [Ratatui](https://ratatui.rs). It's developed against StarPunk, but sticks to the spec, so other Micropub servers should work too. ## Install ```sh cargo install --path . ``` ## Use ```sh tuipub login example.com # opens your browser to approve access tuipub # write and publish a note tuipub whoami # show the account and endpoints tuipub logout # revoke the token and forget the account ``` Running `tuipub` with no account starts the login flow first. ### Writing (compose screen) | Key | Action | | --- | --- | | Tab / Shift-Tab | Next / previous field (Title, In reply to, Note, Tags, Crosspost) | | Ctrl-S | Publish or save. The confirm dialog offers **d** (draft) / **p** (publish) | | Ctrl-P | Your posts | | Ctrl-N | New note (asks before discarding changes) | | Ctrl-R | Reload crosspost targets from the server | | Ctrl-O | Open the last published post | | Esc | Quit, or back to the post list while editing (asks if there are unsaved changes) | | ↑ ↓ / j k, Space, a | Crosspost list: move, toggle, all/none | When editing, saving sends only the fields you changed. Crosspost targets can't be changed after posting, but StarPunk updates existing crossposts when you edit. ### Your posts (Ctrl-P) | Key | Action | | --- | --- | | ↑ ↓ / j k | Move (scrolling past the end loads more) | | Enter / e | Edit | | p | Publish a draft | | d | Delete (asks first) | | u | Undo the last delete | | o | Open in the browser | | n | New note | | r | Reload | | Esc | Back to writing | Ctrl-Q quits from anywhere. Content is sent as written (Markdown for StarPunk). Tags are comma-separated, and a leading `#` is dropped. "In reply to" must be an http(s) URL. ## How it works - **Discovery**: reads `rel="micropub"` and `rel="indieauth-metadata"` from your site's `Link` headers and HTML. If there's no metadata link, it falls back to `authorization_endpoint` / `token_endpoint`. - **Login**: authorization code flow with PKCE (S256). tuipub runs a one-shot callback server on `127.0.0.1:` and uses `http://127.0.0.1:/` as its `client_id`. The client ID and redirect URI share an origin, so the server needs no client registration. It checks `state` and `iss`. Scopes requested: `create update delete media`. Tokens from older tuipub versions only had `create media`; run `tuipub login` again to edit and delete. - **Token storage**: the system keyring (Secret Service / gnome-keyring), keyed by your profile URL. Account settings go in `~/.config/tuipub/config.toml`. - **Posts list**: `q=source` without `url` (`limit`/`offset`, drafts included). Edits are Micropub `update` with `replace`/`delete`; deletes are `delete`/`undelete`; drafts are `post-status: draft`. - **Posting**: always sends a JSON body. `mp-syndicate-to` lists exactly the checked targets, and an empty list means "crosspost nowhere". If the target list can't be loaded, `mp-syndicate-to` is left out and the server's default applies (the confirm dialog says so). ### Environment - `TUIPUB_TOKEN`: use this token instead of the keyring (e.g. one made in StarPunk's `/admin/tokens`). - `TUIPUB_CONFIG_DIR`: use a different config directory (handy for dev servers). ## StarPunk notes - StarPunk 2.3.3+ stores the Title as the note's `# Heading` first line. Older versions ignore it, so on those, start the note with `# Heading` instead. - Listing, editing, deleting, drafts and replies need StarPunk 2.4.0+. tuipub hides the post list when a server says it can't list posts (`q` in `q=config`). ## Develop ```sh cargo test cargo clippy --all-targets -- -D warnings ``` To try it against a local StarPunk, start it with `DEV_MODE=true`, `SITE_URL`/`ADMIN_ME`/`DEV_ADMIN_ME=http://127.0.0.1:8099/`, then run `TUIPUB_CONFIG_DIR=/tmp/tp tuipub login 127.0.0.1:8099`. Bare `localhost` / `127.*` addresses default to `http://`.