agentleFS
yacb2yacb2/aidex/skills/comm/SKILL.md

comm

Skill2 starsChanged 33 days agoMITView on GitHub

Use when the user wants to log or draft a real communication with a person — capture an email/WhatsApp that was received, log a meeting or call that happened, or draft a message/email to send — as a written `.context/communications/` entry, kept in the communication''s native language. Fires on "log this email", "save the email the client sent", "capture this WhatsApp from X", "record the call with X", "log the meeting with X", "draft an email to X", "write a reply to the client", "save this thread", and /aidex:comm commands. Not for: capturing a stakeholder/product requirement to act on (/aidex:request); recording a decision/ADR (/aidex:decision); planning multi-step work (/aidex:plan); deferring an idea (/aidex:backlog); research notes (/aidex:research); references (/aidex:reference); ecosystem audits (/aidex:aidex); project-state audits (/aidex:audit).

2 other projects use a version of this.

Adopted by

Most recently taken up by

The file

We split this skill into the rules it gives an agent

4 rules. About 0 are common, 2 are distinctive, and 2 are very specific to this project.

  • ≈0

    Common · estimate

    Many files like this have a rule of this kind.

  • ≈2

    Distinctive · estimate

    This author's own choices. Worth a look.

  • 2

    Very specific

    Tied to their project's names, files or tools. Probably skip.

  • Common
  • Distinctive
  • Very specific
  1. Distinctive:

    Write the body afterward in the native language.

    line 56
  2. Distinctive:

    If the meeting produced no action items, say so and stop — an empty derivation is a valid outcome and inventing work to fill the step is …

    line 137
  3. Very specific:

    Every sent/ draft with channel: email (an email, a reply, "in HTML", "to paste into Outlook" — asked for or not) is built this way.

    line 200
  4. Very specific:

    If the project carries a ratchet baseline (.context/.validate-baseline.json), a non-zero exit means you introduced a NEW violation — fix it …

    line 236

≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
SKILL.md

Communications

Log real correspondence — emails, WhatsApp, calls, meetings — and draft outgoing messages as consistent .context/communications/ entries. Each entry is a folder holding a body.md (plus any attachments alongside it). The taxonomy splits on async vs synchronous: async correspondence has a direction (received/, sent/); synchronous conversations — meetings and calls — have participants, not a direction, and live in meetings/. Communications are kept in their native language (D-04 English-default does NOT apply here; D-11 governs skill descriptions, not artifact bodies).


Sub-actions

CommandScriptPurpose
/aidex:comm new received <slug> [--channel email]scripts/new-communication.shScaffold a received async record (email/WhatsApp) under received/
/aidex:comm new sent <slug> [--channel whatsapp]sameScaffold an outgoing async draft under sent/ (status starts draft)
/aidex:comm new meeting <slug>sameScaffold a synchronous meeting record under meetings/ (participant-based, status: sent)
/aidex:comm new call <slug>sameScaffold a synchronous call record under meetings/ (participant-based, status: sent)
/aidex:comm migratescripts/migrate-communications.shRename pre-canonical email.md / conversation.md bodies to body.md, reporting each

--channel is async-only and accepts email (default), whatsapp, other. For meetings and calls use new meeting / new call — the channel is fixed to the kind.


Dispatch

bash "${CLAUDE_SKILL_DIR}/scripts/new-communication.sh" "$@"

For migrate:

bash "${CLAUDE_SKILL_DIR}/scripts/migrate-communications.sh"

It renames only files sitting directly inside a <YYYY-MM-DD>-<slug>/ entry folder, never attachments, and refuses any rename that would clobber an existing body.md (exit 1). Run validate.py --type communications first if you want the preview — the communication-legacy-body-name findings are exactly what it will rename.

The script scaffolds .context/communications/<received|sent|meetings>/<YYYY-MM-DD>-<slug>/body.md from the matching template, refuses to overwrite, and prints the created path on stdout. For async, fill from/to/subject; for meetings/calls, fill participants/subject. Write the body afterward in the native language.


Entry format

Read ${CLAUDE_PLUGIN_ROOT}/skills/conventions/references/communication-conventions.md before writing an entry — it is the full canon behind the shapes below: the front-matter schema per direction, async (received/sent) vs synchronous (meetings/), the draft→sent transition, the English-only exemption for bodies, and how to migrate a legacy drafts/ folder.

.context/communications/
  received/<YYYY-MM-DD>-<slug>/body.md   (+ attachments alongside)   async inbound
  sent/<YYYY-MM-DD>-<slug>/body.md                                   async outbound
  meetings/<YYYY-MM-DD>-<slug>/body.md   (+ transcript/slides)       synchronous (meeting + call)

Async (received/, sent/) front-matter — directional, from/to:

---
channel: email          # email | whatsapp | other
direction: received     # received | sent
from: "..."
to: "..."
subject: "..."
date: YYYY-MM-DD
status: sent            # draft | sent  (received records are 'sent'; outgoing start 'draft')
related: []             # D-03 cross-refs to other .context/ artifacts
created: YYYY-MM-DD
updated: YYYY-MM-DD
---

<body — in the NATIVE language of the communication>

Synchronous (meetings/) front-matter — non-directional, participants instead of from/to, always status: sent (it already happened):

---
channel: meeting        # meeting | call
participants:           # the people in the conversation
  - "Marta Ruiz <...> (Ejemplo SL)"
  - "..."
organizer: "..."        # optional
subject: "..."
date: YYYY-MM-DD
status: sent
related: []
created: YYYY-MM-DD
updated: YYYY-MM-DD
---

<agenda / notes / decisions / action items — in the NATIVE language>

After a meeting: action items become tracked work

Logging the meeting is half the job. A meeting record whose action items stay inside body.md is a note, not a commitment. Once the body is written, walk its action items and derive each one:

The action item is…Register it asCommand
Work this side has agreed to doa backlog entrybash ${CLAUDE_PLUGIN_ROOT}/skills/backlog/scripts/register-item.sh --origin communication --communication <folder> --title "<item>"
Something a stakeholder or client is asking fora request/aidex:request — capture the ask, then cross-ref the communication
A decision the meeting settledan ADR/aidex:decision

--origin communication stamps origin_ref: communication/<YYYY-MM-DD>-<slug> — the D-03 marker, the folder name, never a filesystem path. That is what makes the entry answer "where did this come from?" six months later.

Derive, do not transcribe. An action item is a line in someone's notes; a backlog entry needs a title that stands alone. "Ver lo del export" becomes "Add CSV export to the bookings list". Say what you registered when you are done, so nothing is created silently.

If the meeting produced no action items, say so and stop — an empty derivation is a valid outcome and inventing work to fill the step is worse than skipping it.


Drafting: read what was actually sent before opening the template

For the sent/ path, read the existing entries in .context/communications/sent/ of the same channel before you draft — the folder is a corpus of messages this project really sent, and it is the only record of how it sounds. Match structure (how it opens, how much context it restates, how it closes) and register (formal vs direct, how requests are phrased). Prefer the most recent few and any addressed to the same interlocutor.

The template is the fallback, not the starting point: use it when sent/ is empty or holds nothing of the same kind. Say which prior entries you leaned on.

Never translate to match a sample. D-04 keeps every body in the communication's own language; a Spanish thread stays Spanish even when the closest structural example is English. Borrow the shape, never the language.

The house style is already in the scaffolded body

new-communication.sh reads .context/profiles/communication.md and renders its six axes — voice, sign-off, tone, address, date format, paste font — into the body.md it creates, so the draft starts in this workspace's voice instead of being corrected into it. A workspace with no profile gets the documented defaults; that is the normal case, not an error. Read the block at the top of the scaffolded file before writing, and if a correction keeps recurring on an axis the profile does not carry, record it there rather than re-applying it. Full shape: conventions/references/communication-conventions.md § House style.

An outgoing email body must survive a paste into Outlook or Gmail

Neither client renders markdown, and the body is going to be pasted into one of them. Two constructs have already reached real recipients broken — a table as a literal | grid, a blockquote as literal > characters. So in a sent/ entry with channel: email:

Do not writeWrite instead
a markdown tablea bulleted list, or short Label — value lines
a markdown blockquote (> …)plain prose, or Ana escribió: followed by the text

Bold, links and bullets paste correctly, so they stay available. validate.py enforces this as communication-paste-unsafe — scoped to sent/ + channel: email only. A received/ body is a faithful capture of what arrived: a table there is correct, and >-quoted thread text is the normal inbound shape, so neither is flagged.

The HTML the owner pastes comes from the email-draft section below, which is the default for every outgoing email draft; body.md stays the record. A hand-written body.html alongside body.md is only for a body that path cannot express — attachments already live next to the body, so this needs no new file tier.

A body.html states font-family explicitly, at the scaffolded paste_font value. Omitting it is not neutral — copying from a browser puts computed styles on the clipboard, so an unstyled block pastes as the browser's default serif instead of inheriting Outlook's composing font. Do not emit an @font-face: Aptos lives inside Outlook.app, so a browser preview falls back to Calibri, and that gap is documented rather than worked around. Full contract: conventions/references/communication-conventions.md § Typography contract.


Every outgoing email draft: one spec, one command

Every sent/ draft with channel: email (an email, a reply, "in HTML", "to paste into Outlook" — asked for or not) is built this way; never stop at a markdown body.md shown in chat. Do not build an artifact page. Write ONE spec file per email (front matter subject, to, cc, language; then the body in markdown: paragraphs, bold/italic, links, headings, lists, pipe tables, one fenced block), then run (keep the spec inside the communication's own folder, sent/<YYYY-MM-DD>-<slug>/, beside body.md, since attachments and body.html live there per communication-conventions.md; a single newline in a paragraph is a line break, so sign-offs keep their lines):

python3 "${CLAUDE_SKILL_DIR}/scripts/email-draft.py" <spec.md> [--out <dir>]

It writes <spec>.html and <spec>.txt and prints both paths; open the HTML once. The page shows Asunto / Para / CC on top, each with its own Copiar button, and the body below with one Copiar correo button at its top-right corner. The page is a centered column (max-width) but the body is inline-styled HTML only (no classes, scripts, stylesheets, width of any kind), so the copied email takes the mail window's width and brings no page chrome. Tables are allowed here, unlike in a body.md paste. No .eml.


Draft → sent flow

An outgoing message is scaffolded under sent/ with status: draft. When it actually goes out, set status: sent and bump updated. A received communication is a record of what already arrived, so it lands with status: sent from the start. The draft→sent flow is exclusive to outgoing async messages: meetings and calls already happened, so they land with status: sent too.


Self-check

Validate the artifact you just wrote and fix any violation before closing:

python3 ${CLAUDE_PLUGIN_ROOT}/skills/conventions/scripts/validate.py --type communications

If the project carries a ratchet baseline (.context/.validate-baseline.json), a non-zero exit means you introduced a NEW violation — fix it before closing.

Related

  • request — for a stakeholder/product requirement to act on (the ask), not the raw message; log the message here, capture the requirement there.
  • conventions — parent convention for .context/communications/.

Download now (ZIP)

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

No reviews yet

People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.

  • It worked
  • Partly
  • It didn't
What did you use it for? e.g. Reviewing pull requests in a Rails app

Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.