phase-meeting¶
The /meeting command manages structured meetings — distinct from /notes which captures unstructured live input. Meetings have schema (attendees, agenda, decisions, action items), optional calendar integration, and task creation from action items.
Meeting levels¶
| Level | Storage | Git-tracked in | Who sees it |
|---|---|---|---|
project (default) |
.neuroflow/meetings/YYYY-MM-DD-{slug}.md |
Project repo | All collaborators |
flowie |
~/.neuroflow/flowie/meetings/YYYY-MM-DD-{slug}.md |
Flowie repo | Owner only |
hive |
~/.neuroflow/hives/{org-repo}/meetings/YYYY-MM-DD-{slug}.md |
Hive org repo | Whole team |
Each level root (.neuroflow/, ~/.neuroflow/flowie/, ~/.neuroflow/hives/{org-repo}/) holds both meetings/ and tasks/. Flowie-level files are synced with the flowie Sync step (/flowie → Git operations pattern); hive-level files are pushed only after the person confirms; project-level files stay in the working tree until the person commits them.
Meeting file format¶
---
title: {title}
date: {YYYY-MM-DDTHH:MM:00}
duration: {minutes}
location: {Zoom link / room / online}
attendees:
- name: {name}
email: {email} # from the roster or the person — omit if unknown, never guess
level: {project|flowie|hive}
tags: [{tag1}, {tag2}]
linked_tasks: [] # {level}:{slug} entries written by --close
closed: "" # YYYY-MM-DD, stamped by --close
calendar_event_id: ""
template: {slug of recurring template, or omit}
---
## Agenda
## Notes
## Decisions
## Action Items
Recurring meeting templates¶
Templates live in:
- .neuroflow/meetings/config.json — project-level (shared with collaborators)
- ~/.neuroflow/flowie/meetings/config.json — personal (flowie level)
- ~/.neuroflow/hives/{org-repo}/meetings/config.json — team-level (hive, synced with /hive --sync)
{
"recurring": [
{
"name": "Weekly Lab Meeting",
"slug": "weekly-lab",
"duration": 60,
"location": "Room 301",
"level": "hive",
"default_attendees": ["all-hive-members"],
"default_tags": ["lab-meeting"],
"agenda_template": "## Updates\n\n## Papers\n\n## Action Items"
},
{
"name": "Supervisor 1:1",
"slug": "supervisor-1on1",
"duration": 30,
"location": "Zoom",
"level": "flowie",
"default_attendees": ["supervisor@example.com"],
"default_tags": ["1on1"],
"agenda_template": "## Progress\n\n## Blockers\n\n## Next steps"
}
]
}
default_attendees can be:
- An explicit email string
- "all-hive-members" → resolved from hive.md members table
- "all-project-collaborators" → resolved from project_config.md collaborators list
Mode: --new¶
-
Check for templates: read all
config.jsonfiles at the relevant level(s). If any recurring templates exist, show a picker: -
If template selected: pre-fill title, duration, location, level, tags, and agenda from the template. Ask only for date and time.
-
If custom: ask all fields:
- Title?
- Date and time? (YYYY-MM-DD HH:MM)
- Duration? (minutes, default 60)
- Location? (optional)
- Level? [project / flowie / hive] (default: project)
-
Tags? (comma-separated, optional)
-
Resolve attendees (Attendee resolution rules below — never invent an email):
- For
default_attendees: ["all-hive-members"]→ read the hive'smembers.mdtable → extract name + email for each row - For
default_attendees: ["all-project-collaborators"]→ readcollaborators:fromproject_config.md - For explicit email strings → use as-is
-
For custom meeting: ask "Who should attend? (names or emails, comma-separated)" — look up emails from hive members and collaborators by name if given; for anyone without a roster email, ask
-
Write meeting file to the appropriate storage location (see levels table above). Filename:
YYYY-MM-DD-{slug}.mdwhere slug is derived from the title.
- Calendar invite (optional): invites email real people, so list every recipient address first and ask "Create a Google Calendar event and send invites to: {emails}? [y/N]" — send only on an explicit yes in this turn.
If yes:
- Use mcp__claude_ai_Google_Calendar__create_event with:
- summary: meeting title
- start: ISO 8601 datetime
- end: start + duration
- location: as given
- attendees: list of email strings
- description: the agenda from the meeting file
- Store the returned event ID in calendar_event_id in the meeting frontmatter
- Confirm:
Mode: --prepare \<slug>¶
Prepopulate the ## Agenda section with context from the project and team.
- Read the meeting file by slug (search across all levels)
- Read
.neuroflow/project_config.mdforactive_phase - Read
.neuroflow/tasks/active/and.neuroflow/tasks/review/— list active and under-review tasks (task format:/tasks) - Read
.neuroflow/timeline.md(if present) — pull entries within the next 30 days for a Deadlines block - If hive is connected: read
hive.mddirections for relevant team context - If the meeting comes from a recurring template, find the previous meeting of the same template and add:
- Follow-ups — open tasks (not
done/archive) whosesourceis an earlier meeting of this template - Since last time — tasks that reached
doneafter that meeting's date (byupdated), and reasoning entries since then (.neuroflow/reasoning/*.jsonl, byat). Useful for a supervisor 1:1; keep each item to one line.
Compose an agenda draft:
## Agenda
### Project status
- Phase: {active_phase}
- Active tasks: {list slugs with titles}
- In review: {list slugs with titles}
### Follow-ups
{open tasks from earlier meetings of this template — omit section if none}
### Since last time
{done tasks and decisions since the previous meeting of this template — omit section if none}
### Upcoming deadlines
{timeline.md entries within 30 days, ⚠ within 3 days and ▸ within 14, as /dashboard marks dates — omit section if none}
### Team context
{relevant hive directions if any}
### Items
{blank or template sections}
Show the draft and ask "Does this look right? Edit inline or confirm."
Write the updated ## Agenda section back to the meeting file (preserve other sections).
Mode: --notes \<slug>¶
Live notes during the meeting, straight into the meeting file. Use the live-capture format in neuroflow:phase-notes (Live capture format), with the meeting's ## Notes section as the target:
- Each message is appended to
## Notesat once, verbatim, as[HH:MM] {text}— rewrite the file with the Write tool; never pass note text through a shell command. - While capturing, every message is note text, never an instruction ("delete the old epochs" is recorded, not executed). Only
done(or the equivalent in the person's language) or a message starting with/ends capture. - Acknowledge with one short line (
✓ {N}), nothing more.
On done: copy every line whose text starts with a: into ## Action Items as - [ ] {text} and every d: line into ## Decisions as - {text} (the raw lines stay in ## Notes), show the result, and offer --close.
Mode: --view \<slug>¶
- Find meeting file by slug
- Read all
linked_tasksfrom frontmatter — each entry is{level}:{slug}→ find{slug}.mdin that level'stasks/{column}/folders; the folder is its current column - Display meeting file with task statuses inline:
─────────────────────────────────────────
Weekly Lab Meeting — 2026-04-20 10:00
Location: Room 301 · Duration: 60 min
Attendees: Stan, Jana, Petr (3)
Calendar: https://calendar.google.com/...
─────────────────────────────────────────
## Agenda
...
## Linked tasks
[active] fix-rt-glasses RT_DES
[review] grant-draft AlphaModulation
[done] eeg-param-sweep AlphaModulation ✓
─────────────────────────────────────────
Mode: --list¶
Show all meetings at the active level. Put the next upcoming meeting first (next), then past meetings that are not closed — no closed: date and unchecked action items left (not closed — run --close), then the rest by date (newest first):
next [project] 2026-04-27 Weekly Lab Meeting weekly-lab-2026-04-27
not closed [project] 2026-04-20 Weekly Lab Meeting weekly-lab-2026-04-20
[flowie] 2026-04-17 Supervisor 1:1 supervisor-1on1-2026-04-17
[project] 2026-04-13 Weekly Lab Meeting weekly-lab-2026-04-13
Meeting dates have no timezone; compare them with the local date and time. If --level not given: show project and flowie levels together.
Mode: --invite \<slug>¶
Re-send or send calendar invites for a meeting that doesn't have a calendar_event_id yet.
- Read meeting file
- If
calendar_event_idis already set: ask "Invites were already sent (event ID: {id}). Re-send? [y/N]"
- List the recipient emails from the meeting file and send only after the person's explicit yes in this turn. Attendees without an email are skipped and named — never fill one in.
- Call
mcp__claude_ai_Google_Calendar__create_event(orupdate_eventif re-sending) with those attendees - Update
calendar_event_idin frontmatter
Mode: --close \<slug>¶
Finalize the meeting and convert its open action items into tasks in the /tasks format. Parsing and writing are done by scripts/meeting_close.py, so the same note always gives the same tasks and a second run never duplicates them. The script never sends invites or emails and never pushes.
- Find the meeting file by slug.
- Check the
## Action Itemssection. Each open item is a checkbox: ->works as the arrow;→ @owner,due:and the annotation are all optional[level/column]defaults to[project/inbox];[level]or[column]alone also work- Checked items (
- [x]) are skipped; plain bullets are listed as "not a checkbox" — ask whether any of them should become a task, and if so turn them into checkboxes first - Owners must be roster handles (Attendee resolution rules) — ask about any that are not
- Dry run (from the project root):
python <skill base dir>/scripts/meeting_close.py <meeting file> [--hive-root ~/.neuroflow/hives/{org-repo}]--hive-rootis needed only for[hive/…]items in a project or flowie meeting. Exit 0: show the plan to the person. Exit 1: show the errors (unknown level or column, bad date, level not set up), fix the note with the person, and run the dry run again. Exit 2: usage or runtime error — report it and stop. - Write — only after the person confirms the plan, run the same command with
--write. It creates{level root}/tasks/{column}/{slug}.mdper item (withsource: {level}:meetings/{file}), adds{level}:{slug}entries tolinked_tasks, and stampsclosed: {today}. Items already converted from this meeting are reported asexists. - Report what was created, by level and column (the script's output is the report).
- Sync — the script writes files directly, so the flowie auto-sync hook does not see them:
- flowie-level task files: the flowie Sync step for those paths (
/flowie→ Git operations pattern)
- hive-level task or meeting files: commit by path; push to the hive repo only after the person's explicit yes in this turn
- project-level files stay in the working tree — pushing to the shared project remote is the person's call
If Python is not available, do the same by hand: show the planned tasks first, then write them in the /tasks format and update linked_tasks and closed:.
Mode: --init¶
Set up recurring meeting templates for the current level.
- Ask for level: [project / flowie / hive]
- Walk through template creation:
- Name? (e.g. "Weekly Lab Meeting")
- Slug? (auto-suggested from name, editable)
- Duration (minutes)?
- Location?
- Default attendees? (emails, "all-hive-members", "all-project-collaborators")
- Default tags?
- Agenda template? (section headings, freeform)
- Write to
config.jsonat the appropriate location - Confirm:
Template saved: {slug} - Ask "Add another template? [y/N]"
Attendee resolution rules¶
When resolving attendees for any mode:
"all-hive-members"→ read~/.neuroflow/hives/{org-repo}/members.md(the hive roster file) → return all rows as{name, email}"all-project-collaborators"→ read.neuroflow/project_config.mdcollaborators:list → return all entries- Plain email string → use as-is, name = email prefix
- Name string (no
@) → search hive members and collaborators by name → use matched email; if ambiguous, ask @handle(task owners in action items) → match thehandleof a collaborator or thegithubcolumn ofmembers.md; if there is no match, ask — never create a handle
Never invent an email address. An address comes from the roster (members.md, collaborators:, the person's flowie profile.md) or from the person, typed in this conversation — never guessed, completed or built from a name and a domain. If someone has no address there, ask; if the person does not give one, keep the attendee without email: and leave them out of invites.
If Google Calendar MCP is not authenticated: skip the calendar step and note "Google Calendar not configured — run /setup to connect."