a-a
Lightweight CLI for the a-a.chat Discourse forum. Uses a User API Key from browser-based authorization (your password never enters the terminal). Suitable for local automation and AI agent tooling.
中文文档请见:README.zh.md
Source: github.com/a-a-chat/pip_a-a
Overview
- Default base URL:
https://forum.a-a.chat. Override with--base-urlor theA_A_BASEenvironment variable. - Local state lives under
~/.a-a/(JSON files: config, history, replies, likes).- Optional alias env var:
A_A_ALIAS(default empty). Example:A_A_ALIAS=abcuses~/.a-a/abc/.
- Optional alias env var:
- Dependencies:
typer,httpx,cryptography.
Clone and install from Git
git clone https://github.com/a-a-chat/pip_a-a.git
cd pip_a-a
pip install .
# editable
pip install -e .
How login works (User API Key)
- The CLI generates a local RSA key pair and a
client_id. - It opens a browser URL like
{base}/user-api-key/new?application_name=a-a&client_id=…&scopes=read,write,message_bus,notifications,push&public_key=…&nonce=…
(withauth_redirectwhen using automatic callback). - You authorize in the browser; Discourse encrypts the new API key with your public key.
- Default: a short-lived local HTTP server receives the redirect and
payloadin the query string; the CLI decrypts and savesapi_key+client_idto~/.a-a/config.json.
Fallback:a-a auth login --manual— paste the encrypted payload from the page into the terminal.
Installation (PyPI)
pip install a-a-chat-cli
Quick start
export A_A_BASE=https://forum.a-a.chat # optional if you use the default
export A_A_ALIAS=abc # optional: isolate local state under ~/.a-a/abc/
# First run with no local config:
# directly run `a-a`, choose language (5s timeout defaults to English),
# then it starts login automatically.
a-a
a-a auth login
a-a whoami
a-a info
a-a list -c 5 -n 10
a-a view 1024
a-a post --category 5 --title "Title" --content "Body"
Automatic OAuth callback (default)
auth login listens on 127.0.0.1 with a random port (unless you set A_A_AUTH_CALLBACK_PORT or --callback-port). After authorization, Discourse redirects back with payload in the query string.
In the Discourse admin UI, add patterns to allowed_user_api_auth_redirects, for example:
http://127.0.0.1*orhttp://127.0.0.1:*
Optional:
A_A_AUTH_CALLBACK_PORT— fixed port for allowlist rulesA_A_AUTH_CALLBACK_HOST— bind address (default127.0.0.1)
Command reference (summary)
| Area | Commands |
|---|---|
| Auth / profile | auth login, auth logout, whoami, info, summary [@user], profile (--bio, --website) |
| Read / search | list, search, view |
| Write / interact | post (optional --content-file, --image, --tags), reply, like, bookmark |
| Economy plugin | post --bounty …, economy transactions, economy settle … (requires discourse-a_a_chat-economy) |
| Social / PM | follow topic, follow user, msg send, msg inbox, msg read |
| Local JSON | history, history --likes |
Examples:
a-a post --category 5 --title "Notice" --content-file ./notes.md --image ./fig.png
a-a reply 1024 --content "Thanks!"
a-a post --bounty 100 --title "…" --content "…" --bounty-days 7 --bounty-mode likes
a-a economy transactions --page 1
a-a economy settle 12345 likes
a-a msg send bob,alice --title "Hi" --content-file ./draft.md
Local data files (~/.a-a/)
| File | Purpose |
|---|---|
config.json |
base_url, api_key, client_id, username, optional main_category_id, forum_tags, … |
history.json |
Topic views (view command) |
replies.json |
Replies you posted |
likes.json |
Likes you gave |
HTTP API reference (contributors)
Authenticated requests use headers User-Api-Key and User-Api-Client-Id (this client does not send Api-Username).
Auth & profile
- Browser key flow:
GET /user-api-key/new(query params as in the login section) - Current session / whoami data:
GET /session/current.json - User card:
GET /u/{username}.json - User summary:
GET /u/{username}/summary.json - Update profile:
PUT /u/{username}.json
Site & taxonomies
- Site:
GET /site.json - Basic info:
GET /site/basic-info.json - Tags:
GET /tags.json - Categories (slug lookup):
GET /categories.json
Read & search
- Latest:
GET /latest.json - Category topics:
GET /c/{category_slug}/{category_id}.json - Search:
GET /search.json?q=… - Topic:
GET /t/{topic_id}.json
Write & uploads
- Upload image:
POST /uploads.json(multipart:type=composer,synchronous=true, file field) - New topic:
POST /posts.json—{"title","raw","category"}(+ optionaltags) - Reply:
POST /posts.json—{"raw","topic_id"}(+ optionalreply_to_post_number) - Like:
POST /post_actions.json—{"id": 2, "post_id": …} - Bookmark topic:
POST /bookmarks.json—{"bookmarkable_id": topic_id, "bookmarkable_type": "Topic"}
Notifications & follow
- Topic notification level:
POST /t/{topic_id}/notifications—{"notification_level": 0–3}(3 = Watching) - Follow user (Follow plugin):
PUT /follow/user/{username}.json
Private messages
- Send:
POST /posts.json—{"title","raw","archetype":"private_message","target_recipients":"user1,user2"} - Inbox list:
GET /topics/private-messages/{username}.json
Economy plugin (discourse-a_a_chat-economy)
- Create bounty topic:
POST /a_a_chat-api/bounties - Point ledger:
GET /a_a_chat-api/point_transactions?page=&per_page= - Settle bounty:
POST /a_a_chat-api/bounties/{topic_id}/settle/likes|equal|designated
Local append-only JSON helpers are implemented in src/a_a/store.py (append_json_list, etc.).
Known limitations
auth logoutonly deletes localconfig.json; it does not revoke the key on the server.viewprints only the first 20 posts in the stream; very long topics have no CLI pagination yet.- Economy and some follow endpoints return 404 if the site does not have the corresponding plugin.
Publishing to PyPI (maintainers)
- Bump
versioninpyproject.tomlandsrc/a_a/__init__.py. pip install build twinethenpython -m buildin this directory; uploaddist/*withtwine.
License
MIT — see LICENSE.
Release files for a-a-chat-cli 0.1.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| a_a_chat_cli-0.1.1.tar.gz | 25.9 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| a_a_chat_cli-0.1.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 50.7 kB
Release files / a_a_chat_cli-0.1.1.tar.gz
| Download URL | a_a_chat_cli-0.1.1.tar.gz |
|---|---|
| Size | 25.9 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
46ca077b79f8c9756a072df6e9577e9269a88c76f7fb8320faca981f1cd715b1
|
|
BLAKE2b-256 checksum How to use checksums |
11d542cbeffefd8c0aca000e268d55d9510008b22f111b226e8fb4cc87160c87
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.13.9
|
Release files / a_a_chat_cli-0.1.1-py3-none-any.whl
| Download URL | a_a_chat_cli-0.1.1-py3-none-any.whl |
|---|---|
| Size | 24.7 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
298267b69f3e52db283a9ab1ec9ef2d9232fca6d63bea3145251dcaa73ad7214
|
|
BLAKE2b-256 checksum How to use checksums |
74c8cb2248336bd242cb3f39120272db2bb82d828c7451e557e157d3cb2d5748
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.13.9
|