agentsclimarketplace

Submail client

Skill chickenzord/submail/skills/submail-client

Read emails from a Submail virtual inbox using the submail CLI. Use when an agent needs to check, list, or retrieve emails delivered to its inbox address.From its SKILL.md

Install
npx -y skills add chickenzord/submail --skill submail-client

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

One thing to look at

  • 0 stars0 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.

SKILL.md

7.1 KB, ~1.7k tokens by cl100k_base, as published. Nobody here has run it

Submail Client Skill

Submail is a virtual inbox router. Each agent has a dedicated email address and API token. This skill covers everything needed to configure and use the submail CLI to access that inbox.


Prerequisites

  • submail binary is on $PATH
  • You know your server URL, agent token, and (optionally) your profile name

Step 1 — Configure a profile (one-time setup)

Profiles store the server URL and token so you never pass them as flags. Profile files live at ~/.config/submail/profiles/<name>.yaml.

submail profile set <profile-name> \
  --url <server-url> \
  --token <your-agent-token>

Example:

submail profile set hawkeye \
  --url http://localhost:8080 \
  --token hawkeye-secret-token

Validate the profile was saved correctly

submail profile show <profile-name> --json

Expected output (token is always masked):

{"name":"hawkeye","token_set":true,"url":"http://localhost:8080"}

Check: token_set must be true and url must be non-empty. If either is wrong, re-run profile set with the correct values.

Set the active profile for this agent session

export SUBMAIL_PROFILE=<profile-name>

After this, all submail inbox commands use the profile automatically — no --url or --token flags needed.


Step 2 — Verify connectivity

Run a quick sanity check before doing real work:

submail inbox list --json --limit 1
Exit codeMeaningFix
0Connected and authenticated
4Token rejectedRe-run profile set with the correct token
1Server unreachableCheck url in the profile; confirm server is running

A successful response looks like:

{"mails":[...],"total":5,"limit":1,"offset":0}

If total is 0 the inbox is empty — that is not an error.


Available tasks

List messages

submail inbox list --json

Response schema:

{
  "mails": [
    {
      "id":          "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
      "message_id":  "<[email protected]>",
      "subject":     "Subject line",
      "from":        "[email protected]",
      "to":          "[email protected]",
      "received_at": "2026-01-01T00:00:00Z"
    }
  ],
  "total":  42,
  "limit":  50,
  "offset": 0
}

Key fields:

  • id — UUID used to fetch the full message; use this in inbox get
  • received_at — ISO 8601 UTC timestamp
  • total — total matching messages (ignores limit/offset)
  • mails may be an empty array [] — that is not an error

Pagination

# First page
submail inbox list --json --limit 20 --offset 0

# Second page
submail inbox list --json --limit 20 --offset 20

Iterate until offset + len(mails) >= total.

Get only IDs (pipe-friendly)

submail inbox list --quiet

Outputs one UUID per line. Useful for looping or piping.


Get a single message

submail inbox get --json <id>

<id> must be a lowercase UUID (xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx). Obtain it from the id field in inbox list.

Response schema (same as list items, plus body fields):

{
  "id":          "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
  "message_id":  "<[email protected]>",
  "subject":     "Subject line",
  "from":        "[email protected]",
  "to":          "[email protected]",
  "received_at": "2026-01-01T00:00:00Z",
  "text_body":   "Plain-text content of the email.",
  "html_body":   "<html>...</html>"
}
  • text_body — prefer this for content parsing; may be empty for HTML-only emails
  • html_body — raw HTML; present when the sender included an HTML part
  • Both fields are omitted (not null) when absent

Exit codes

CodeMeaningRetryable
0Success
2Bad input (e.g. malformed UUID)No — fix the input
3Message not foundNo
4Unauthorized — wrong tokenNo — fix the profile
1Server / network errorYes

Always check $? after each command. On non-zero exit (JSON mode), stdout contains a structured error:

{
  "error":     "not_found",
  "message":   "mail not found",
  "input":     {"id": "00000000-0000-0000-0000-000000000000"},
  "retryable": false
}

Use retryable to decide whether to retry or abort.


Common workflows

Read the most recent message

ID=$(submail inbox list --quiet --limit 1)
submail inbox get --json "$ID"

Process all messages newest-first

LIMIT=20
OFFSET=0

while true; do
  PAGE=$(submail inbox list --json --limit $LIMIT --offset $OFFSET)
  TOTAL=$(echo "$PAGE" | jq '.total')
  IDS=$(echo "$PAGE"  | jq -r '.mails[].id')

  for ID in $IDS; do
    submail inbox get --json "$ID" | jq '.text_body'
  done

  OFFSET=$((OFFSET + LIMIT))
  [ $OFFSET -ge $TOTAL ] && break
done

Check for new mail since a known timestamp

inbox list does not have a since filter — fetch the list and filter client-side by received_at:

submail inbox list --json --limit 50 | \
  jq '[.mails[] | select(.received_at > "2026-01-01T00:00:00Z")]'

Profile reference

CommandPurpose
submail profile set <name> --url URL --token TOKENCreate or update a profile
submail profile show <name> --jsonVerify a profile (token masked)
submail profile list --jsonList all configured profiles
submail profile delete <name>Remove a profile

Profile files are stored at ~/.config/submail/profiles/<name>.yaml with mode 0600 (readable only by the current OS user).


Credential precedence (most specific wins)

  1. --url / --token flags
  2. SUBMAIL_URL / SUBMAIL_TOKEN environment variables
  3. --profile flag or SUBMAIL_PROFILE environment variable
  4. ~/.config/submail/profiles/default.yaml (silent fallback)

What ships with it

Read from the repository

Just SKILL.md. No reference files, no scripts.

Keep looking

Skills are one crate of 326,422. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.