commune-cli 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- commune_cli-0.1.0/.gitignore +82 -0
- commune_cli-0.1.0/PKG-INFO +243 -0
- commune_cli-0.1.0/README.md +214 -0
- commune_cli-0.1.0/commune_cli/__init__.py +3 -0
- commune_cli-0.1.0/commune_cli/client.py +111 -0
- commune_cli-0.1.0/commune_cli/commands/__init__.py +1 -0
- commune_cli-0.1.0/commune_cli/commands/attachments.py +127 -0
- commune_cli-0.1.0/commune_cli/commands/config_cmd.py +89 -0
- commune_cli-0.1.0/commune_cli/commands/data.py +130 -0
- commune_cli-0.1.0/commune_cli/commands/delivery.py +126 -0
- commune_cli-0.1.0/commune_cli/commands/dmarc.py +81 -0
- commune_cli-0.1.0/commune_cli/commands/domains.py +158 -0
- commune_cli-0.1.0/commune_cli/commands/inboxes.py +282 -0
- commune_cli-0.1.0/commune_cli/commands/messages.py +143 -0
- commune_cli-0.1.0/commune_cli/commands/search.py +56 -0
- commune_cli-0.1.0/commune_cli/commands/threads.py +247 -0
- commune_cli-0.1.0/commune_cli/commands/webhooks.py +130 -0
- commune_cli-0.1.0/commune_cli/config.py +123 -0
- commune_cli-0.1.0/commune_cli/errors.py +114 -0
- commune_cli-0.1.0/commune_cli/main.py +106 -0
- commune_cli-0.1.0/commune_cli/output.py +191 -0
- commune_cli-0.1.0/commune_cli/state.py +37 -0
- commune_cli-0.1.0/pyproject.toml +47 -0
- commune_cli-0.1.0/uv.lock +534 -0
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
node_modules/
|
|
2
|
+
**/node_modules/
|
|
3
|
+
|
|
4
|
+
# Python
|
|
5
|
+
__pycache__/
|
|
6
|
+
*.py[cod]
|
|
7
|
+
*$py.class
|
|
8
|
+
*.so
|
|
9
|
+
.Python
|
|
10
|
+
build/
|
|
11
|
+
develop-eggs/
|
|
12
|
+
dist/
|
|
13
|
+
downloads/
|
|
14
|
+
eggs/
|
|
15
|
+
.eggs/
|
|
16
|
+
/lib/
|
|
17
|
+
/lib64/
|
|
18
|
+
parts/
|
|
19
|
+
sdist/
|
|
20
|
+
var/
|
|
21
|
+
wheels/
|
|
22
|
+
*.egg-info/
|
|
23
|
+
.installed.cfg
|
|
24
|
+
*.egg
|
|
25
|
+
MANIFEST
|
|
26
|
+
|
|
27
|
+
# Virtual environments
|
|
28
|
+
venv/
|
|
29
|
+
.venv/
|
|
30
|
+
env/
|
|
31
|
+
ENV/
|
|
32
|
+
env.bak/
|
|
33
|
+
venv.bak/
|
|
34
|
+
|
|
35
|
+
# IDEs
|
|
36
|
+
.vscode/
|
|
37
|
+
.idea/
|
|
38
|
+
*.swp
|
|
39
|
+
*.swo
|
|
40
|
+
*~
|
|
41
|
+
|
|
42
|
+
# OS
|
|
43
|
+
.DS_Store
|
|
44
|
+
.DS_Store?
|
|
45
|
+
._*
|
|
46
|
+
.Spotlight-V100
|
|
47
|
+
.Trashes
|
|
48
|
+
ehthumbs.db
|
|
49
|
+
Thumbs.db
|
|
50
|
+
|
|
51
|
+
# Logs
|
|
52
|
+
*.log
|
|
53
|
+
logs/
|
|
54
|
+
|
|
55
|
+
# Environment variables
|
|
56
|
+
.env
|
|
57
|
+
.env.local
|
|
58
|
+
.env.development.local
|
|
59
|
+
.env.test.local
|
|
60
|
+
.env.production.local
|
|
61
|
+
|
|
62
|
+
# Build artifacts
|
|
63
|
+
dist/
|
|
64
|
+
build/
|
|
65
|
+
.next/
|
|
66
|
+
.cache/
|
|
67
|
+
|
|
68
|
+
# Remotion
|
|
69
|
+
# ./remotion
|
|
70
|
+
|
|
71
|
+
# Video files
|
|
72
|
+
*.mp4
|
|
73
|
+
*.mov
|
|
74
|
+
*.avi
|
|
75
|
+
*.mkv
|
|
76
|
+
|
|
77
|
+
# Large/generated folders
|
|
78
|
+
.pytest_cache/
|
|
79
|
+
.mypy_cache/
|
|
80
|
+
.ruff_cache/
|
|
81
|
+
*.egg-info/
|
|
82
|
+
pip-wheel-metadata/
|
|
@@ -0,0 +1,243 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: commune-cli
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Official CLI for the Commune email API — agent-native, pipe-friendly, covers every API surface.
|
|
5
|
+
Project-URL: Homepage, https://commune.email
|
|
6
|
+
Project-URL: Documentation, https://docs.commune.email
|
|
7
|
+
Project-URL: Repository, https://github.com/commune-email/commune
|
|
8
|
+
License: MIT
|
|
9
|
+
Keywords: agent,ai,cli,commune,email
|
|
10
|
+
Classifier: Development Status :: 4 - Beta
|
|
11
|
+
Classifier: Environment :: Console
|
|
12
|
+
Classifier: Intended Audience :: Developers
|
|
13
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
14
|
+
Classifier: Programming Language :: Python :: 3
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
19
|
+
Classifier: Topic :: Communications :: Email
|
|
20
|
+
Classifier: Topic :: Utilities
|
|
21
|
+
Requires-Python: >=3.9
|
|
22
|
+
Requires-Dist: cryptography>=41.0.0
|
|
23
|
+
Requires-Dist: httpx>=0.27.0
|
|
24
|
+
Requires-Dist: platformdirs>=4.0.0
|
|
25
|
+
Requires-Dist: rich>=13.0.0
|
|
26
|
+
Requires-Dist: tomli>=2.0.0; python_version < '3.11'
|
|
27
|
+
Requires-Dist: typer>=0.12.0
|
|
28
|
+
Description-Content-Type: text/markdown
|
|
29
|
+
|
|
30
|
+
# commune-cli
|
|
31
|
+
|
|
32
|
+
Official command-line interface for the [Commune](https://commune.email) email API.
|
|
33
|
+
|
|
34
|
+
Covers every API surface: domains, inboxes, messages, threads, attachments, search, delivery analytics, webhooks, DMARC, and data deletion.
|
|
35
|
+
|
|
36
|
+
---
|
|
37
|
+
|
|
38
|
+
## Install
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
pip install commune-cli
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
Requires Python ≥ 3.9.
|
|
45
|
+
|
|
46
|
+
---
|
|
47
|
+
|
|
48
|
+
## Quick Start
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
# Set your API key
|
|
52
|
+
export COMMUNE_API_KEY=comm_...
|
|
53
|
+
|
|
54
|
+
# Send an email
|
|
55
|
+
commune messages send \
|
|
56
|
+
--to recipient@example.com \
|
|
57
|
+
--subject "Hello from CLI" \
|
|
58
|
+
--text "Sent from the terminal."
|
|
59
|
+
|
|
60
|
+
# List inboxes
|
|
61
|
+
commune inboxes list
|
|
62
|
+
|
|
63
|
+
# JSON output (automatic when stdout is piped)
|
|
64
|
+
commune inboxes list --json | jq '.data[].email'
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
---
|
|
68
|
+
|
|
69
|
+
## Authentication
|
|
70
|
+
|
|
71
|
+
Set your API key in one of these ways (highest priority wins):
|
|
72
|
+
|
|
73
|
+
| Priority | Source |
|
|
74
|
+
|----------|--------|
|
|
75
|
+
| 1 | `--api-key` flag |
|
|
76
|
+
| 2 | `COMMUNE_API_KEY` env var |
|
|
77
|
+
| 3 | `~/.commune/config.toml` → `api_key` |
|
|
78
|
+
|
|
79
|
+
Store permanently:
|
|
80
|
+
|
|
81
|
+
```bash
|
|
82
|
+
commune config set api_key comm_...
|
|
83
|
+
commune config show
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
---
|
|
87
|
+
|
|
88
|
+
## Output
|
|
89
|
+
|
|
90
|
+
- **TTY**: rich tables and panels with color
|
|
91
|
+
- **Piped / `--json`**: clean JSON to stdout; status messages to stderr
|
|
92
|
+
|
|
93
|
+
```bash
|
|
94
|
+
# JSON list format (always consistent)
|
|
95
|
+
commune threads list --json
|
|
96
|
+
# {"data": [...], "has_more": false, "next_cursor": null}
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
---
|
|
100
|
+
|
|
101
|
+
## Exit Codes
|
|
102
|
+
|
|
103
|
+
| Code | Meaning |
|
|
104
|
+
|------|---------|
|
|
105
|
+
| 0 | Success |
|
|
106
|
+
| 1 | API / validation error |
|
|
107
|
+
| 2 | Auth error (401/403) |
|
|
108
|
+
| 3 | Not found (404) |
|
|
109
|
+
| 4 | Rate limit or plan gate (429/403) |
|
|
110
|
+
| 5 | Network / connection error |
|
|
111
|
+
|
|
112
|
+
---
|
|
113
|
+
|
|
114
|
+
## Error Format (stderr)
|
|
115
|
+
|
|
116
|
+
```json
|
|
117
|
+
{"error": {"code": "not_found", "message": "Inbox not found.", "status_code": 404}}
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
---
|
|
121
|
+
|
|
122
|
+
## Commands
|
|
123
|
+
|
|
124
|
+
```
|
|
125
|
+
commune
|
|
126
|
+
├── config
|
|
127
|
+
│ ├── set <key> <value>
|
|
128
|
+
│ ├── get <key>
|
|
129
|
+
│ ├── show [--reveal]
|
|
130
|
+
│ ├── unset <key>
|
|
131
|
+
│ └── path
|
|
132
|
+
│
|
|
133
|
+
├── domains
|
|
134
|
+
│ ├── list [--limit] [--cursor]
|
|
135
|
+
│ ├── get <domain-id>
|
|
136
|
+
│ ├── create <name>
|
|
137
|
+
│ ├── verify <domain-id>
|
|
138
|
+
│ └── records <domain-id>
|
|
139
|
+
│
|
|
140
|
+
├── inboxes
|
|
141
|
+
│ ├── list [--domain-id] [--limit] [--cursor]
|
|
142
|
+
│ ├── get <inbox-id>
|
|
143
|
+
│ ├── create [--local-part] [--domain-id] [--name] [--webhook-url]
|
|
144
|
+
│ ├── update <inbox-id> [--name] [--webhook-url]
|
|
145
|
+
│ ├── delete <inbox-id> --domain-id [--yes]
|
|
146
|
+
│ ├── set-webhook <inbox-id> --domain-id --url
|
|
147
|
+
│ └── extraction-schema
|
|
148
|
+
│ ├── set <inbox-id> --domain-id --schema <json>
|
|
149
|
+
│ └── remove <inbox-id> --domain-id
|
|
150
|
+
│
|
|
151
|
+
├── messages
|
|
152
|
+
│ ├── send --to --subject [--text] [--html] [--from] [--inbox-id] [--domain-id]
|
|
153
|
+
│ │ [--cc] [--bcc] [--reply-to] [--thread-id]
|
|
154
|
+
│ └── list [--inbox-id] [--domain-id] [--sender] [--limit] [--order] [--before] [--after]
|
|
155
|
+
│
|
|
156
|
+
├── threads
|
|
157
|
+
│ ├── list [--inbox-id] [--domain-id] [--limit] [--cursor] [--order]
|
|
158
|
+
│ ├── messages <thread-id> [--limit] [--order] [--cursor]
|
|
159
|
+
│ ├── metadata <thread-id>
|
|
160
|
+
│ ├── set-status <thread-id> <open|needs_reply|waiting|closed>
|
|
161
|
+
│ ├── assign <thread-id> [--to <user>]
|
|
162
|
+
│ └── tags
|
|
163
|
+
│ ├── add <thread-id> <tag...>
|
|
164
|
+
│ └── remove <thread-id> <tag...>
|
|
165
|
+
│
|
|
166
|
+
├── attachments
|
|
167
|
+
│ ├── upload <file>
|
|
168
|
+
│ ├── get <attachment-id>
|
|
169
|
+
│ └── url <attachment-id> [--expires-in]
|
|
170
|
+
│
|
|
171
|
+
├── search
|
|
172
|
+
│ └── threads <query> [--inbox-id] [--domain-id] [--limit]
|
|
173
|
+
│
|
|
174
|
+
├── delivery
|
|
175
|
+
│ ├── metrics [--domain-id] [--inbox-id] [--period]
|
|
176
|
+
│ ├── events [--domain-id] [--inbox-id] [--limit]
|
|
177
|
+
│ └── suppressions [--domain-id] [--inbox-id] [--limit]
|
|
178
|
+
│
|
|
179
|
+
├── webhooks
|
|
180
|
+
│ ├── list [--inbox-id] [--status] [--endpoint] [--limit]
|
|
181
|
+
│ ├── get <delivery-id>
|
|
182
|
+
│ ├── retry <delivery-id>
|
|
183
|
+
│ └── health
|
|
184
|
+
│
|
|
185
|
+
├── dmarc
|
|
186
|
+
│ ├── reports <domain> [--limit]
|
|
187
|
+
│ └── summary <domain> [--days]
|
|
188
|
+
│
|
|
189
|
+
└── data
|
|
190
|
+
├── delete-request [--email] [--inbox-id] [--domain-id]
|
|
191
|
+
├── delete-confirm <id> [--yes]
|
|
192
|
+
└── delete-status <id>
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
---
|
|
196
|
+
|
|
197
|
+
## Global Flags
|
|
198
|
+
|
|
199
|
+
```
|
|
200
|
+
--api-key TEXT API key (overrides env/config)
|
|
201
|
+
--base-url TEXT API base URL (default: https://api.commune.email)
|
|
202
|
+
--json Output raw JSON
|
|
203
|
+
--quiet / -q Suppress status messages
|
|
204
|
+
--no-color Disable color output
|
|
205
|
+
--version / -V Show version and exit
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
---
|
|
209
|
+
|
|
210
|
+
## Config File
|
|
211
|
+
|
|
212
|
+
Stored at `~/.commune/config.toml` (or `$COMMUNE_CONFIG_DIR/config.toml`).
|
|
213
|
+
Created with `chmod 600` to protect your API key.
|
|
214
|
+
|
|
215
|
+
```toml
|
|
216
|
+
api_key = "comm_..."
|
|
217
|
+
base_url = "https://api.commune.email"
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
---
|
|
221
|
+
|
|
222
|
+
## Scripting
|
|
223
|
+
|
|
224
|
+
```bash
|
|
225
|
+
# Non-TTY → auto JSON
|
|
226
|
+
inboxes=$(commune inboxes list)
|
|
227
|
+
echo "$inboxes" | jq '.data[0].email'
|
|
228
|
+
|
|
229
|
+
# Pipe body from stdin
|
|
230
|
+
echo "Email body" | commune messages send \
|
|
231
|
+
--to user@example.com \
|
|
232
|
+
--subject "Automated" \
|
|
233
|
+
--text -
|
|
234
|
+
|
|
235
|
+
# Exit code handling
|
|
236
|
+
if commune messages send --to user@example.com --subject Test --text "Hi" --json; then
|
|
237
|
+
echo "Sent"
|
|
238
|
+
else
|
|
239
|
+
echo "Failed: $?"
|
|
240
|
+
fi
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
Full API reference: https://docs.commune.email
|
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
# commune-cli
|
|
2
|
+
|
|
3
|
+
Official command-line interface for the [Commune](https://commune.email) email API.
|
|
4
|
+
|
|
5
|
+
Covers every API surface: domains, inboxes, messages, threads, attachments, search, delivery analytics, webhooks, DMARC, and data deletion.
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Install
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
pip install commune-cli
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
Requires Python ≥ 3.9.
|
|
16
|
+
|
|
17
|
+
---
|
|
18
|
+
|
|
19
|
+
## Quick Start
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
# Set your API key
|
|
23
|
+
export COMMUNE_API_KEY=comm_...
|
|
24
|
+
|
|
25
|
+
# Send an email
|
|
26
|
+
commune messages send \
|
|
27
|
+
--to recipient@example.com \
|
|
28
|
+
--subject "Hello from CLI" \
|
|
29
|
+
--text "Sent from the terminal."
|
|
30
|
+
|
|
31
|
+
# List inboxes
|
|
32
|
+
commune inboxes list
|
|
33
|
+
|
|
34
|
+
# JSON output (automatic when stdout is piped)
|
|
35
|
+
commune inboxes list --json | jq '.data[].email'
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
---
|
|
39
|
+
|
|
40
|
+
## Authentication
|
|
41
|
+
|
|
42
|
+
Set your API key in one of these ways (highest priority wins):
|
|
43
|
+
|
|
44
|
+
| Priority | Source |
|
|
45
|
+
|----------|--------|
|
|
46
|
+
| 1 | `--api-key` flag |
|
|
47
|
+
| 2 | `COMMUNE_API_KEY` env var |
|
|
48
|
+
| 3 | `~/.commune/config.toml` → `api_key` |
|
|
49
|
+
|
|
50
|
+
Store permanently:
|
|
51
|
+
|
|
52
|
+
```bash
|
|
53
|
+
commune config set api_key comm_...
|
|
54
|
+
commune config show
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
---
|
|
58
|
+
|
|
59
|
+
## Output
|
|
60
|
+
|
|
61
|
+
- **TTY**: rich tables and panels with color
|
|
62
|
+
- **Piped / `--json`**: clean JSON to stdout; status messages to stderr
|
|
63
|
+
|
|
64
|
+
```bash
|
|
65
|
+
# JSON list format (always consistent)
|
|
66
|
+
commune threads list --json
|
|
67
|
+
# {"data": [...], "has_more": false, "next_cursor": null}
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
---
|
|
71
|
+
|
|
72
|
+
## Exit Codes
|
|
73
|
+
|
|
74
|
+
| Code | Meaning |
|
|
75
|
+
|------|---------|
|
|
76
|
+
| 0 | Success |
|
|
77
|
+
| 1 | API / validation error |
|
|
78
|
+
| 2 | Auth error (401/403) |
|
|
79
|
+
| 3 | Not found (404) |
|
|
80
|
+
| 4 | Rate limit or plan gate (429/403) |
|
|
81
|
+
| 5 | Network / connection error |
|
|
82
|
+
|
|
83
|
+
---
|
|
84
|
+
|
|
85
|
+
## Error Format (stderr)
|
|
86
|
+
|
|
87
|
+
```json
|
|
88
|
+
{"error": {"code": "not_found", "message": "Inbox not found.", "status_code": 404}}
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
---
|
|
92
|
+
|
|
93
|
+
## Commands
|
|
94
|
+
|
|
95
|
+
```
|
|
96
|
+
commune
|
|
97
|
+
├── config
|
|
98
|
+
│ ├── set <key> <value>
|
|
99
|
+
│ ├── get <key>
|
|
100
|
+
│ ├── show [--reveal]
|
|
101
|
+
│ ├── unset <key>
|
|
102
|
+
│ └── path
|
|
103
|
+
│
|
|
104
|
+
├── domains
|
|
105
|
+
│ ├── list [--limit] [--cursor]
|
|
106
|
+
│ ├── get <domain-id>
|
|
107
|
+
│ ├── create <name>
|
|
108
|
+
│ ├── verify <domain-id>
|
|
109
|
+
│ └── records <domain-id>
|
|
110
|
+
│
|
|
111
|
+
├── inboxes
|
|
112
|
+
│ ├── list [--domain-id] [--limit] [--cursor]
|
|
113
|
+
│ ├── get <inbox-id>
|
|
114
|
+
│ ├── create [--local-part] [--domain-id] [--name] [--webhook-url]
|
|
115
|
+
│ ├── update <inbox-id> [--name] [--webhook-url]
|
|
116
|
+
│ ├── delete <inbox-id> --domain-id [--yes]
|
|
117
|
+
│ ├── set-webhook <inbox-id> --domain-id --url
|
|
118
|
+
│ └── extraction-schema
|
|
119
|
+
│ ├── set <inbox-id> --domain-id --schema <json>
|
|
120
|
+
│ └── remove <inbox-id> --domain-id
|
|
121
|
+
│
|
|
122
|
+
├── messages
|
|
123
|
+
│ ├── send --to --subject [--text] [--html] [--from] [--inbox-id] [--domain-id]
|
|
124
|
+
│ │ [--cc] [--bcc] [--reply-to] [--thread-id]
|
|
125
|
+
│ └── list [--inbox-id] [--domain-id] [--sender] [--limit] [--order] [--before] [--after]
|
|
126
|
+
│
|
|
127
|
+
├── threads
|
|
128
|
+
│ ├── list [--inbox-id] [--domain-id] [--limit] [--cursor] [--order]
|
|
129
|
+
│ ├── messages <thread-id> [--limit] [--order] [--cursor]
|
|
130
|
+
│ ├── metadata <thread-id>
|
|
131
|
+
│ ├── set-status <thread-id> <open|needs_reply|waiting|closed>
|
|
132
|
+
│ ├── assign <thread-id> [--to <user>]
|
|
133
|
+
│ └── tags
|
|
134
|
+
│ ├── add <thread-id> <tag...>
|
|
135
|
+
│ └── remove <thread-id> <tag...>
|
|
136
|
+
│
|
|
137
|
+
├── attachments
|
|
138
|
+
│ ├── upload <file>
|
|
139
|
+
│ ├── get <attachment-id>
|
|
140
|
+
│ └── url <attachment-id> [--expires-in]
|
|
141
|
+
│
|
|
142
|
+
├── search
|
|
143
|
+
│ └── threads <query> [--inbox-id] [--domain-id] [--limit]
|
|
144
|
+
│
|
|
145
|
+
├── delivery
|
|
146
|
+
│ ├── metrics [--domain-id] [--inbox-id] [--period]
|
|
147
|
+
│ ├── events [--domain-id] [--inbox-id] [--limit]
|
|
148
|
+
│ └── suppressions [--domain-id] [--inbox-id] [--limit]
|
|
149
|
+
│
|
|
150
|
+
├── webhooks
|
|
151
|
+
│ ├── list [--inbox-id] [--status] [--endpoint] [--limit]
|
|
152
|
+
│ ├── get <delivery-id>
|
|
153
|
+
│ ├── retry <delivery-id>
|
|
154
|
+
│ └── health
|
|
155
|
+
│
|
|
156
|
+
├── dmarc
|
|
157
|
+
│ ├── reports <domain> [--limit]
|
|
158
|
+
│ └── summary <domain> [--days]
|
|
159
|
+
│
|
|
160
|
+
└── data
|
|
161
|
+
├── delete-request [--email] [--inbox-id] [--domain-id]
|
|
162
|
+
├── delete-confirm <id> [--yes]
|
|
163
|
+
└── delete-status <id>
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
---
|
|
167
|
+
|
|
168
|
+
## Global Flags
|
|
169
|
+
|
|
170
|
+
```
|
|
171
|
+
--api-key TEXT API key (overrides env/config)
|
|
172
|
+
--base-url TEXT API base URL (default: https://api.commune.email)
|
|
173
|
+
--json Output raw JSON
|
|
174
|
+
--quiet / -q Suppress status messages
|
|
175
|
+
--no-color Disable color output
|
|
176
|
+
--version / -V Show version and exit
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
---
|
|
180
|
+
|
|
181
|
+
## Config File
|
|
182
|
+
|
|
183
|
+
Stored at `~/.commune/config.toml` (or `$COMMUNE_CONFIG_DIR/config.toml`).
|
|
184
|
+
Created with `chmod 600` to protect your API key.
|
|
185
|
+
|
|
186
|
+
```toml
|
|
187
|
+
api_key = "comm_..."
|
|
188
|
+
base_url = "https://api.commune.email"
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
---
|
|
192
|
+
|
|
193
|
+
## Scripting
|
|
194
|
+
|
|
195
|
+
```bash
|
|
196
|
+
# Non-TTY → auto JSON
|
|
197
|
+
inboxes=$(commune inboxes list)
|
|
198
|
+
echo "$inboxes" | jq '.data[0].email'
|
|
199
|
+
|
|
200
|
+
# Pipe body from stdin
|
|
201
|
+
echo "Email body" | commune messages send \
|
|
202
|
+
--to user@example.com \
|
|
203
|
+
--subject "Automated" \
|
|
204
|
+
--text -
|
|
205
|
+
|
|
206
|
+
# Exit code handling
|
|
207
|
+
if commune messages send --to user@example.com --subject Test --text "Hi" --json; then
|
|
208
|
+
echo "Sent"
|
|
209
|
+
else
|
|
210
|
+
echo "Failed: $?"
|
|
211
|
+
fi
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
Full API reference: https://docs.commune.email
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
"""CommuneClient — thin httpx wrapper with API key auth.
|
|
2
|
+
|
|
3
|
+
Auth: Authorization: Bearer comm_...
|
|
4
|
+
|
|
5
|
+
Raises:
|
|
6
|
+
httpx.ConnectError / httpx.TimeoutException — caller wraps with network_error()
|
|
7
|
+
All non-2xx responses — caller checks response.is_success and calls api_error()
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
from __future__ import annotations
|
|
11
|
+
|
|
12
|
+
from typing import Any, Optional
|
|
13
|
+
|
|
14
|
+
import httpx
|
|
15
|
+
|
|
16
|
+
from .state import AppState
|
|
17
|
+
|
|
18
|
+
DEFAULT_TIMEOUT = 30.0
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
class CommuneClient:
|
|
22
|
+
"""HTTP client for the Commune API.
|
|
23
|
+
|
|
24
|
+
Usage:
|
|
25
|
+
client = CommuneClient.from_state(state)
|
|
26
|
+
r = client.get("/v1/domains")
|
|
27
|
+
if not r.is_success:
|
|
28
|
+
api_error(r, json_output=state.should_json())
|
|
29
|
+
"""
|
|
30
|
+
|
|
31
|
+
def __init__(
|
|
32
|
+
self,
|
|
33
|
+
base_url: str,
|
|
34
|
+
api_key: Optional[str] = None,
|
|
35
|
+
timeout: float = DEFAULT_TIMEOUT,
|
|
36
|
+
):
|
|
37
|
+
self.base_url = base_url.rstrip("/")
|
|
38
|
+
self.api_key = api_key
|
|
39
|
+
self.timeout = timeout
|
|
40
|
+
|
|
41
|
+
@classmethod
|
|
42
|
+
def from_state(cls, state: AppState) -> "CommuneClient":
|
|
43
|
+
return cls(
|
|
44
|
+
base_url=state.base_url,
|
|
45
|
+
api_key=state.api_key,
|
|
46
|
+
timeout=DEFAULT_TIMEOUT,
|
|
47
|
+
)
|
|
48
|
+
|
|
49
|
+
def _base_headers(self) -> dict[str, str]:
|
|
50
|
+
headers: dict[str, str] = {
|
|
51
|
+
"Content-Type": "application/json",
|
|
52
|
+
"User-Agent": "commune-cli/0.1.0",
|
|
53
|
+
}
|
|
54
|
+
if self.api_key:
|
|
55
|
+
headers["Authorization"] = f"Bearer {self.api_key}"
|
|
56
|
+
return headers
|
|
57
|
+
|
|
58
|
+
def _url(self, path: str) -> str:
|
|
59
|
+
return self.base_url + path
|
|
60
|
+
|
|
61
|
+
def _req(
|
|
62
|
+
self,
|
|
63
|
+
method: str,
|
|
64
|
+
path: str,
|
|
65
|
+
*,
|
|
66
|
+
params: Optional[dict[str, Any]] = None,
|
|
67
|
+
json: Optional[Any] = None,
|
|
68
|
+
data: Optional[bytes] = None,
|
|
69
|
+
extra_headers: Optional[dict[str, str]] = None,
|
|
70
|
+
) -> httpx.Response:
|
|
71
|
+
headers = self._base_headers()
|
|
72
|
+
if extra_headers:
|
|
73
|
+
headers.update(extra_headers)
|
|
74
|
+
if data is not None:
|
|
75
|
+
headers.pop("Content-Type", None)
|
|
76
|
+
|
|
77
|
+
if params:
|
|
78
|
+
params = {k: v for k, v in params.items() if v is not None}
|
|
79
|
+
|
|
80
|
+
with httpx.Client(timeout=self.timeout) as client:
|
|
81
|
+
return client.request(
|
|
82
|
+
method,
|
|
83
|
+
self._url(path),
|
|
84
|
+
headers=headers,
|
|
85
|
+
params=params or None,
|
|
86
|
+
json=json,
|
|
87
|
+
content=data,
|
|
88
|
+
)
|
|
89
|
+
|
|
90
|
+
def get(self, path: str, *, params: Optional[dict[str, Any]] = None) -> httpx.Response:
|
|
91
|
+
return self._req("GET", path, params=params)
|
|
92
|
+
|
|
93
|
+
def post(
|
|
94
|
+
self,
|
|
95
|
+
path: str,
|
|
96
|
+
*,
|
|
97
|
+
json: Optional[Any] = None,
|
|
98
|
+
data: Optional[bytes] = None,
|
|
99
|
+
extra_headers: Optional[dict[str, str]] = None,
|
|
100
|
+
params: Optional[dict[str, Any]] = None,
|
|
101
|
+
) -> httpx.Response:
|
|
102
|
+
return self._req("POST", path, json=json, data=data, extra_headers=extra_headers, params=params)
|
|
103
|
+
|
|
104
|
+
def patch(self, path: str, *, json: Optional[Any] = None) -> httpx.Response:
|
|
105
|
+
return self._req("PATCH", path, json=json)
|
|
106
|
+
|
|
107
|
+
def delete(self, path: str, *, params: Optional[dict[str, Any]] = None) -> httpx.Response:
|
|
108
|
+
return self._req("DELETE", path, params=params)
|
|
109
|
+
|
|
110
|
+
def put(self, path: str, *, json: Optional[Any] = None) -> httpx.Response:
|
|
111
|
+
return self._req("PUT", path, json=json)
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"""Command modules for the Commune CLI."""
|