imap-agent-cli 0.2.0__tar.gz → 0.3.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.
Files changed (45) hide show
  1. {imap_agent_cli-0.2.0 → imap_agent_cli-0.3.0}/AGENTS.md +1 -1
  2. {imap_agent_cli-0.2.0 → imap_agent_cli-0.3.0}/CHANGELOG.md +7 -0
  3. imap_agent_cli-0.3.0/PKG-INFO +444 -0
  4. imap_agent_cli-0.3.0/README.md +406 -0
  5. imap_agent_cli-0.3.0/docs/setup.md +127 -0
  6. {imap_agent_cli-0.2.0 → imap_agent_cli-0.3.0}/imap_agent_cli.py +4 -1
  7. {imap_agent_cli-0.2.0 → imap_agent_cli-0.3.0}/pyproject.toml +5 -2
  8. {imap_agent_cli-0.2.0 → imap_agent_cli-0.3.0}/spec.md +22 -15
  9. {imap_agent_cli-0.2.0 → imap_agent_cli-0.3.0}/src/imap_agent_cli/__init__.py +1 -1
  10. {imap_agent_cli-0.2.0 → imap_agent_cli-0.3.0}/src/imap_agent_cli/cli.py +78 -62
  11. imap_agent_cli-0.3.0/src/imap_agent_cli/config.py +297 -0
  12. imap_agent_cli-0.3.0/src/imap_agent_cli/credentials.py +79 -0
  13. {imap_agent_cli-0.2.0 → imap_agent_cli-0.3.0}/src/imap_agent_cli/imap_client.py +62 -60
  14. {imap_agent_cli-0.2.0 → imap_agent_cli-0.3.0}/src/imap_agent_cli/models.py +6 -1
  15. imap_agent_cli-0.3.0/src/imap_agent_cli/onboarding.py +200 -0
  16. imap_agent_cli-0.3.0/src/imap_agent_cli/providers.py +67 -0
  17. {imap_agent_cli-0.2.0 → imap_agent_cli-0.3.0}/src/imap_agent_cli/skill.py +26 -15
  18. imap_agent_cli-0.3.0/src/imap_agent_cli/storage.py +72 -0
  19. imap_agent_cli-0.3.0/src/imap_agent_cli/verification.py +94 -0
  20. {imap_agent_cli-0.2.0 → imap_agent_cli-0.3.0}/tests/test_cli.py +50 -3
  21. {imap_agent_cli-0.2.0 → imap_agent_cli-0.3.0}/tests/test_imap_client.py +8 -0
  22. imap_agent_cli-0.3.0/tests/test_onboarding.py +414 -0
  23. {imap_agent_cli-0.2.0 → imap_agent_cli-0.3.0}/tests/test_pymap_integration.py +36 -9
  24. {imap_agent_cli-0.2.0 → imap_agent_cli-0.3.0}/tests/test_skill.py +20 -0
  25. {imap_agent_cli-0.2.0 → imap_agent_cli-0.3.0}/tests/test_skill_sync.py +6 -5
  26. {imap_agent_cli-0.2.0 → imap_agent_cli-0.3.0}/tests/test_wheel_smoke.py +30 -5
  27. imap_agent_cli-0.2.0/PKG-INFO +0 -294
  28. imap_agent_cli-0.2.0/README.md +0 -259
  29. imap_agent_cli-0.2.0/src/imap_agent_cli/config.py +0 -313
  30. {imap_agent_cli-0.2.0 → imap_agent_cli-0.3.0}/.github/workflows/publish.yml +0 -0
  31. {imap_agent_cli-0.2.0 → imap_agent_cli-0.3.0}/.gitignore +0 -0
  32. {imap_agent_cli-0.2.0 → imap_agent_cli-0.3.0}/LICENSE +0 -0
  33. {imap_agent_cli-0.2.0 → imap_agent_cli-0.3.0}/src/imap_agent_cli/errors.py +0 -0
  34. {imap_agent_cli-0.2.0 → imap_agent_cli-0.3.0}/src/imap_agent_cli/mime.py +0 -0
  35. {imap_agent_cli-0.2.0 → imap_agent_cli-0.3.0}/src/imap_agent_cli/render.py +0 -0
  36. {imap_agent_cli-0.2.0 → imap_agent_cli-0.3.0}/src/imap_agent_cli/runtime.py +0 -0
  37. {imap_agent_cli-0.2.0 → imap_agent_cli-0.3.0}/src/imap_agent_cli/search.py +0 -0
  38. {imap_agent_cli-0.2.0 → imap_agent_cli-0.3.0}/tests/__init__.py +0 -0
  39. {imap_agent_cli-0.2.0 → imap_agent_cli-0.3.0}/tests/_bootstrap.py +0 -0
  40. {imap_agent_cli-0.2.0 → imap_agent_cli-0.3.0}/tests/pymap_server_runner.py +0 -0
  41. {imap_agent_cli-0.2.0 → imap_agent_cli-0.3.0}/tests/test_config.py +0 -0
  42. {imap_agent_cli-0.2.0 → imap_agent_cli-0.3.0}/tests/test_live_no_seen.py +0 -0
  43. {imap_agent_cli-0.2.0 → imap_agent_cli-0.3.0}/tests/test_mime.py +0 -0
  44. {imap_agent_cli-0.2.0 → imap_agent_cli-0.3.0}/tests/test_runtime.py +0 -0
  45. {imap_agent_cli-0.2.0 → imap_agent_cli-0.3.0}/tests/test_search.py +0 -0
@@ -25,7 +25,7 @@ The core safety boundary is strict: never add support for sending email, deletin
25
25
  - Keep the root wrapper thin; application logic belongs under `src/imap_agent_cli/`.
26
26
  - Preserve stable JSON payloads on stdout. Diagnostics, warnings, progress, and errors must go to stderr.
27
27
  - Do not print secrets, credentials, full message bodies, or attachment contents in logs.
28
- - Keep credentials in environment variables or config references to environment variables. Do not add config examples that store passwords directly.
28
+ - Keep secrets separate from ordinary configuration. Credentials may come from environment variables, explicit stdin, or the separate credentials file written by setup. Never include real credentials in examples. Use normal inherited filesystem permissions. Do not require an OS keyring or persist shell environment variables.
29
29
  - Keep README and skill language platform-neutral and agent-tool-neutral. Avoid shell-specific syntax unless explicitly documenting a shell-specific example.
30
30
  - If changing installed-skill behavior or wording, update `src/imap_agent_cli/skill.py` and `tests/test_skill.py` together.
31
31
  - If changing MIME parsing, body rendering, draft creation, or search behavior, add focused tests for the contract being changed.
@@ -1,5 +1,12 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.2.1 - 2026-09-08
4
+
5
+ - Direct agents to search only `INBOX` when the user does not specify a folder or broader scope. Do not automatically expand empty or incomplete searches.
6
+ - Keep specific-folder, recursive, and all-folder searches available when requested, including through JSON input.
7
+ - Clarify search scope in CLI help and documentation. Preserve the existing configurable CLI folder default.
8
+ - Add regression coverage for search scope defaults, explicit overrides, and single-folder searches avoiding folder enumeration.
9
+
3
10
  ## 0.2.0 - 2026-09-03
4
11
 
5
12
  - Automatically synchronize existing managed `imap` skills in the standard directory to the running CLI's newer version. No package lookup, uv refresh, or CLI update is performed.
@@ -0,0 +1,444 @@
1
+ Metadata-Version: 2.5
2
+ Name: imap-agent-cli
3
+ Version: 0.3.0
4
+ Summary: Agent-first IMAP CLI for safe email search, read, attachment download, and draft creation
5
+ Project-URL: Homepage, https://github.com/pseudosavant/imap-agent-cli
6
+ Project-URL: Repository, https://github.com/pseudosavant/imap-agent-cli
7
+ Project-URL: Issues, https://github.com/pseudosavant/imap-agent-cli/issues
8
+ Author: Paul
9
+ License-Expression: MIT
10
+ License-File: LICENSE
11
+ Keywords: agent,cli,drafts,email,imap
12
+ Classifier: Development Status :: 3 - Alpha
13
+ Classifier: Environment :: Console
14
+ Classifier: Intended Audience :: Developers
15
+ Classifier: License :: OSI Approved :: MIT License
16
+ Classifier: Operating System :: OS Independent
17
+ Classifier: Programming Language :: Python :: 3
18
+ Classifier: Programming Language :: Python :: 3.11
19
+ Classifier: Programming Language :: Python :: 3.12
20
+ Classifier: Programming Language :: Python :: 3.13
21
+ Classifier: Topic :: Communications :: Email
22
+ Classifier: Topic :: Communications :: Email :: Post-Office :: IMAP
23
+ Classifier: Topic :: Utilities
24
+ Requires-Python: <3.14,>=3.11
25
+ Requires-Dist: beautifulsoup4>=4.12.0
26
+ Requires-Dist: bleach>=6.2.0
27
+ Requires-Dist: filelock>=3.16.0
28
+ Requires-Dist: imapclient>=3.0.0
29
+ Requires-Dist: markdownify>=0.14.0
30
+ Requires-Dist: packaging>=23.2
31
+ Requires-Dist: prompt-toolkit>=3.0.43
32
+ Requires-Dist: pyyaml>=6.0
33
+ Requires-Dist: tomlkit>=0.13.0
34
+ Provides-Extra: test
35
+ Requires-Dist: pymap>=0.36.0; extra == 'test'
36
+ Requires-Dist: pytest>=8.0.0; extra == 'test'
37
+ Description-Content-Type: text/markdown
38
+
39
+ # imap-agent-cli
40
+
41
+ `imap-agent-cli` gives coding agents a narrow, safe interface to generic IMAP mailboxes. It can search email, read messages without changing their unread state, inspect or download requested attachments, and save new or reply drafts.
42
+
43
+ It never sends email and cannot change existing messages or folders.
44
+
45
+ ## Quick start with an agent
46
+
47
+ You need an IMAP-enabled email account and a compatible password or app password. Setup explains credential creation for Gmail, Fastmail, and iCloud. Other IMAP servers need their provider's hostname and login details. Microsoft 365 and Outlook.com require OAuth and are not supported. Microsoft app passwords are not a workaround.
48
+
49
+ Install [`uv`](https://docs.astral.sh/uv/getting-started/installation/) if needed. The managed skill runs the tool with `uvx`. You do not need a global tool installation. uv can obtain a compatible Python automatically. Direct Python installs require Python 3.11 through 3.13. IMAPClient is currently incompatible with Python 3.14.
50
+
51
+ PowerShell:
52
+
53
+ ```powershell
54
+ # Skip this command if uv is already installed.
55
+ powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex"
56
+
57
+ # Open a new PowerShell window after installation.
58
+ uv --version
59
+ uvx imap-agent-cli setup --format plain
60
+ ```
61
+
62
+ Bash on Linux or macOS:
63
+
64
+ ```bash
65
+ # Skip these two commands if uv is already installed.
66
+ curl -LsSf https://astral.sh/uv/install.sh | sh
67
+ . "$HOME/.local/bin/env"
68
+
69
+ uv --version
70
+ uvx imap-agent-cli setup --format plain
71
+ ```
72
+
73
+ Enter your credential only at the masked terminal prompt. Never paste a credential into agent chat. Setup saves account settings and credentials separately, verifies read-only mailbox access, and installs the managed `imap` skill. No separate test command is needed after successful setup.
74
+
75
+ You can provide information you already know:
76
+
77
+ ```text
78
+ uvx imap-agent-cli setup "me@gmail.com"
79
+ uvx imap-agent-cli setup "https://app.fastmail.com/"
80
+ uvx imap-agent-cli setup --host imap.example.com --username me@example.com
81
+ ```
82
+
83
+ A webmail URL is only a provider hint. It is not fetched. Custom email domains require a provider hostname. See [setup and credential guidance](docs/setup.md) for provider requirements and recovery commands.
84
+
85
+ Start a new agent session if the skill is not available. Then ask:
86
+
87
+ > Use $imap to list the five newest messages in INBOX. Show senders and subjects only.
88
+
89
+ The agent must have access to `uvx`, the saved files, and the IMAP server. A remote host or container needs its own runtime and credential provision. If terminal use works but agent use fails, ask the agent to run `uvx imap-agent-cli config check`. Do not ask it to open the credentials file.
90
+
91
+ ## What it can do
92
+
93
+ | The tool can | The tool cannot |
94
+ | --- | --- |
95
+ | List folders and their metadata | Send email |
96
+ | Search message metadata | Delete, move, or archive messages |
97
+ | Read messages without marking them read | Mark messages read or unread |
98
+ | Inspect bounded thread context | Change flags, stars, or labels |
99
+ | List and download requested attachments | Create, rename, or delete folders |
100
+ | Append new and reply drafts to Drafts | Modify existing messages |
101
+
102
+ Draft creation only appends a new MIME message to the configured or detected Drafts folder. It never submits or sends the message.
103
+
104
+ ## Use the CLI directly
105
+
106
+ Run the published CLI without installing it globally:
107
+
108
+ ```text
109
+ uvx imap-agent-cli --help
110
+ uvx imap-agent-cli folders
111
+ uvx imap-agent-cli search --subject invoice
112
+ ```
113
+
114
+ To install the command as a persistent tool instead:
115
+
116
+ ```text
117
+ uv tool install imap-agent-cli
118
+ uv tool update-shell
119
+ imap-agent-cli --help
120
+ ```
121
+
122
+ Restart your shell after `uv tool update-shell` if the command is not found.
123
+
124
+ You can also install it into a Python environment:
125
+
126
+ ```text
127
+ python -m pip install imap-agent-cli
128
+ imap-agent-cli --help
129
+ ```
130
+
131
+ The examples below continue to use `uvx imap-agent-cli` so they work without a global installation.
132
+
133
+ ## How safe access works
134
+
135
+ The tool follows five core rules:
136
+
137
+ 1. Folder access is read-only except for appending a new message to Drafts.
138
+ 2. Search fetches message metadata, not complete message bodies.
139
+ 3. Read and thread operations use peek behavior so they do not set the IMAP `\Seen` flag.
140
+ 4. Attachment content is written only after an explicit download command and output directory.
141
+ 5. Draft commands use IMAP `APPEND`. There is no SMTP client or send command.
142
+
143
+ The usual workflow is to search first, select a result by folder and UID, read only the needed context, then optionally create a draft.
144
+
145
+ ## Configure accounts
146
+
147
+ ### Saved accounts
148
+
149
+ ```text
150
+ uvx imap-agent-cli setup
151
+ uvx imap-agent-cli setup --profile work
152
+ uvx imap-agent-cli setup --profile work --set-default
153
+ uvx imap-agent-cli profiles
154
+ uvx imap-agent-cli config show
155
+ ```
156
+
157
+ The first account uses the name `default`. Adding an account preserves the existing default. Pass `--profile work` to mailbox commands to select it.
158
+
159
+ Non-secret settings live in `~/.imap-agent-cli/config.toml`. Setup saves entered passwords in `~/.imap-agent-cli/credentials.toml` with normal inherited permissions. It does not require a keyring, change ACLs, or persist shell variables. The credential file is plain text. Keep it out of repositories and shared exports.
160
+
161
+ Repeated setup reuses existing credentials and preserves unrelated configuration and skill content. Use `setup --replace-password` to verify and save a replacement. Unset password environment overrides first. Existing configuration remains usable if verification or saving fails.
162
+
163
+ ### Environment overrides
164
+
165
+ Environment variables remain available. Connection flags take priority over non-empty environment overrides, followed by the selected saved profile and built-in defaults. Password resolution uses explicit stdin, the profile's named password variable, the global password variable, and finally the matching saved credential. Rejected credentials do not trigger fallback to another source.
166
+
167
+ PowerShell:
168
+
169
+ ```powershell
170
+ $env:IMAP_AGENT_CLI_HOST = "imap.example.com"
171
+ $env:IMAP_AGENT_CLI_USERNAME = "me@example.com"
172
+ $imapCredential = Read-Host "IMAP password or app password" -AsSecureString
173
+ $env:IMAP_AGENT_CLI_PASSWORD = [System.Net.NetworkCredential]::new("", $imapCredential).Password
174
+ Remove-Variable imapCredential
175
+ uvx imap-agent-cli setup --non-interactive
176
+ ```
177
+
178
+ Bash:
179
+
180
+ ```bash
181
+ export IMAP_AGENT_CLI_HOST="imap.example.com"
182
+ export IMAP_AGENT_CLI_USERNAME="me@example.com"
183
+ read -rs -p "IMAP password or app password: " IMAP_AGENT_CLI_PASSWORD
184
+ printf '\n'
185
+ export IMAP_AGENT_CLI_PASSWORD
186
+ uvx imap-agent-cli setup --non-interactive
187
+ ```
188
+
189
+ These variables affect the current shell and its children. An already-running agent does not inherit later changes. Setup uses an environment password without saving its value. Secure defaults supply port `993`, `tls=true`, and `ssl_mode=required`.
190
+
191
+ The existing `config init`, `config add-profile`, and `config set-default-profile` commands remain available. `config init` creates a starter file. Prefer `setup` to complete onboarding. Existing `password_env` references continue to work.
192
+
193
+ ### Check configuration
194
+
195
+ ```text
196
+ uvx imap-agent-cli config check
197
+ uvx imap-agent-cli config check --profile work --format plain
198
+ uvx imap-agent-cli config check --local
199
+ ```
200
+
201
+ Checks never write configuration, credentials, or skills. The network check verifies login, opens the default mailbox read-only, and checks bounded metadata access. It never reads bodies or appends a test message. Missing Drafts is a warning for reading. Finding Drafts does not verify append permission or quota. An empty mailbox leaves metadata fetching untested.
202
+
203
+ Use `--config PATH` or `IMAP_AGENT_CLI_CONFIG` for another configuration file. Use `--credentials-file PATH` or `IMAP_AGENT_CLI_CREDENTIALS_FILE` for a separate credential file. Explicit paths work with setup, diagnostics, and mailbox commands. Relative command-line paths resolve from the working directory. Setup saves an explicitly selected credential file path for later use. Custom skill locations use `--skills-dir PATH`.
204
+
205
+ ### Connection security
206
+
207
+ The recommended configuration is port `993`, `tls=true`, and `ssl_mode=required`.
208
+
209
+ | Setting | Behavior |
210
+ | --- | --- |
211
+ | `tls=true`, `ssl_mode=required` | Use implicit TLS and fail if a secure connection cannot be established |
212
+ | `tls=false`, `ssl_mode=required` | Require STARTTLS before login |
213
+ | `ssl_mode=preferred` | Allow implicit TLS to fall back to STARTTLS without falling back to plaintext login |
214
+ | `ssl_mode=disabled` | Allow plaintext IMAP login for deliberate local testing only |
215
+
216
+ Both `required` and `preferred` refuse to send credentials over plaintext.
217
+
218
+ ## Common workflows
219
+
220
+ ### Find messages
221
+
222
+ Search defaults to `INBOX` only, returns metadata only, and limits results to a bounded number. You can override the default folder with `defaults.default_folder` in config. Pass `--folder INBOX` to explicitly select the inbox:
223
+
224
+ ```text
225
+ uvx imap-agent-cli search --subject "invoice" --max-results 10
226
+ uvx imap-agent-cli search --from "person@example.com" --since 2026-01-01 --max-results 10
227
+ uvx imap-agent-cli search --to "me@example.com" --has-attachments --max-results 10 --max-scan 100
228
+ ```
229
+
230
+ When requested, search a specific folder, include its children, or search all selectable folders:
231
+
232
+ ```text
233
+ uvx imap-agent-cli search --folder "Archive/Support" --subject "contract" --max-results 25
234
+ uvx imap-agent-cli search --folder Projects --recursive --subject "contract" --max-results 25
235
+ uvx imap-agent-cli search --all-folders --subject "contract" --max-results 25
236
+ ```
237
+
238
+ All-folder searches exclude folders marked as Junk or Spam by default. All-folder and recursive searches can be expensive on large nested archives even with a small result limit. The installed skill directs agents to use the inbox unless the user requests another scope. Empty or incomplete results do not authorize automatically expanding the search.
239
+
240
+ ### Read a selected message
241
+
242
+ Search results identify messages by folder and UID. Read only metadata when confirming a result, or request a body format when content is needed:
243
+
244
+ ```text
245
+ uvx imap-agent-cli read --folder INBOX --uid 12345 --body-format metadata --include-attachments none
246
+ uvx imap-agent-cli read --folder INBOX --uid 12345 --body-format plain --max-body-chars 12000
247
+ uvx imap-agent-cli read --folder INBOX --uid 12345 --body-format markdown
248
+ uvx imap-agent-cli read --folder INBOX --uid 12345 --body-format html --include-attachments metadata
249
+ ```
250
+
251
+ | Body format | Intended use |
252
+ | --- | --- |
253
+ | `metadata` | Return headers without a message body |
254
+ | `plain` | Summaries and ordinary text processing |
255
+ | `markdown` | Agent-friendly conversion that preserves common structure |
256
+ | `html` | Sanitized HTML when layout, tables, or links matter |
257
+ | `raw-html` | Explicit access to untrusted, unsanitized source HTML |
258
+
259
+ HTML sanitization removes active content and unsafe resource references. Markdown conversion is intentionally lossy. Attachment content is never included in a read result.
260
+
261
+ ### Inspect thread context
262
+
263
+ Start with metadata-only context for a conversation:
264
+
265
+ ```text
266
+ uvx imap-agent-cli thread --folder INBOX --uid 12345 --max-messages 5
267
+ ```
268
+
269
+ Include only the latest body when preparing a summary or reply:
270
+
271
+ ```text
272
+ uvx imap-agent-cli thread --folder INBOX --uid 12345 --include-body latest --body-format plain --max-body-chars 6000
273
+ ```
274
+
275
+ ### Inspect and download attachments
276
+
277
+ List attachment names, types, sizes, and part IDs without downloading content:
278
+
279
+ ```text
280
+ uvx imap-agent-cli attachments --folder INBOX --uid 12345
281
+ ```
282
+
283
+ Download one attachment or all non-inline attachments to an explicit directory:
284
+
285
+ ```text
286
+ uvx imap-agent-cli attachments download --folder INBOX --uid 12345 --part-id 2 --output-dir ./email-attachments
287
+ uvx imap-agent-cli attachments download --folder INBOX --uid 12345 --all --output-dir ./email-attachments
288
+ ```
289
+
290
+ Downloads sanitize filenames and preflight every target before writing. Existing files are preserved unless `--overwrite` is provided. Inline attachments are excluded unless `--include-inline` is provided.
291
+
292
+ ### Create drafts
293
+
294
+ Create a new draft:
295
+
296
+ ```text
297
+ uvx imap-agent-cli draft create --to person@example.com --subject "Hello" --body "Draft only."
298
+ ```
299
+
300
+ Create a reply draft from an existing message:
301
+
302
+ ```text
303
+ uvx imap-agent-cli draft reply --folder INBOX --uid 12345 --body "Thanks. I will review this."
304
+ ```
305
+
306
+ For longer content, use `--body-file`. Add local files with repeated `--attachment` options. Draft bodies may be `plain`, `markdown`, or `html`.
307
+
308
+ Reply drafts choose the original sender or `Reply-To`, add a reply subject when needed, and preserve `In-Reply-To` and `References` headers. They do not quote the original message by default.
309
+
310
+ ## Manage the agent skill
311
+
312
+ The managed skill is installed at `~/.agents/skills/imap/SKILL.md`:
313
+
314
+ ```text
315
+ uvx imap-agent-cli skill install
316
+ ```
317
+
318
+ Inspect its path, ownership, version, integrity, and automatic synchronization eligibility without changing it:
319
+
320
+ ```text
321
+ uvx imap-agent-cli skill status
322
+ uvx imap-agent-cli skill status --format plain
323
+ ```
324
+
325
+ Normal mailbox invocations and top-level help, version, and about commands of an installed CLI update a pristine older managed skill to the running CLI version. Synchronization is local. It does not query PyPI, refresh uv's cache, or update the CLI. Missing skills are never installed automatically. Unmanaged, modified, equal-version, and newer skills are preserved.
326
+
327
+ Restore altered managed content explicitly:
328
+
329
+ ```text
330
+ uvx imap-agent-cli skill install --force
331
+ ```
332
+
333
+ Install-time `--force` still refuses unmanaged content and never downgrades a newer skill. Managed front matter records ownership, version, and a SHA-256 content hash. The hash detects edits. It is not a signature.
334
+
335
+ Remove the managed skill:
336
+
337
+ ```text
338
+ uvx imap-agent-cli skill remove
339
+ ```
340
+
341
+ Removal deletes only `SKILL.md` and removes its directory when empty. Unrelated files are kept. The original `install-skill` and `remove-skill` aliases remain supported.
342
+
343
+ All skill commands accept `--skills-dir PATH`. Custom locations require explicit updates and are not checked during normal invocations:
344
+
345
+ ```text
346
+ uvx imap-agent-cli skill install --skills-dir ./my-skills
347
+ uvx imap-agent-cli skill status --skills-dir ./my-skills
348
+ ```
349
+
350
+ Local checkouts, direct source installs, editable builds, and unidentifiable installation origins do not synchronize automatically. Explicit skill installation still works from development builds. Skill updates affect future agent sessions and may not replace instructions already loaded by a running session.
351
+
352
+ ## Structured output and automation
353
+
354
+ Operational commands write JSON payloads to stdout. Diagnostics, warnings, progress, and errors go to stderr. This keeps command output safe to parse in agent and automation workflows.
355
+
356
+ Search, read, and draft commands also accept structured input from a JSON file:
357
+
358
+ ```text
359
+ uvx imap-agent-cli search --json query.json
360
+ uvx imap-agent-cli read --json message.json
361
+ uvx imap-agent-cli draft create --json draft.json
362
+ uvx imap-agent-cli draft reply --json reply.json
363
+ ```
364
+
365
+ Use `--json -` to read the JSON request from stdin. Operational failures leave stdout empty and write a compact JSON error to stderr. Setup and configuration checks return structured readiness reports when verification or a later step fails. Check the exit status and the `ready` or `ok` field. Human diagnostics go to stderr. Add `--format plain` to setup or config check for a readable report. Logs do not include passwords, message bodies, or attachment content.
366
+
367
+ Default guardrails keep work bounded:
368
+
369
+ | Limit | Default |
370
+ | --- | ---: |
371
+ | Search results | 25 |
372
+ | Messages scanned | 250 |
373
+ | Body characters | 12,000 |
374
+ | Thread messages | 5 |
375
+ | Connection timeout | 15 seconds |
376
+ | Read timeout | 30 seconds |
377
+
378
+ Commands expose targeted overrides such as `--max-results`, `--max-scan`, `--max-messages`, and `--max-body-chars`.
379
+
380
+ ## Reference
381
+
382
+ | Command | Purpose |
383
+ | --- | --- |
384
+ | `setup` | Verify and save an account, then install the managed skill |
385
+ | `config` | Initialize, inspect, validate, and manage profile configuration |
386
+ | `profiles` | List configured profile names |
387
+ | `skill` | Install, inspect, or remove the managed agent skill |
388
+ | `folders` | List folders and folder metadata |
389
+ | `search` | Search message metadata with bounded results |
390
+ | `read` | Read one message by folder and UID without marking it read |
391
+ | `thread` | Inspect bounded conversation context |
392
+ | `attachments` | List or explicitly download attachments |
393
+ | `draft create` | Append a new message to Drafts |
394
+ | `draft reply` | Append a reply draft with conversation headers |
395
+
396
+ Use command help for the complete set of options:
397
+
398
+ ```text
399
+ uvx imap-agent-cli --help
400
+ uvx imap-agent-cli search --help
401
+ uvx imap-agent-cli read --help
402
+ uvx imap-agent-cli attachments download --help
403
+ uvx imap-agent-cli draft reply --help
404
+ uvx imap-agent-cli --about
405
+ uvx imap-agent-cli --version
406
+ ```
407
+
408
+ ## Development
409
+
410
+ Run the CLI from the repository:
411
+
412
+ ```text
413
+ uv run ./imap_agent_cli.py --help
414
+ uv run ./imap_agent_cli.py folders
415
+ uv run ./imap_agent_cli.py search --subject invoice
416
+ ```
417
+
418
+ Run the no-network test suite:
419
+
420
+ ```text
421
+ python -m unittest discover -v
422
+ ```
423
+
424
+ Run the opt-in local IMAP integration test after setting `IMAP_AGENT_CLI_TEST_PYMAP=1`:
425
+
426
+ ```text
427
+ uv run --extra test python -m unittest tests.test_pymap_integration -v
428
+ ```
429
+
430
+ The integration test starts `pymap dict --demo-data` locally and signs in with its demo credentials.
431
+
432
+ Run the opt-in live no-seen test only when intentionally validating a configured mailbox. Set `IMAP_AGENT_CLI_LIVE_TEST=1` first:
433
+
434
+ ```text
435
+ python -m unittest tests.test_live_no_seen -v
436
+ ```
437
+
438
+ Build the package:
439
+
440
+ ```text
441
+ uv build --no-sources
442
+ ```
443
+
444
+ This project is under active development. The behavior target is documented in [`spec.md`](./spec.md). It is distributed under the [MIT License](./LICENSE).