# afmail CLI Reference
> Regenerate with `scripts/projects/agent-first-mail/generate-cli-doc.sh` (runs `afmail --help --recursive --output markdown`).
# afmail - Agent-First Mail: local-first email case workspace for agents.
### Interface Policy
- Files are the read interface; CLI is for effects.
- One workspace represents one mailbox account.
- Message commands use `afmail message ACTION MESSAGE_ID ...`.
- Case commands use `afmail case ACTION CASE_REF ...`.
- Active and archived cases are readable with `afmail case show REF` and
`afmail archive case show REF`.
- stdout carries structured Agent-First Data events; stderr is not a protocol channel.
### Workspace Shape
```text
.afmail/messages/ raw .eml plus durable remote sidecars
messages/ rebuildable parsed message cache
.afmail/logs/events.jsonl append-only audit log
.afmail/transactions/ transient local write transaction sentinels
.afmail/workspace.progress.json latest push/pull runtime snapshot
templates/ user-editable generated Markdown templates
triage/message_*.md active unprocessed message views
spam/*.md generated spam review views
trash/*.md generated trash review views
deleted/*.md generated remote-deleted review views
cases/<group>/<case_uid>-<name>/case.md generated case entry view
cases/<group>/<case_uid>-<name>/data/ canonical case state
cases/<group>/<case_uid>-<name>/views/ generated case detail views
contacts/<group>/<contact_uid>-<name>.md canonical contact cards
archive/contacts/<contact_uid>-<name>.md archived contact cards
archive/cases/<case_uid>-<name>/ archived case workspaces
archive/notifications/<archive_uid>-<name>/archive.md generated archive entry view
archive/notifications/<archive_uid>-<name>/data/ canonical archive state
archive/notifications/<archive_uid>-<name>/views/ generated archive detail views
```
### Examples
```text
afmail init
afmail init email-a
afmail skill status
afmail skill install --agent codex --scope workspace
afmail status
afmail doctor
afmail pull
afmail pull sent archive
afmail remote folders
afmail case create --name 应用反馈-肥料登记 --message message_inbox_607146690_21 --group open --reason "new feedback thread"
afmail case show c20260603001
afmail case add c20260603001 message_inbox_607146690_22 --reason "follow-up belongs to same feedback case"
afmail archive message create --name 服务通知 --message message_inbox_607146690_23 --summary "billing notification" --reason "billing notification"
afmail archive message show a20260603001
afmail archive message restore a20260603001 message_inbox_607146690_23 --reason "needs triage again"
afmail message spam message_inbox_607146690_23 --reason "phishing attempt"
afmail message trash message_inbox_607146690_24 --reason "duplicate no longer needed"
afmail render refresh
afmail doctor repair --confirm
afmail case move c20260603001 waiting
afmail case archive c20260603001 --reason "feedback handled"
afmail archive case restore c20260603001 --group open --reason "customer replied"
afmail case tag c20260603001 legal --reason "legal review needed"
afmail contact create --name "Zhang San" --email zhang@example.com --org Acme --role Buyer
afmail contact list --group people
afmail contact email add p20260603001 zhang-alt@example.com
afmail contact rename p20260603001 --name "Zhang Sanfeng"
afmail contact extract --from-triage
afmail contact archive p20260603001 --reason "left the company"
afmail case draft reply c20260603001 message_inbox_607146690_22
afmail case draft attach c20260603001 reply-message_inbox_607146690_22.md ./screenshot.png
afmail case draft change c20260603001 reply-message_inbox_607146690_22.md --body "Thanks, I will check this."
afmail case draft validate c20260603001 reply-message_inbox_607146690_22.md
afmail case draft send c20260603001 reply-message_inbox_607146690_22.md
afmail case draft remove c20260603001 reply-message_inbox_607146690_22.md --reason "mistaken draft"
afmail push list
afmail push
afmail push --confirm
afmail purge
afmail purge spam --older-than-days 30
afmail purge deleted
afmail log list --limit 20
afmail message show message_inbox_607146690_21
afmail message attachment fetch message_inbox_607146690_21 2
```
### Exit Codes
- `0`: command completed successfully
- `1`: runtime/store/protocol error
- `2`: invalid CLI arguments
```text
Usage: afmail [OPTIONS] [COMMAND]
Commands:
init Initialize the current directory or a child path as an afmail workspace
pull Read configured IMAP mailbox ids into local message files without changing remote mail
config Read or update local afmail configuration
remote Inspect remote IMAP state for configuring mailboxes
push Push queued local work or manage the local push queue
status Report workspace health, counts, and latest pull/push progress
doctor Check afmail workspace consistency without inspecting Git
purge Permanently delete old local spam, trash, and remote-deleted records
skill Manage the Agent-First Mail skill for Codex, Claude Code, opencode, and Hermes
triage Inspect the triage queue
message Operate on any local message id
case Create a case or operate on an existing case ref
contact Create a contact or operate on an existing contact ref
archive Inspect and manage archived cases and direct-message archive categories
render Rebuild generated read views from local workspace state
log Inspect the workspace audit log
help Print this message or the help of the given subcommand(s)
Options:
--output <OUTPUT>
Output format: json (default), yaml, plain
[default: json]
--log <LOG>
Log categories (comma-separated): startup, request, progress, retry
--verbose
Enable all log categories
-V, --version
Print structured version event
-h, --help
Print help. Add --recursive to expand every nested subcommand; add --output json|yaml|markdown to render this help in another format.
```
## afmail init - Initialize the current directory or a child path as an afmail workspace
```text
Usage: init [PATH]
Arguments:
[PATH]
Optional workspace path to initialize under the current directory
Options:
-h, --help
Print help
```
## afmail pull - Read configured IMAP mailbox ids into local message files without changing remote mail
```text
Usage: pull [IDS]...
Arguments:
[IDS]...
Configured mailbox ids to pull. With none, pulls actions.pull.default_mailbox_ids
Options:
-h, --help
Print help
```
## afmail config - Read or update local afmail configuration
```text
Usage: config <COMMAND>
Commands:
show Show local .afmail/config.json
get Get one config key
set Set one config key. Multiple values become an array for array keys
help Print this message or the help of the given subcommand(s)
Options:
-h, --help
Print help
```
### afmail config show - Show local .afmail/config.json
```text
Usage: show
Options:
-h, --help
Print help
```
### afmail config get - Get one config key
```text
Usage: get <KEY>
Arguments:
<KEY>
Options:
-h, --help
Print help
```
### afmail config set - Set one config key. Multiple values become an array for array keys
```text
Usage: set <KEY> [VALUES]...
Arguments:
<KEY>
[VALUES]...
Options:
-h, --help
Print help
```
## afmail remote - Inspect remote IMAP state for configuring mailboxes
```text
Usage: remote <COMMAND>
Commands:
test Test IMAP login using local config
folders List IMAP folders/mailboxes
help Print this message or the help of the given subcommand(s)
Options:
-h, --help
Print help
```
### afmail remote test - Test IMAP login using local config
```text
Usage: test
Options:
-h, --help
Print help
```
### afmail remote folders - List IMAP folders/mailboxes
```text
Usage: folders
Options:
-h, --help
Print help
```
## afmail push - Push queued local work or manage the local push queue
```text
Usage: push [OPTIONS] [COMMAND]
Commands:
list List queued local push items
help Print this message or the help of the given subcommand(s)
Options:
--dry-run
Show planned push actions without IMAP/SMTP writes. This is the default
--confirm
Apply queued IMAP/SMTP effects
-h, --help
Print help
```
### afmail push list - List queued local push items
```text
Usage: list
Options:
-h, --help
Print help
```
## afmail status - Report workspace health, counts, and latest pull/push progress
```text
Usage: status
Options:
-h, --help
Print help
```
## afmail doctor - Check afmail workspace consistency without inspecting Git
```text
Usage: doctor [COMMAND]
Commands:
repair Repair only unambiguous afmail-generated state
help Print this message or the help of the given subcommand(s)
Options:
-h, --help
Print help
```
### afmail doctor repair - Repair only unambiguous afmail-generated state
```text
Usage: repair [OPTIONS]
Options:
--confirm
Apply repair actions. Without this flag, repair is refused
-h, --help
Print help
```
## afmail purge - Permanently delete old local spam, trash, and remote-deleted records
```text
Usage: purge [OPTIONS] [COMMAND]
Commands:
spam Permanently delete old local spam records
trash Permanently delete old local trash records
deleted Permanently delete old local records whose remote message disappeared
help Print this message or the help of the given subcommand(s)
Options:
--older-than-days <DAYS>
Only purge messages in a discard state at least this many days ago. Defaults to 30
-h, --help
Print help
```
### afmail purge spam - Permanently delete old local spam records
```text
Usage: spam [OPTIONS]
Options:
--older-than-days <DAYS>
Only purge messages marked spam at least this many days ago. Defaults to 30
-h, --help
Print help
```
### afmail purge trash - Permanently delete old local trash records
```text
Usage: trash [OPTIONS]
Options:
--older-than-days <DAYS>
Only purge messages marked trash at least this many days ago. Defaults to 30
-h, --help
Print help
```
### afmail purge deleted - Permanently delete old local records whose remote message disappeared
```text
Usage: deleted [OPTIONS]
Options:
--older-than-days <DAYS>
Only purge messages marked remote-deleted at least this many days ago. Defaults to 30
-h, --help
Print help
```
## afmail skill - Manage the Agent-First Mail skill for Codex, Claude Code, opencode, and Hermes
```text
Usage: skill <COMMAND>
Commands:
status Show whether the Agent-First Mail skill is installed and valid
install Install the Agent-First Mail skill
uninstall Remove an afmail-managed Agent-First Mail skill
help Print this message or the help of the given subcommand(s)
Options:
-h, --help
Print help
```
### afmail skill status - Show whether the Agent-First Mail skill is installed and valid
```text
Usage: status [OPTIONS]
Options:
--agent <AGENT>
Agent to manage. Defaults to all personal skill targets
Possible values:
- all: Manage every agent that supports the requested scope
- codex: Manage the Codex skill under $CODEX_HOME/skills or .codex/skills
- claude-code: Manage the Claude Code skill under ~/.claude/skills or .claude/skills
- opencode: Manage the opencode skill under ~/.config/opencode/skills or .opencode/skills
- hermes: Manage the Hermes skill under $HERMES_HOME/skills or ~/.hermes/skills
[default: all]
--scope <SCOPE>
Skill scope. Workspace scope installs under the current workspace's skill directory
Possible values:
- personal: Install under the user-level skills directory
- workspace: Install under the current workspace's skills directory
[default: personal]
--skills-dir <SKILLS_DIR>
Directory that contains skill folders. Requires an explicit single --agent
-h, --help
Print help (see a summary with '-h')
```
### afmail skill install - Install the Agent-First Mail skill
```text
Usage: install [OPTIONS]
Options:
--agent <AGENT>
Agent to manage. Defaults to all personal skill targets
Possible values:
- all: Manage every agent that supports the requested scope
- codex: Manage the Codex skill under $CODEX_HOME/skills or .codex/skills
- claude-code: Manage the Claude Code skill under ~/.claude/skills or .claude/skills
- opencode: Manage the opencode skill under ~/.config/opencode/skills or .opencode/skills
- hermes: Manage the Hermes skill under $HERMES_HOME/skills or ~/.hermes/skills
[default: all]
--scope <SCOPE>
Skill scope. Workspace scope installs under the current workspace's skill directory
Possible values:
- personal: Install under the user-level skills directory
- workspace: Install under the current workspace's skills directory
[default: personal]
--skills-dir <SKILLS_DIR>
Directory that contains skill folders. Requires an explicit single --agent
--force
Overwrite or remove an unmanaged Agent-First Mail skill at the target path
-h, --help
Print help (see a summary with '-h')
```
### afmail skill uninstall - Remove an afmail-managed Agent-First Mail skill
```text
Usage: uninstall [OPTIONS]
Options:
--agent <AGENT>
Agent to manage. Defaults to all personal skill targets
Possible values:
- all: Manage every agent that supports the requested scope
- codex: Manage the Codex skill under $CODEX_HOME/skills or .codex/skills
- claude-code: Manage the Claude Code skill under ~/.claude/skills or .claude/skills
- opencode: Manage the opencode skill under ~/.config/opencode/skills or .opencode/skills
- hermes: Manage the Hermes skill under $HERMES_HOME/skills or ~/.hermes/skills
[default: all]
--scope <SCOPE>
Skill scope. Workspace scope installs under the current workspace's skill directory
Possible values:
- personal: Install under the user-level skills directory
- workspace: Install under the current workspace's skills directory
[default: personal]
--skills-dir <SKILLS_DIR>
Directory that contains skill folders. Requires an explicit single --agent
--force
Overwrite or remove an unmanaged Agent-First Mail skill at the target path
-h, --help
Print help (see a summary with '-h')
```
## afmail triage - Inspect the triage queue
```text
Usage: triage <COMMAND>
Commands:
list List compact untriaged message locators
help Print this message or the help of the given subcommand(s)
Options:
-h, --help
Print help
```
### afmail triage list - List compact untriaged message locators
```text
Usage: list
Options:
-h, --help
Print help
```
## afmail message - Operate on any local message id
```text
Usage: message <COMMAND>
Commands:
show Show the full local message metadata, body text, and attachment metadata
spam Mark junk/phishing/malware/suspicious mail locally, show it under spam/, and queue a Junk move
trash Explicitly discard this message locally, show it under trash/, and queue a Trash move
restore Restore a message from spam, trash, or direct archive back to triage
attachment Fetch an attachment for this message
help Print this message or the help of the given subcommand(s)
Options:
-h, --help
Print help
```
### afmail message show - Show the full local message metadata, body text, and attachment metadata
```text
Usage: show <MESSAGE_ID>
Arguments:
<MESSAGE_ID>
Message id, for example message_inbox_607146690_22
Options:
-h, --help
Print help
```
### afmail message spam - Mark junk/phishing/malware/suspicious mail locally, show it under spam/, and queue a Junk move
```text
Usage: spam [OPTIONS] <MESSAGE_ID>
Arguments:
<MESSAGE_ID>
Message id, for example message_inbox_607146690_22
Options:
--reason <REASON>
Why this disposition is correct; required by default
-h, --help
Print help
```
### afmail message trash - Explicitly discard this message locally, show it under trash/, and queue a Trash move
```text
Usage: trash [OPTIONS] <MESSAGE_ID>
Arguments:
<MESSAGE_ID>
Message id, for example message_inbox_607146690_22
Options:
--reason <REASON>
Why this disposition is correct; required by default
-h, --help
Print help
```
### afmail message restore - Restore a message from spam, trash, or direct archive back to triage
```text
Usage: restore [OPTIONS] <MESSAGE_ID>
Arguments:
<MESSAGE_ID>
Message id, for example message_inbox_607146690_22
Options:
--reason <REASON>
Why this restore is correct; required by default
-h, --help
Print help
```
### afmail message attachment - Fetch an attachment for this message
```text
Usage: attachment <COMMAND>
Commands:
fetch Fetch one attachment by MIME part id, or all attachments when omitted
help Print this message or the help of the given subcommand(s)
Options:
-h, --help
Print help
```
#### afmail message attachment fetch - Fetch one attachment by MIME part id, or all attachments when omitted
```text
Usage: fetch <MESSAGE_ID> [PART_ID]
Arguments:
<MESSAGE_ID>
Message id, for example message_inbox_607146690_22
[PART_ID]
Options:
-h, --help
Print help
```
## afmail case - Create a case or operate on an existing case ref
```text
Usage: case <COMMAND>
Commands:
create Create a new case and return its stable UID/ref
list List compact active case locators
show Show a case's case.md (active or archived) without changing workspace state
add Add a message to this existing case
move Move this case to another group
rename Rename this active case's human-readable name without changing its UID
notes Show or edit active case notes
archive Archive this active case
reopen Reopen this case as active work without changing its tags
tag Add a case organization tag
untag Remove a case organization tag
draft Create, edit, validate, queue, or remove local case drafts
merge Merge another case into this case
help Print this message or the help of the given subcommand(s)
Options:
-h, --help
Print help
```
### afmail case create - Create a new case and return its stable UID/ref
```text
Usage: create [OPTIONS] --name <NAME>
Options:
--name <NAME>
Human-readable case name used in case.md and the directory suffix
--group <GROUP>
Destination group. Defaults to the configured default group
--message <MESSAGE>
Optional first message to add to the case
--summary <SUMMARY>
Short summary for the first message
--reason <REASON>
Why this case is being created
-h, --help
Print help
```
### afmail case list - List compact active case locators
```text
Usage: list
Options:
-h, --help
Print help
```
### afmail case show - Show a case's case.md (active or archived) without changing workspace state
```text
Usage: show <CASE_REF>
Arguments:
<CASE_REF>
Case ref: cYYYYMMDDNNN or cYYYYMMDDNNN-any-suffix
Options:
-h, --help
Print help
```
### afmail case add - Add a message to this existing case
```text
Usage: add [OPTIONS] <CASE_REF> <MESSAGE_ID>
Arguments:
<CASE_REF>
Case ref: cYYYYMMDDNNN or cYYYYMMDDNNN-any-suffix
<MESSAGE_ID>
Message id to add
Options:
--summary <SUMMARY>
Short summary for this message in the case
--reason <REASON>
Why this message belongs in this case; required by default
-h, --help
Print help
```
### afmail case move - Move this case to another group
```text
Usage: move <CASE_REF> <GROUP>
Arguments:
<CASE_REF>
Case ref: cYYYYMMDDNNN or cYYYYMMDDNNN-any-suffix
<GROUP>
Destination group
Options:
-h, --help
Print help
```
### afmail case rename - Rename this active case's human-readable name without changing its UID
```text
Usage: rename [OPTIONS] --name <NAME> <CASE_REF>
Arguments:
<CASE_REF>
Case ref: cYYYYMMDDNNN or cYYYYMMDDNNN-any-suffix
Options:
--name <NAME>
New human-readable case name
--reason <REASON>
Why this name better represents the case; required by default
-h, --help
Print help
```
### afmail case notes - Show or edit active case notes
```text
Usage: notes <COMMAND>
Commands:
show Show notes markdown
append Append text to notes markdown
replace Replace notes markdown with text
help Print this message or the help of the given subcommand(s)
Options:
-h, --help
Print help
```
#### afmail case notes show - Show notes markdown
```text
Usage: show <CASE_REF>
Arguments:
<CASE_REF>
Case ref: cYYYYMMDDNNN or cYYYYMMDDNNN-any-suffix
Options:
-h, --help
Print help
```
#### afmail case notes append - Append text to notes markdown
```text
Usage: append --text <TEXT> <CASE_REF>
Arguments:
<CASE_REF>
Case ref: cYYYYMMDDNNN or cYYYYMMDDNNN-any-suffix
Options:
--text <TEXT>
Markdown text to append
-h, --help
Print help
```
#### afmail case notes replace - Replace notes markdown with text
```text
Usage: replace --text <TEXT> <CASE_REF>
Arguments:
<CASE_REF>
Case ref: cYYYYMMDDNNN or cYYYYMMDDNNN-any-suffix
Options:
--text <TEXT>
Markdown text to write
-h, --help
Print help
```
### afmail case archive - Archive this active case
```text
Usage: archive [OPTIONS] <CASE_REF>
Arguments:
<CASE_REF>
Case ref: cYYYYMMDDNNN or cYYYYMMDDNNN-any-suffix
Options:
--reason <REASON>
Why this case is ready to archive; required by default
-h, --help
Print help
```
### afmail case reopen - Reopen this case as active work without changing its tags
```text
Usage: reopen [OPTIONS] <CASE_REF>
Arguments:
<CASE_REF>
Case ref: cYYYYMMDDNNN or cYYYYMMDDNNN-any-suffix
Options:
--reason <REASON>
Why this case should be reopened; required by default
-h, --help
Print help
```
### afmail case tag - Add a case organization tag
```text
Usage: tag [OPTIONS] <CASE_REF> <TAG>
Arguments:
<CASE_REF>
Case ref: cYYYYMMDDNNN or cYYYYMMDDNNN-any-suffix
<TAG>
Case organization tag
Options:
--reason <REASON>
Why this tag is useful; required by default
-h, --help
Print help
```
### afmail case untag - Remove a case organization tag
```text
Usage: untag [OPTIONS] <CASE_REF> <TAG>
Arguments:
<CASE_REF>
Case ref: cYYYYMMDDNNN or cYYYYMMDDNNN-any-suffix
<TAG>
Case organization tag
Options:
--reason <REASON>
Why this tag should be removed; required by default
-h, --help
Print help
```
### afmail case draft - Create, edit, validate, queue, or remove local case drafts
```text
Usage: draft <COMMAND>
Commands:
new Scaffold a new outbound draft (not a reply) in this case
reply Scaffold a reply draft to a message, prefilled and quoting the original
change Change an existing editable draft in place
show Show an existing draft in a review-friendly JSON shape
validate Validate a draft under the case drafts directory
save Queue this draft to be saved to the remote Drafts mailbox
send Queue this draft to be sent and recorded in the case after push succeeds
attach Copy or reference a file and add it to a draft's attachments
remove Remove a local draft and any queued outbound item for it
help Print this message or the help of the given subcommand(s)
Options:
-h, --help
Print help
```
#### afmail case draft new - Scaffold a new outbound draft (not a reply) in this case
```text
Usage: new [OPTIONS] --to <TO> --subject <SUBJECT> <CASE_REF>
Arguments:
<CASE_REF>
Case ref: cYYYYMMDDNNN or cYYYYMMDDNNN-any-suffix
Options:
--to <TO>
Recipient address. Repeatable
--cc <CC>
Cc address. Repeatable
--subject <SUBJECT>
Draft subject
--identity <IDENTITY>
Workspace identity slug to send as. Defaults to the configured default identity
--body <BODY>
Draft body text
--body-file <BODY_FILE>
Path to a file whose contents become the draft body
-h, --help
Print help
```
#### afmail case draft reply - Scaffold a reply draft to a message, prefilled and quoting the original
```text
Usage: reply [OPTIONS] <CASE_REF> <MESSAGE_ID>
Arguments:
<CASE_REF>
Case ref: cYYYYMMDDNNN or cYYYYMMDDNNN-any-suffix
<MESSAGE_ID>
Message id in this case to reply to
Options:
--identity <IDENTITY>
Workspace identity slug to send as. Defaults to the configured default identity
--body <BODY>
Draft body text. Replaces the default reply template when provided
--body-file <BODY_FILE>
Path to a file whose contents become the draft body
--all
Reply to all original recipients (To and Cc), not just the sender
-h, --help
Print help
```
#### afmail case draft change - Change an existing editable draft in place
```text
Usage: change [OPTIONS] <CASE_REF> <DRAFT_NAME>
Arguments:
<CASE_REF>
Case ref: cYYYYMMDDNNN or cYYYYMMDDNNN-any-suffix
<DRAFT_NAME>
Draft markdown file under the case drafts directory
Options:
--subject <SUBJECT>
Replacement subject
--to <TO>
Replacement To list. Repeatable; when provided it replaces all To recipients
--cc <CC>
Replacement Cc list. Repeatable; when provided it replaces all Cc recipients
--clear-cc
Clear all Cc recipients
--identity <IDENTITY>
Change the workspace identity slug used by this draft
--body <BODY>
Replacement draft body text
--body-file <BODY_FILE>
Path to a file whose contents replace the draft body
-h, --help
Print help
```
#### afmail case draft show - Show an existing draft in a review-friendly JSON shape
```text
Usage: show <CASE_REF> <DRAFT_NAME>
Arguments:
<CASE_REF>
Case ref: cYYYYMMDDNNN or cYYYYMMDDNNN-any-suffix
<DRAFT_NAME>
Draft markdown file under the case drafts directory
Options:
-h, --help
Print help
```
#### afmail case draft validate - Validate a draft under the case drafts directory
```text
Usage: validate <CASE_REF> <DRAFT_NAME>
Arguments:
<CASE_REF>
Case ref: cYYYYMMDDNNN or cYYYYMMDDNNN-any-suffix
<DRAFT_NAME>
Draft markdown file under the case drafts directory
Options:
-h, --help
Print help
```
#### afmail case draft save - Queue this draft to be saved to the remote Drafts mailbox
```text
Usage: save <CASE_REF> <DRAFT_NAME>
Arguments:
<CASE_REF>
Case ref: cYYYYMMDDNNN or cYYYYMMDDNNN-any-suffix
<DRAFT_NAME>
Draft markdown file under the case drafts directory
Options:
-h, --help
Print help
```
#### afmail case draft send - Queue this draft to be sent and recorded in the case after push succeeds
```text
Usage: send <CASE_REF> <DRAFT_NAME>
Arguments:
<CASE_REF>
Case ref: cYYYYMMDDNNN or cYYYYMMDDNNN-any-suffix
<DRAFT_NAME>
Draft markdown file under the case drafts directory
Options:
-h, --help
Print help
```
#### afmail case draft attach - Copy or reference a file and add it to a draft's attachments
```text
Usage: attach <CASE_REF> <DRAFT_NAME> <PATH>
Arguments:
<CASE_REF>
Case ref: cYYYYMMDDNNN or cYYYYMMDDNNN-any-suffix
<DRAFT_NAME>
Draft markdown file under the case drafts directory
<PATH>
Local file path to attach
Options:
-h, --help
Print help
```
#### afmail case draft remove - Remove a local draft and any queued outbound item for it
```text
Usage: remove [OPTIONS] <CASE_REF> <DRAFT_NAME>
Arguments:
<CASE_REF>
Case ref: cYYYYMMDDNNN or cYYYYMMDDNNN-any-suffix
<DRAFT_NAME>
Draft markdown file under the case drafts directory
Options:
--reason <REASON>
Why this draft should be removed; required by default
-h, --help
Print help
```
### afmail case merge - Merge another case into this case
```text
Usage: merge [OPTIONS] <CASE_REF> <OTHER_CASE_REF>
Arguments:
<CASE_REF>
Primary case ref
<OTHER_CASE_REF>
Case ref to merge into the primary case
Options:
--reason <REASON>
Why these cases should be merged; required by default
-h, --help
Print help
```
## afmail contact - Create a contact or operate on an existing contact ref
```text
Usage: contact <COMMAND>
Commands:
create Create a new contact record
list List contacts, optionally filtered by group, tag, org, or role
show Show a contact's full file content
move Move a contact to a different group
rename Rename a contact's display name
email Add or remove email addresses for a contact
phone Add or remove phone numbers for a contact
tag Add a tag to a contact
untag Remove a tag from a contact
notes Show or edit contact notes
archive Archive an active contact
reopen Reopen an archived contact as active
extract Extract stub contacts from message senders not yet in the contact list
help Print this message or the help of the given subcommand(s)
Options:
-h, --help
Print help
```
### afmail contact create - Create a new contact record
```text
Usage: create [OPTIONS] --name <NAME>
Options:
--name <NAME>
Display name for the contact
--group <GROUP>
Group. Defaults to the configured default contact group
--email <EMAILS>
Email address. Repeatable
--phone <PHONES>
Phone number. Repeatable
--org <ORG>
Organization name
--role <ROLE>
Role or title
--tag <TAGS>
Tag. Repeatable
-h, --help
Print help
```
### afmail contact list - List contacts, optionally filtered by group, tag, org, or role
```text
Usage: list [OPTIONS]
Options:
--group <GROUP>
Filter to a specific group
--tag <TAG>
Filter by tag
--org <ORG>
Filter by organization
--role <ROLE>
Filter by role
-h, --help
Print help
```
### afmail contact show - Show a contact's full file content
```text
Usage: show <CONTACT_REF>
Arguments:
<CONTACT_REF>
Contact ref: pYYYYMMDDNNN or pYYYYMMDDNNN-any-suffix
Options:
-h, --help
Print help
```
### afmail contact move - Move a contact to a different group
```text
Usage: move --group <GROUP> <CONTACT_REF>
Arguments:
<CONTACT_REF>
Contact ref: pYYYYMMDDNNN or pYYYYMMDDNNN-any-suffix
Options:
--group <GROUP>
Destination group
-h, --help
Print help
```
### afmail contact rename - Rename a contact's display name
```text
Usage: rename --name <NAME> <CONTACT_REF>
Arguments:
<CONTACT_REF>
Contact ref: pYYYYMMDDNNN or pYYYYMMDDNNN-any-suffix
Options:
--name <NAME>
New display name
-h, --help
Print help
```
### afmail contact email - Add or remove email addresses for a contact
```text
Usage: email <COMMAND>
Commands:
add Add an email address to the contact
remove Remove an email address from the contact
help Print this message or the help of the given subcommand(s)
Options:
-h, --help
Print help
```
#### afmail contact email add - Add an email address to the contact
```text
Usage: add <CONTACT_REF> <EMAIL>
Arguments:
<CONTACT_REF>
Contact ref: pYYYYMMDDNNN or pYYYYMMDDNNN-any-suffix
<EMAIL>
Email address to add
Options:
-h, --help
Print help
```
#### afmail contact email remove - Remove an email address from the contact
```text
Usage: remove <CONTACT_REF> <EMAIL>
Arguments:
<CONTACT_REF>
Contact ref: pYYYYMMDDNNN or pYYYYMMDDNNN-any-suffix
<EMAIL>
Email address to remove
Options:
-h, --help
Print help
```
### afmail contact phone - Add or remove phone numbers for a contact
```text
Usage: phone <COMMAND>
Commands:
add Add a phone number to the contact
remove Remove a phone number from the contact
help Print this message or the help of the given subcommand(s)
Options:
-h, --help
Print help
```
#### afmail contact phone add - Add a phone number to the contact
```text
Usage: add <CONTACT_REF> <PHONE>
Arguments:
<CONTACT_REF>
Contact ref: pYYYYMMDDNNN or pYYYYMMDDNNN-any-suffix
<PHONE>
Phone number to add
Options:
-h, --help
Print help
```
#### afmail contact phone remove - Remove a phone number from the contact
```text
Usage: remove <CONTACT_REF> <PHONE>
Arguments:
<CONTACT_REF>
Contact ref: pYYYYMMDDNNN or pYYYYMMDDNNN-any-suffix
<PHONE>
Phone number to remove
Options:
-h, --help
Print help
```
### afmail contact tag - Add a tag to a contact
```text
Usage: tag <CONTACT_REF> <TAG>
Arguments:
<CONTACT_REF>
Contact ref: pYYYYMMDDNNN or pYYYYMMDDNNN-any-suffix
<TAG>
Tag to add
Options:
-h, --help
Print help
```
### afmail contact untag - Remove a tag from a contact
```text
Usage: untag <CONTACT_REF> <TAG>
Arguments:
<CONTACT_REF>
Contact ref: pYYYYMMDDNNN or pYYYYMMDDNNN-any-suffix
<TAG>
Tag to remove
Options:
-h, --help
Print help
```
### afmail contact notes - Show or edit contact notes
```text
Usage: notes <COMMAND>
Commands:
show Show notes markdown
append Append text to notes markdown
replace Replace notes markdown with text
help Print this message or the help of the given subcommand(s)
Options:
-h, --help
Print help
```
#### afmail contact notes show - Show notes markdown
```text
Usage: show <CONTACT_REF>
Arguments:
<CONTACT_REF>
Contact ref: pYYYYMMDDNNN or pYYYYMMDDNNN-any-suffix
Options:
-h, --help
Print help
```
#### afmail contact notes append - Append text to notes markdown
```text
Usage: append --text <TEXT> <CONTACT_REF>
Arguments:
<CONTACT_REF>
Contact ref: pYYYYMMDDNNN or pYYYYMMDDNNN-any-suffix
Options:
--text <TEXT>
Markdown text to append
-h, --help
Print help
```
#### afmail contact notes replace - Replace notes markdown with text
```text
Usage: replace --text <TEXT> <CONTACT_REF>
Arguments:
<CONTACT_REF>
Contact ref: pYYYYMMDDNNN or pYYYYMMDDNNN-any-suffix
Options:
--text <TEXT>
Markdown text to write
-h, --help
Print help
```
### afmail contact archive - Archive an active contact
```text
Usage: archive [OPTIONS] <CONTACT_REF>
Arguments:
<CONTACT_REF>
Contact ref: pYYYYMMDDNNN or pYYYYMMDDNNN-any-suffix
Options:
--reason <REASON>
Why this contact is being archived; required by default
-h, --help
Print help
```
### afmail contact reopen - Reopen an archived contact as active
```text
Usage: reopen [OPTIONS] <CONTACT_REF>
Arguments:
<CONTACT_REF>
Contact ref: pYYYYMMDDNNN or pYYYYMMDDNNN-any-suffix
Options:
--group <GROUP>
Destination group. Defaults to contact.default_group in config
--reason <REASON>
Why this contact should be reopened; required by default
-h, --help
Print help
```
### afmail contact extract - Extract stub contacts from message senders not yet in the contact list
```text
Usage: extract [OPTIONS]
Options:
--from-triage
Extract from triage messages only
--from-case <CASE_REF>
Extract from a specific case's messages
--all
Extract from all triage and case messages
--group <GROUP>
Destination group for created contacts. Defaults to contact.default_group
-h, --help
Print help
```
## afmail archive - Inspect and manage archived cases and direct-message archive categories
```text
Usage: archive <COMMAND>
Commands:
list List compact archived cases and/or direct-message archive categories
message Operate on a direct-message archive category
case Operate on an archived case
help Print this message or the help of the given subcommand(s)
Options:
-h, --help
Print help
```
### afmail archive list - List compact archived cases and/or direct-message archive categories
```text
Usage: list [COMMAND]
Commands:
cases List compact archived cases
messages List compact direct-message archive categories
help Print this message or the help of the given subcommand(s)
Options:
-h, --help
Print help
```
#### afmail archive list cases - List compact archived cases
```text
Usage: cases
Options:
-h, --help
Print help
```
#### afmail archive list messages - List compact direct-message archive categories
```text
Usage: messages
Options:
-h, --help
Print help
```
### afmail archive message - Operate on a direct-message archive category
```text
Usage: message <COMMAND>
Commands:
create Create a direct-message archive category and optionally file one message
add File an existing message into this direct-message archive category
show Show archive category index and entries
restore Restore a direct archived message to triage
move Move a direct archived message to another archive category
rename Rename this archive category's human-readable name without changing its UID
set-summary Set or replace one direct archive entry summary
notes Show or edit archive category notes
help Print this message or the help of the given subcommand(s)
Options:
-h, --help
Print help
```
#### afmail archive message create - Create a direct-message archive category and optionally file one message
```text
Usage: create [OPTIONS] --name <NAME>
Options:
--name <NAME>
Human-readable archive category name used in metadata and the directory suffix
--message <MESSAGE>
Optional message to immediately file into the new archive category
--summary <SUMMARY>
Required when --message is supplied
--reason <REASON>
Why this archive category is being created
-h, --help
Print help
```
#### afmail archive message add - File an existing message into this direct-message archive category
```text
Usage: add [OPTIONS] --summary <SUMMARY> <ARCHIVE_REF> <MESSAGE_ID>
Arguments:
<ARCHIVE_REF>
Direct-message archive category ref: aYYYYMMDDNNN or aYYYYMMDDNNN-any-suffix
<MESSAGE_ID>
Message id to file
Options:
--summary <SUMMARY>
Human/agent-authored summary for this archive entry
--reason <REASON>
Why this disposition is correct; required by default
-h, --help
Print help
```
#### afmail archive message show - Show archive category index and entries
```text
Usage: show <ARCHIVE_REF>
Arguments:
<ARCHIVE_REF>
Direct-message archive category ref: aYYYYMMDDNNN or aYYYYMMDDNNN-any-suffix
Options:
-h, --help
Print help
```
#### afmail archive message restore - Restore a direct archived message to triage
```text
Usage: restore [OPTIONS] <ARCHIVE_REF> <MESSAGE_ID>
Arguments:
<ARCHIVE_REF>
Direct-message archive category ref: aYYYYMMDDNNN or aYYYYMMDDNNN-any-suffix
<MESSAGE_ID>
Options:
--reason <REASON>
Why this message needs active triage again; required by default
-h, --help
Print help
```
#### afmail archive message move - Move a direct archived message to another archive category
```text
Usage: move [OPTIONS] <ARCHIVE_REF> <MESSAGE_ID> <NEW_ARCHIVE_REF>
Arguments:
<ARCHIVE_REF>
Source direct-message archive category ref
<MESSAGE_ID>
<NEW_ARCHIVE_REF>
Destination archive category ref
Options:
--reason <REASON>
Why this category is better; required by default
-h, --help
Print help
```
#### afmail archive message rename - Rename this archive category's human-readable name without changing its UID
```text
Usage: rename [OPTIONS] --name <NAME> <ARCHIVE_REF>
Arguments:
<ARCHIVE_REF>
Direct-message archive category ref: aYYYYMMDDNNN or aYYYYMMDDNNN-any-suffix
Options:
--name <NAME>
New human-readable archive name
--reason <REASON>
Why this name better represents the category; required by default
-h, --help
Print help
```
#### afmail archive message set-summary - Set or replace one direct archive entry summary
```text
Usage: set-summary [OPTIONS] --summary <SUMMARY> <ARCHIVE_REF> <MESSAGE_ID>
Arguments:
<ARCHIVE_REF>
Direct-message archive category ref: aYYYYMMDDNNN or aYYYYMMDDNNN-any-suffix
<MESSAGE_ID>
Options:
--summary <SUMMARY>
--reason <REASON>
Why this summary is useful; required by default
-h, --help
Print help
```
#### afmail archive message notes - Show or edit archive category notes
```text
Usage: notes <COMMAND>
Commands:
show Show notes markdown
append Append text to notes markdown
replace Replace notes markdown with text
help Print this message or the help of the given subcommand(s)
Options:
-h, --help
Print help
```
##### afmail archive message notes show - Show notes markdown
```text
Usage: show <ARCHIVE_REF>
Arguments:
<ARCHIVE_REF>
Direct-message archive category ref: aYYYYMMDDNNN or aYYYYMMDDNNN-any-suffix
Options:
-h, --help
Print help
```
##### afmail archive message notes append - Append text to notes markdown
```text
Usage: append --text <TEXT> <ARCHIVE_REF>
Arguments:
<ARCHIVE_REF>
Direct-message archive category ref: aYYYYMMDDNNN or aYYYYMMDDNNN-any-suffix
Options:
--text <TEXT>
Markdown text to append
-h, --help
Print help
```
##### afmail archive message notes replace - Replace notes markdown with text
```text
Usage: replace --text <TEXT> <ARCHIVE_REF>
Arguments:
<ARCHIVE_REF>
Direct-message archive category ref: aYYYYMMDDNNN or aYYYYMMDDNNN-any-suffix
Options:
--text <TEXT>
Markdown text to write
-h, --help
Print help
```
### afmail archive case - Operate on an archived case
```text
Usage: case <COMMAND>
Commands:
show Show the archived case
restore Restore an archived case to an active case group
rename Rename this archived case's human-readable name without changing its UID
notes Show or edit archived case notes
help Print this message or the help of the given subcommand(s)
Options:
-h, --help
Print help
```
#### afmail archive case show - Show the archived case
```text
Usage: show <CASE_REF>
Arguments:
<CASE_REF>
Case ref: cYYYYMMDDNNN or cYYYYMMDDNNN-any-suffix
Options:
-h, --help
Print help
```
#### afmail archive case restore - Restore an archived case to an active case group
```text
Usage: restore [OPTIONS] --group <GROUP> <CASE_REF>
Arguments:
<CASE_REF>
Case ref: cYYYYMMDDNNN or cYYYYMMDDNNN-any-suffix
Options:
--group <GROUP>
Active case group to restore into
--reason <REASON>
Why this case needs active attention again; required by default
-h, --help
Print help
```
#### afmail archive case rename - Rename this archived case's human-readable name without changing its UID
```text
Usage: rename [OPTIONS] --name <NAME> <CASE_REF>
Arguments:
<CASE_REF>
Case ref: cYYYYMMDDNNN or cYYYYMMDDNNN-any-suffix
Options:
--name <NAME>
New human-readable case name
--reason <REASON>
Why this name better represents the case; required by default
-h, --help
Print help
```
#### afmail archive case notes - Show or edit archived case notes
```text
Usage: notes <COMMAND>
Commands:
show Show notes markdown
append Append text to notes markdown
replace Replace notes markdown with text
help Print this message or the help of the given subcommand(s)
Options:
-h, --help
Print help
```
##### afmail archive case notes show - Show notes markdown
```text
Usage: show <CASE_REF>
Arguments:
<CASE_REF>
Case ref: cYYYYMMDDNNN or cYYYYMMDDNNN-any-suffix
Options:
-h, --help
Print help
```
##### afmail archive case notes append - Append text to notes markdown
```text
Usage: append --text <TEXT> <CASE_REF>
Arguments:
<CASE_REF>
Case ref: cYYYYMMDDNNN or cYYYYMMDDNNN-any-suffix
Options:
--text <TEXT>
Markdown text to append
-h, --help
Print help
```
##### afmail archive case notes replace - Replace notes markdown with text
```text
Usage: replace --text <TEXT> <CASE_REF>
Arguments:
<CASE_REF>
Case ref: cYYYYMMDDNNN or cYYYYMMDDNNN-any-suffix
Options:
--text <TEXT>
Markdown text to write
-h, --help
Print help
```
## afmail render - Rebuild generated read views from local workspace state
```text
Usage: render <COMMAND>
Commands:
refresh Rebuild generated case and direct-message archive read views
templates Export built-in language templates, keeping existing files unless forced
help Print this message or the help of the given subcommand(s)
Options:
-h, --help
Print help
```
### afmail render refresh - Rebuild generated case and direct-message archive read views
```text
Usage: refresh
Options:
-h, --help
Print help
```
### afmail render templates - Export built-in language templates, keeping existing files unless forced
```text
Usage: templates [OPTIONS]
Options:
--force
Overwrite existing workspace templates with built-in defaults
-h, --help
Print help
```
## afmail log - Inspect the workspace audit log
```text
Usage: log <COMMAND>
Commands:
list List recent audit events
tail Tail recent audit events as JSON data
message List events for one message id
case List events for one case id
archive List events for one archive category
help Print this message or the help of the given subcommand(s)
Options:
-h, --help
Print help
```
### afmail log list - List recent audit events
```text
Usage: list [OPTIONS]
Options:
--limit <LIMIT>
Maximum number of events to return
[default: 50]
-h, --help
Print help
```
### afmail log tail - Tail recent audit events as JSON data
```text
Usage: tail
Options:
-h, --help
Print help
```
### afmail log message - List events for one message id
```text
Usage: message <MESSAGE_ID>
Arguments:
<MESSAGE_ID>
Options:
-h, --help
Print help
```
### afmail log case - List events for one case id
```text
Usage: case <CASE_UID>
Arguments:
<CASE_UID>
Options:
-h, --help
Print help
```
### afmail log archive - List events for one archive category
```text
Usage: archive <ARCHIVE_UID>
Arguments:
<ARCHIVE_UID>
Options:
-h, --help
Print help
```