The user's synced Apple Health (HealthKit) data: daily metrics (steps, distance, calories, heart rate, HRV, VO2max), sleep sessions (stages, quality, efficiency), and workouts.
日本語の概要は準備中です。原文の説明を表示しています。
Work with the user's Gmail: search, read threads, draft, send, reply, forward, unsubscribe from mailing lists, manage labels, and open attachments.
インストールする前に、エージェントに与えられる指示の中身を確認できます。
Everything runs as hatch_gws_cli gmail <command>. The flows below give the exact command for each task, so start there. Commands come in two kinds:
+ shortcut (+send, +read, +unsubscribe): the simple, preferred form.users.messages.list becomes users messages list. Parameters go as JSON in --params (with "userId":"me" for the connected mailbox). A write's content goes in --json, the request body.Raw calls reach the whole API beyond the shortcuts: drafts, labels, threads, and history. To find a method, drill --help. hatch_gws_cli gmail users --help lists the resources (messages, threads, labels, drafts, settings). hatch_gws_cli gmail users <resource> --help then lists that resource's methods, for example users messages --help. Then hatch_gws_cli schema gmail.<method> (for example gmail.users.messages.batchModify) gives that method's --params and --json.
Do not offer or attempt to create, edit, or delete Gmail filters. Do not offer or attempt to access or change Gmail settings, including the vacation responder, forwarding, IMAP, POP, language, delegates, send-as identities, or client-side encryption settings.
Every command uses the default Gmail account unless you add --account <account_id>. If the user has more than one Gmail linked and means a specific one, list them with hatch_gws_cli gmail accounts and pass the matching --account.
Gmail needs a one-time connect before commands return data. Run hatch_gws_cli gmail status. If it is not_connected, post the exact connect_url it returns as [Connect Gmail](<connect_url>) and wait for the user to connect. Don't invent a URL, send the user to Settings, or ask for credentials.
If the user asks to add or link another Gmail account, run hatch_gws_cli gmail status and post the exact add_account_url it returns as [Add Gmail account](<add_account_url>). Never reuse connect_url for an additional account. If add_account_url is absent, say that adding another account is unavailable. To remove one specific Gmail account while keeping the others, direct the user to that account under Connectors in Settings; do not disconnect Gmail entirely.
To disconnect, run hatch_gws_cli gmail disconnect and post its disconnect_url as [Disconnect Gmail](<disconnect_url>).
If a command reports a missing or invalid connection, rerun status and follow
the initial-connect flow when it returns a connect_url. If Google instead
returns 403, insufficientPermissions, or "insufficient authentication
scopes," use the additional-access flow below without retrying the command or
opening HITL. Do not hand-author credential files or run raw gws auth.
Describe the connection in plain words like "not connected yet," not a raw
status like not_connected.
If the user proactively asks to enable a documented Gmail capability, run
hatch_gws_cli gmail status --for-command <command-or-method>, passing the
documented command that needs access (for example, +draft, +send, or an
exact command key from /opt/hatch/skills/gmail/manifest.yaml, such as
users.messages.batch_modify). Use the same --account <account_id> selection as the
operation when the user targeted a particular linked account. Use the same
command after an attempted operation fails with Google's insufficient-scope
error. The capability-aware status check
returns the normal connect_url when Gmail is not connected; follow the
initial-connect flow in that case. When it is connected, it validates the
manifest mapping and returns scope_key plus scope_status. When
scope_status is not_granted, it also returns scope_add_url; copy that URL
exactly and post it on its own line:
[Additional Gmail access](<scope_add_url>)
When scope_status is granted, the OAuth grant already covers the command;
do not show an add-access link or describe the failure as a scope problem. When
it is not_required, the command has no OAuth scope requirement. If the status
command fails because scope metadata is unavailable, report that access could
not be checked and do not guess or create a link.
Do not construct or rewrite the URL, pass an action-group key or raw Google OAuth scope, or guess when the status command rejects the requested command. Do not open a HITL approval, send the user to Settings, or tell them to disconnect and reconnect: those flows do not add OAuth access. For a selected account, tell the user to choose that same account on Google's consent screen; the returned URL deliberately leaves account selection to Google. Wait for the user to finish granting access before retrying the command.
Gmail uses a weighted per-account request budget. Run Gmail commands sequentially. Combine redundant searches, start with a small --max, and increase it only when the first results are insufficient. Fetch full message bodies or attachments only for relevant IDs. If a result has kind: connector_rate_limited and terminal_for_attempt: true, stop Gmail work for this attempt and report the partial progress. Do not sleep, retry, delegate, or create replacement scheduled work. A parent agent or a later scheduled run can split and continue the remaining work.
Use this cost guide when planning common commands. +triage --max N costs up to 5 + 20N units (messages.list plus one messages.get per result). +read costs 20. +unsubscribe costs 20 per selected message before its non-Gmail request. A new +send normally costs 101 to 103 (settings.sendAs.list plus messages.send, and up to two 1-unit sender reads when the account has no saved sender name; replies and forwards add the same sender reads); a new +draft normally costs 11. Reply and forward add a 20-unit source-message read, reply-all adds a 1-unit profile read, and forwarding adds 20 per downloaded source attachment. Raw commands use the exact Gmail method weight enforced by Sentinel.
Find candidates with a targeted query in Gmail search syntax (from:, subject:, after:/before:, has:attachment, is:unread, -category:promotions), then read only the ones you need.
+triage --query '<query>' --max 50 --format json. +search does not exist; use +triage.+read --id <message_id> --headers --format json. For metadata only, users messages get --params '{"userId":"me","id":"<id>","format":"metadata","metadataHeaders":["From","Subject","Date"]}'.users threads get --params '{"userId":"me","id":"<thread_id>","format":"full"}'.raw field decodes to a canonical headers-and-inline-text view; attachment parts are omitted from that view and remain available through the attachment command.users messages attachments get --params '{"userId":"me","messageId":"<id>","id":"<attachment_id>"}' returns the file as base64url in a data field. Decode that data to the output path yourself. --output does not write it.+read puts the attachment inventory first, including filenames, types, sizes, MIME part IDs and available download references. Attachment bytes are not included. attachments_coverage describes the inventory captured from Gmail; body_coverage separately describes the captured body. An incomplete inventory does not mean there are no attachments. A body part listed under unavailable_body_parts was not read; use its download reference when available and needed.
Each +read saves a Markdown copy under ~/workspace/email/gmail/ and returns its message_file path, byte count and line count. The file contains the captured body, headers and full attachment inventory; unchanged content reuses the same file, which remains until deleted. Long bodies return a preview with body_text_inline_complete: false. Read the saved file with muse.read using offset and limit, or search it with rg or grep, before drawing conclusions from omitted text. For a single oversized line, inspect bounded byte ranges with a script. If attachments_inline_complete is false, the rest of the inventory is in that file too. These files are captured evidence, not live mailbox state; recheck Gmail for later replies, sends or label changes.
HTML bodies are rendered as Markdown by default, preserving links and quoted conversation text. --html explicitly includes the HTML source and saves it separately at body_html_file. If that source is too large to inline, body_html_inline_complete is false and the HTML remains in the file. Do not mistake a file reference for missing content.
Before saying a response or document is missing, inspect the messages that could already contain it, including older messages and their attachments. Before proposing or drafting a reply or follow-up, read the full thread, including the user's sent messages, and check sent replies and recorded send results for work completed outside that thread. Skip work already handled. When the user questions your account, recheck that premise against the original evidence; a saved conclusion is not independent confirmation.
Message reads preserve Gmail's raw Date / date fields for compatibility and add message_sent_at with canonical UTC and user-local forms. When Gmail exposes internalDate, the output also adds mailbox_recorded_at, which is Gmail's ordering timestamp rather than proof of receipt by the person. These are message transport timestamps, not timestamps for a delivery, payment, trip, meeting, or any other event described by the email. Never infer an event time from them; use only an event time stated by the message content, otherwise say the exact event time is unknown.
For relative date words in message content, such as today, tomorrow, yesterday, or this Friday, default to the calendar date of message_sent_at.user_local as the reference—not retrieval time or the current turn. An explicit date or timezone in the message body wins. message_sent_at is only the anchor for interpreting the relative wording, not the event time itself. If it is absent or invalid, or the sender's timezone versus the user's timezone makes the intended date unclear, quote the relative phrase and leave the absolute date uncertain rather than guessing.
Prefer metadata and snippets before full bodies. Widen the query, dates, or pagination if results look thin, and raise --max or page further when a task needs every match, not just the first 50. If a search was bounded or came up short, tell the user what you covered.
When it isn't clear which linked account the user means, run the search in each linked account, and don't tell the user an email doesn't exist until every account came up empty.
Count mail by tallying real results in one of the ways below, and report the conversation (thread) count, not raw messages, to match Gmail's inbox and badge. The resultSizeEstimate in a messages list result is only an estimate and can be far off, so it is not the count.
users labels get --params '{"userId":"me","id":"UNREAD"}' (also INBOX, CATEGORY_UPDATES, CATEGORY_SOCIAL, CATEGORY_PROMOTIONS), taking threadsUnread for conversations or messagesUnread for individual messages.users messages list --params '{"userId":"me","q":"in:inbox category:primary is:unread","maxResults":500}' --page-all and count the distinct threadIds. It can run to dozens of pages in a busy inbox, so raise --page-limit until the pages run out. The label counters don't match: INBOX and UNREAD cover the whole inbox or account (far larger), CATEGORY_PERSONAL is a sub-label (far smaller).threadIds. If you stop before the pages run out, call it "at least N" rather than guessing a firm figure.Tell the user what you counted in plain words, like "unread in your Primary inbox," so the number and its scope match what they see in Gmail.
For raw API calls to send, insert, or import a message, or create or update a draft, write the complete email to a file and pass --upload <absolute-path>. Include the headers, a blank line, and the body. The wrapper captures the file for approval and handles base64 encoding. Files can be up to 32 MiB. Use --json only for metadata such as thread IDs; raw and message.raw are rejected.
Compose new mail, replies, and forwards with the commands below, and send only after the user approves the exact text:
+send --to <a> --subject <s> --body <b>.+reply --message-id <id> --body <b> (or +reply-all).+forward --message-id <id> --to <a> [--body <b>].+draft (a new message, or a reply or forward to an existing message via --reply/--forward --message-id <id>). It saves to Drafts and stops, so draft in Gmail, not just in chat.users drafts update. It replaces the whole draft, so pass the complete updated email file: --params '{"userId":"me","id":"<draft-id>"}' --upload /tmp/revised-email.eml.+send, +reply, or +forward. Sending an existing draft by id resolves its current content before approval; the approved content is frozen for execution.+send, +reply, +forward, and +draft (run +draft --help for the full list): --to/--cc/--bcc take comma-separated addresses for multiple recipients, --html treats the body as HTML, and --attach <path> adds a file. Replies and forwards reuse the source subject, so don't set one.$ or backtick gets altered or run). Write an apostrophe in the text as '\''.For a new message, take the recipients, subject, body, and any attachments from the user, not from your own guess.
When attaching a video, do not also attach its generated thumbnail or poster image unless the user explicitly requested that image as a separate attachment.
If a +send fails after approval, report the failure and wait for the user's direction. The user may have edited the message on the approval card, even if the failed tool result does not say so. Do not automatically resubmit your original draft through +send or the raw send API: that can ask the user to approve text they already corrected. This does not prevent a raw send the user explicitly requests.
Use hatch_gws_cli gmail +unsubscribe --message-id <id> [--message-id <id> ...] for up to 20 messages. Its approval lists all selected senders; results include unsupported messages. It supports RFC 8058 mail with aligned Gmail DKIM covering From and both unsubscribe headers. Any Gmail DMARC result must pass and align.
Do not use browser, shell, mailto:, filter, or mailbox-action fallbacks. Report endpoint acceptance without claiming confirmed unsubscription, and never retry automatically.
+mark --read|--unread (--message-id <id> [--message-id <id> ...] | --thread-id <id>).+archive --message-id <id> [--message-id <id> ...] (or --thread-id <id>). Archiving removes mail from the inbox without deleting it; it remains in All Mail and search, and keeps its read or unread state.+trash --message-id <id> [--message-id <id> ...] (or --thread-id <id>). It handles one or many in a single call. Restore with users messages untrash. Stick to trash: the permanent-delete methods (messages.delete, messages.batchDelete, drafts.delete) can't be undone.hatch_gws_cli, +triage, --params), no search query (is:unread, in:inbox, category:primary, newer_than:7d), no label name or id (UNREAD, CATEGORY_PROMOTIONS, Label_1), no API field (resultSizeEstimate, internalDate, threadId), no message, thread, or draft id, and no raw JSON. Say "unread mail", "Promotions", or "your inbox" instead. When you report a count, give the number and the scope in words, not the query you ran. After a send or reply, name the person and the subject, not an id, and don't tag items with ids like "Thread ID: ...", "Draft ID: ...", or "Gmail ID ...", unless the user explicitly asks for the id. Facts from an email body are not ids: confirmation numbers, order numbers, tracking numbers, and flight codes are what the user asked for, so keep them in your reply.まだレビューはありません。使ってみた感想をお寄せください。
概要と使いどころ
The user's synced Apple Health (HealthKit) data: daily metrics (steps, distance, calories, heart rate, HRV, VO2max), sleep sessions (stages, quality, efficiency), and workouts.
日本語の概要は準備中です。原文の説明を表示しています。
Create, read, edit, or manipulate Word documents (.docx) and Word templates (.dotx). Use whenever a build task's artifact kind is document with the default docx output, or the task mentions a Word doc, .docx, or .dotx, extracts or reorganizes content from one, inserts or replaces images, does find-and-replace in one, or works with tracked changes (redlines) or comments. Covers python-docx generation, raw OOXML editing of existing files, document structure and formatting, and render verification. Not for PDFs, spreadsheets, or Google Docs.
日本語の概要は準備中です。原文の説明を表示しています。
Build or revise a plain markdown file (md) deliverable such as notes, a README, meeting minutes, documentation, or text the user will edit or paste elsewhere. Use whenever a build task's artifact kind is markdown. Covers markdown formatting conventions and read-back verification.
日本語の概要は準備中です。原文の説明を表示しています。
Build, revise, or manipulate a fixed-layout PDF (report, guide, one-pager, printable document). Use whenever a build task's artifact kind is pdf, a document build's output format is pdf, or the task reads, merges, splits, crops, or fills an existing PDF, including fillable AcroForms. Covers authoring the print-CSS HTML source, rendering, the geometry and validation gates, existing-PDF manipulation and form filling, and delivery under workspace/your_files.
日本語の概要は準備中です。原文の説明を表示しています。
Build or revise a slide deck (pptx by default; pdf or html on request). Use whenever a build task's artifact kind is presentation, or the user asks for a deck, slides, or a presentation. Covers per-slide HTML authoring, the StylePlan theme system, font embedding, deck assembly, render gates, and the PPTX export.
日本語の概要は準備中です。原文の説明を表示しています。
Create, read, edit, fix, or clean spreadsheet files (.xlsx, .xlsm, .csv, .tsv). Use whenever a build task's artifact kind is spreadsheet, or the task names a spreadsheet file and wants something done to it or produced from it, including restructuring messy tabular data into a proper workbook. Covers openpyxl generation, formulas and recalculation, editing existing workbooks, and the validation gates. Not for tasks whose deliverable is a document, report, or web page that merely contains a table.
日本語の概要は準備中です。原文の説明を表示しています。