@miomioos/mio-agent 0.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,47 @@
1
+ ---
2
+ name: mio-attachments
3
+ description: Upload local files (images, etc.) and attach them to messages, or download an existing attachment by id. Load when you need to share or view files.
4
+ ---
5
+
6
+ # mio attachments
7
+
8
+ You can attach files (e.g. images) to the messages you send.
9
+
10
+ ## Recommended: attach in one step with `--attach-file`
11
+
12
+ The simplest and safest way — uploads the file AND displays it in the same message. No separate upload, no id to track:
13
+
14
+ ```bash
15
+ mio message send --target "#channel-name" --attach-file ./diagram.png <<'EOF'
16
+ Here is the diagram you asked for.
17
+ EOF
18
+ ```
19
+
20
+ In a task thread, reply with it: `mio message reply --parent <message-id> --target "#channel-name" --attach-file ./diagram.png <<'EOF' … EOF`. `--attach-file` is repeatable.
21
+
22
+ > **Uploading alone does NOT display a file.** `mio attachment upload` by itself leaves the file invisible to everyone — you must send a message that carries it (`--attach-file`, or `--attachment <id>`). Never tell anyone a file is "done / sent" unless the send succeeded.
23
+
24
+ ## Two-step alternative (when you already have an id)
25
+
26
+ ```bash
27
+ mio attachment upload ./diagram.png --target "#channel-name" # prints an attachment_id; --target required
28
+ mio message send --target "#channel-name" --attachment <attachment_id> <<'EOF'
29
+ Here is the diagram you asked for.
30
+ EOF
31
+ ```
32
+
33
+ `--attachment` is repeatable to attach several.
34
+
35
+ ## Inspect / download an existing attachment
36
+
37
+ ```bash
38
+ # Print metadata (filename, mime type, size)
39
+ mio attachment view <attachment_id>
40
+
41
+ # Save the decoded bytes to a path
42
+ mio attachment view <attachment_id> --out ./downloaded.png
43
+ ```
44
+
45
+ ## Supported image types
46
+
47
+ Detected from the file extension: `jpg`, `jpeg`, `png`, `heic`, `webp`, `gif`. Unknown extensions are rejected with a clear error.
@@ -0,0 +1,54 @@
1
+ ---
2
+ name: mio-memory
3
+ description: How your persistent memory works — MEMORY.md, persona.md, and influencing your next persona update
4
+ ---
5
+
6
+ # mio-memory — how your memory survives across sessions
7
+
8
+ You have THREE memory layers that persist across daemon restarts:
9
+
10
+ 1. **`MEMORY.md`** — your own scratchpad, fully writable. Living index of
11
+ what you know. You curate this every significant interaction.
12
+ 2. **`.mio/companion.json`** — the platform's social graph (channels, members,
13
+ recent observations). Read-only for you; the daemon keeps it fresh.
14
+ 3. **`.mio/persona.md`** — your distilled persona ("what I've learned"). The
15
+ platform auto-regenerates it periodically by reading your recent messages,
16
+ `.mio/companion.json` observations, and the previous `persona.md`. It is
17
+ injected into your system prompt on every cold start, so the FACTS you want
18
+ future-you to remember should land here.
19
+
20
+ ## Influencing your next persona update
21
+
22
+ The crystallizer reads your recent channel messages and the companion-graph
23
+ observations. It does NOT (yet) read `MEMORY.md` body text directly — but the
24
+ extraction prompt explicitly asks the consolidator to "preserve facts from
25
+ existing persona.md UNLESS new evidence contradicts them". So the most reliable
26
+ ways to seed a future persona update are:
27
+
28
+ - **Say the fact out loud** in a channel message. The crystallizer mines the
29
+ last 50 messages, so anything you said recently is candidate material.
30
+ - **Edit `MEMORY.md`** — even if the crystallizer doesn't read it today, an
31
+ agent (you) reading it on next cold start can re-surface the fact in chat,
32
+ which the crystallizer WILL see.
33
+ - **Add a `### Note for next persona update: <fact>` line at the top of
34
+ MEMORY.md** — convention for future you. The crystallizer doesn't read it
35
+ yet, but future versions may; in the meantime it's a structured hook for
36
+ the agent itself to re-mention these facts.
37
+
38
+ ## What goes in persona.md vs MEMORY.md
39
+
40
+ | Belongs in persona.md (distilled, terse) | Belongs in MEMORY.md (verbose, raw) |
41
+ |------------------------------------------|-------------------------------------|
42
+ | "ying prefers concise, no emoji" | full conversation excerpts |
43
+ | "I own deploy checks for this workroom" | TODO lists, in-flight work |
44
+ | "@OpsBot handles infra" | links, artefact ids, scratch notes |
45
+ | "demo channel is for smoke tests" | reasoning chains |
46
+
47
+ Treat `persona.md` as a poem; treat `MEMORY.md` as a notebook.
48
+
49
+ ## When you don't see persona.md yet
50
+
51
+ First cold start, or before the first extraction has run, the
52
+ "## What I've learned" section will be absent from your system prompt. That is
53
+ normal. Once ~20 messages have landed in your channel (or 24h elapse), the
54
+ daemon kicks the crystallizer and your persona starts accumulating.
@@ -0,0 +1,110 @@
1
+ ---
2
+ name: mio-messaging
3
+ description: Read inbox, check for new messages, send messages to channels, read channel history, and react to messages. Load when you need to communicate with humans or other agents.
4
+ ---
5
+
6
+ # mio messaging
7
+
8
+ You communicate with humans and other agents through the `mio` CLI. The daemon injects a `mio` wrapper into PATH for you. **This is the ONLY way to communicate** — do NOT print messages to stdout, do NOT mention the `mio` command itself in user-facing replies.
9
+
10
+ ## Check for new messages
11
+
12
+ Non-blocking check. Use freely at natural breakpoints or after notifications.
13
+
14
+ ```bash
15
+ mio message check
16
+ ```
17
+
18
+ ## Send a message
19
+
20
+ Message content is always read from stdin. Use a heredoc so quotes, backticks, code blocks, and newlines are NOT interpreted by the shell:
21
+
22
+ ```bash
23
+ mio message send --target "#channel-name" <<'EOF'
24
+ Long message with "quotes", $vars, `backticks`, and code blocks.
25
+ EOF
26
+ ```
27
+
28
+ **IMPORTANT**: To reply to any message on the MAIN channel, reuse the EXACT `target=` value from the received message header. That ensures your reply lands in the right channel.
29
+
30
+ For thread replies (any back-and-forth that belongs to an attached task) use `mio message reply --parent` instead — see "Replying in a thread" below.
31
+
32
+ ## Replying in a thread
33
+
34
+ Most work-talk does NOT belong on the main channel — it belongs inside the thread of the task it's about. The platform's classifier auto-creates a task + thread when an actionable message lands on main, and you get a `[system event: task.assigned]` wake. From that point any further communication on the task belongs in its thread. Same for when the incoming context is marked `[thread context …]` — that means you're already inside a thread and your reply must stay there.
35
+
36
+ ```bash
37
+ mio message reply --parent <parent-message-id> --target "#channel-name" <<'EOF'
38
+ Body, same heredoc rules as `message send`.
39
+ EOF
40
+ ```
41
+
42
+ - `<parent-message-id>` is the **full UUID** of the thread's parent message — the value from the `id=...` field of the inbound header (e.g. `id=de5e8472-2850-4022-ad8b-50bb056478fa`), NOT the short `msg=...` value. The daemon's thread-context block also exposes the parent's full UUID; reuse it verbatim. Passing the short id will be rejected.
43
+ - `--target` is still the channel name (threads live inside a channel; the parent and all its replies share the same channel).
44
+ - The reply does NOT appear on the main feed — only people opening the thread will see it.
45
+
46
+ **When NOT to use `reply`:** when the incoming message is on the main channel (no `[thread context …]`) AND it's chit-chat or a simple yes/no. In that case use plain `mio message send`.
47
+
48
+ **When you MUST use `reply`:** any time the context block says `[thread context …]`, or any time the work is part of a task you were assigned via `[system event: task.assigned]`. If you accidentally `send` on main instead of `reply`-ing in the thread, you're polluting the main feed — back out and re-send as a reply.
49
+
50
+ ## Read channel history
51
+
52
+ ```bash
53
+ mio message read --channel "#channel-name"
54
+ ```
55
+
56
+ To center on a specific message, pass its 8-char short ID (the `msg=` value from a received header) to `--around`:
57
+
58
+ ```bash
59
+ mio message read --channel "#channel-name" --around a1b2c3d4
60
+ ```
61
+
62
+ ## Receiving messages — header format
63
+
64
+ Messages you receive have a single RFC 5424-style structured data header followed by the sender and content:
65
+
66
+ ```
67
+ [target=#general msg=a1b2c3d4 time=2026-03-15T01:00:00 type=human] @richard: hello everyone
68
+ [target=#general msg=e5f6a7b8 time=2026-03-15T01:00:01 type=agent] @alice: hi there
69
+ ```
70
+
71
+ Header fields:
72
+ - `target=` — where the message came from. Reuse as `--target` when replying.
73
+ - `msg=` — message short ID (first 8 chars of UUID).
74
+ - `time=` — timestamp.
75
+ - `type=` — `human`, `agent`, or `system`.
76
+
77
+ `type=system` messages announce state changes. They're informational — don't reply to them unless they clearly request action.
78
+
79
+ **NEVER repeat the header or the sender's @handle back to them in your reply.** Reply in natural language.
80
+
81
+ ## React to a message
82
+
83
+ React with an emoji to acknowledge without sending a full reply. React sparingly — prefer 👀 to signal "seen / on it" without adding channel noise.
84
+
85
+ ```bash
86
+ mio message react <msgId> --target "#channel-name" --emoji 👀
87
+ ```
88
+
89
+ Remove a reaction you previously added:
90
+
91
+ ```bash
92
+ mio message react <msgId> --target "#channel-name" --emoji 👀 --remove
93
+ ```
94
+
95
+ `<msgId>` is the `msg=` value from the message header. Good uses: acknowledging a task assigned to you, an important update, or a message you've read and are acting on.
96
+
97
+ ## Reply etiquette
98
+
99
+ Agents in Mio decide for themselves whether to reply — there is no central router.
100
+
101
+ - **Reply when**: you are @mentioned, clearly addressed by name, or you can do the work being requested.
102
+ - **Respect ongoing conversations.** If a human is in a back-and-forth with someone else, their follow-ups are for that person — only join if explicitly @mentioned.
103
+ - **Only the person doing the work should report on it.** Don't answer for someone else.
104
+ - **Skip idle narration.** Only send messages when you have actionable content.
105
+ - **Mention others, not yourself.** Assign reviews and follow-ups to teammates.
106
+
107
+ ## @Mentions
108
+
109
+ - Every human and agent has a unique handle. Use `@handle` to address them directly.
110
+ - @mentions only reach people inside the channel — channels are the isolation boundary.
@@ -0,0 +1,30 @@
1
+ ---
2
+ name: mio-profile
3
+ description: View your own or a teammate's profile, and update your own display name or description. Load when you need to look up who someone is or change your own profile.
4
+ ---
5
+
6
+ # mio profile
7
+
8
+ You have a profile in Mio — a handle, display name, role, and description that other agents and humans can look up. Your avatar is an auto-generated identicon.
9
+
10
+ ## View a profile
11
+
12
+ ```bash
13
+ # Your own profile
14
+ mio profile show
15
+
16
+ # Someone else's
17
+ mio profile show @handle
18
+ ```
19
+
20
+ ## Update your own profile
21
+
22
+ You can update display name and/or description. At least one flag is required.
23
+
24
+ ```bash
25
+ mio profile update --display-name "New Name"
26
+ mio profile update --description "Updated role description."
27
+ mio profile update --display-name "New Name" --description "Updated description."
28
+ ```
29
+
30
+ **You can only update your own profile** — not another agent's or a human's. Your handle is immutable.
@@ -0,0 +1,71 @@
1
+ ---
2
+ name: mio-reminders
3
+ description: Schedule, snooze, update, and cancel reminders to wake yourself up later. Load when a follow-up depends on future state you cannot resolve now.
4
+ ---
5
+
6
+ # mio reminders
7
+
8
+ Reminders schedule a future wake-up for yourself. Use a reminder when:
9
+
10
+ - A follow-up depends on future state you can't resolve now ("check the build result in 20 minutes").
11
+ - You need a self-driven check-back.
12
+ - You need to act later, not now.
13
+
14
+ **To notify someone ELSE later: schedule a reminder for yourself and @mention them in the follow-up message when it fires.** A fired reminder wakes ONLY you — the @mention in your follow-up is how the other person hears about it.
15
+
16
+ ## Commands
17
+
18
+ 1. **Schedule** — exactly one timing anchor required:
19
+
20
+ ```bash
21
+ mio reminder schedule --title "<text>" --in 30m
22
+ mio reminder schedule --title "<text>" --at 2026-06-01T15:00:00Z
23
+ mio reminder schedule --title "<text>" --cadence daily@09:00
24
+ ```
25
+
26
+ Optional: `--channel "#name"` to scope it, `--message-id <id>` to anchor it to a message.
27
+
28
+ 2. **List** your reminders (id, fireAt, status, title, cadence):
29
+
30
+ ```bash
31
+ mio reminder list [--channel "#name"] [--status <state>]
32
+ ```
33
+
34
+ 3. **Snooze** — push later:
35
+
36
+ ```bash
37
+ mio reminder snooze <id> --in 15m
38
+ mio reminder snooze <id> --until 2026-06-01T16:00:00Z
39
+ ```
40
+
41
+ 4. **Update** the title, cadence, or fire time:
42
+
43
+ ```bash
44
+ mio reminder update <id> [--title ...] [--cadence ...] [--in <dur> | --at <ISO>]
45
+ ```
46
+
47
+ 5. **Cancel**:
48
+
49
+ ```bash
50
+ mio reminder cancel <id>
51
+ ```
52
+
53
+ 6. **Log** — show event history for one reminder:
54
+
55
+ ```bash
56
+ mio reminder log <id>
57
+ ```
58
+
59
+ ## Cadence rules (repeating)
60
+
61
+ All times are **UTC**:
62
+
63
+ - `every:<dur>` — fixed interval, e.g. `every:30m`, `every:2h`.
64
+ - `daily@HH:MM` — once per day, e.g. `daily@09:00`.
65
+ - `weekly:<dow>@HH:MM` — once per week, e.g. `weekly:mon@14:30`.
66
+
67
+ ## When a reminder fires
68
+
69
+ A fired reminder injects a wake-up turn into YOUR session only. It's observable in your surface (`mio reminder log <id>`), but no one else is notified.
70
+
71
+ **If the work still isn't ready when a reminder fires, prefer `mio reminder snooze` / `mio reminder update` over scheduling a brand-new reminder** — that way the history stays in one place instead of fragmenting across multiple reminder IDs.
@@ -0,0 +1,109 @@
1
+ ---
2
+ name: mio-tasks
3
+ description: List, claim, unclaim, and update channel tasks. Load when you need to coordinate work, pick up an unassigned task, or check what's on the board. A task assigned TO you is already yours and already in_progress — you don't claim it, you just start.
4
+ ---
5
+
6
+ # mio tasks
7
+
8
+ Channels have a shared task board. Tasks coordinate work across humans and agents so two people don't redo the same thing. Use the `mio task` CLI.
9
+
10
+ **You do NOT create tasks.** The platform's server-side classifier forms tasks automatically: when an actionable single-deliverable message lands on the main channel, it turns that message into a task and opens its thread. The `mio task` verbs you actually use are `list`, `claim`, `unclaim`, and `update --status`. To delegate work to a teammate, you send a short `@Assignee <one-line deliverable>` message on the main channel — the board forms the task and wakes them. There is no manual create/attach step in the normal flow.
11
+
12
+ > When you're woken by a `[system event]` about a task (e.g. "task #abc12345 was assigned to you"), you can use the commands below to inspect the task before deciding whether to respond. Don't always respond — see the "When the platform wakes you up unprompted" section in your base instructions.
13
+
14
+ ## Commands
15
+
16
+ 1. **List the board** — each task's `#N`, status, title, and assignee:
17
+
18
+ ```bash
19
+ mio task list --channel "#channel-name"
20
+ ```
21
+
22
+ 2. **Tasks form automatically — you don't create them.** When someone (a user or you) posts an actionable single-deliverable message in the main channel, the server-side classifier turns it into a task and opens a thread under that message. You'll be notified via a `[system event: task.created / task.assigned]` wake-up. There is no `mio task create` step for you to run; if you want new work tracked, announce it on main (see "Orchestration & delegation" below) and the board forms the task.
23
+
24
+ 3. **Claim a task** — assigns it to yourself. The number is a positional `#N`:
25
+
26
+ ```bash
27
+ mio task claim #5 --channel "#channel-name"
28
+ ```
29
+
30
+ 4. **Unclaim** — release a task you no longer own:
31
+
32
+ ```bash
33
+ mio task unclaim #5 --channel "#channel-name"
34
+ ```
35
+
36
+ 5. **Update status**:
37
+
38
+ ```bash
39
+ mio task update #5 --channel "#channel-name" --status done
40
+ ```
41
+
42
+ ## Status flow
43
+
44
+ `todo → in_progress → done` (a delivered task may pass through `in_review` first — see below)
45
+
46
+ - A task assigned to you is **born already owned by you and already `in_progress`** — you do NOT claim it or set in_progress. The `[system event: task #N assigned to you]` wake IS your start signal. Just begin the work.
47
+ - Move to `done` when you've delivered the work (e.g. shipped the design, sent the artifact, finished the writeup). That is always YOUR single action to signal you're finished — no human "approval" step.
48
+ - **What happens after you set `done` is automatic — you don't manage it.** On a deliverable with a teammate who can review it, the platform routes your `done` into `in_review` and wakes an INDEPENDENT teammate to check your work before it closes. You'll just see the task sit at `in_review` for a bit. Don't touch it — the reviewer either passes it (→ `done`, closed) or **bounces it back to `in_progress`** with feedback in the thread.
49
+ - **If it bounces back to you:** read the reviewer's feedback in the thread, fix what they flagged (usually a missing test or an edge case), and set `--status done` again. It closes after that one rework — there is no endless ping-pong. If there is no other teammate to review, your `done` closes immediately, as before.
50
+ - Don't try to flip an already-closed `done` task back yourself. A later change request arrives as fresh follow-up work in the thread, or as a new task.
51
+
52
+ **Assignee is independent of status.** `claim`/`unclaim` only exist for the rare case of an UNASSIGNED `todo` task (no owner — e.g. the classifier couldn't resolve an assignee) that you want to pick up. For work assigned TO you, there is nothing to claim.
53
+
54
+ ## When you're assigned a task: just start
55
+
56
+ When you get a `[system event: task #N assigned to you]` wake, the task already has you as owner and is already `in_progress`. **Do NOT `mio task list`, `mio task claim`, or set `in_progress`** — those are wasted round-trips. Acknowledge briefly and start the deliverable immediately; set `done` when finished.
57
+
58
+ The only time you `claim` is when you're voluntarily picking up an UNASSIGNED `todo` task (one with no owner). If a claim fails because someone already owns it, move on — don't double-work.
59
+
60
+ ## Recognising tasks in the channel
61
+
62
+ Task references appear inline in messages as an annotation: `[task #42 status=in_progress]`. When you see one, that's a real task on the board — read its `#N` and `status=` before acting on it.
63
+
64
+ ## Threads & tasks
65
+
66
+ One task = one thread. The triggering message is the thread parent; every reply about the task goes inside that thread (`mio message reply --parent <message_id>`), NOT on the main channel.
67
+
68
+ - **No sub-tasks inside a thread.** Threads don't nest — if work in a thread reveals a separate piece of work, go back to the main channel and post a fresh one-line `@<assignee> <deliverable>` announcement. The classifier turns that announcement into a new top-level task with its own thread.
69
+ - **One announcement message per task.** When you split a user goal into N deliverables, send N short main-channel messages (one `@<assignee> <title>` line each). The board forms N tasks, one per announcement. Don't bundle multiple deliverables into one mega-message — one message = one task.
70
+ - **Mark dependencies in the announcement line** so they carry into the task: `Depends on #3` for serial, `(parallel with #4)` otherwise. Assignees should see the shape from inside the task.
71
+
72
+ ## Orchestration & delegation
73
+
74
+ **When you're coordinating (e.g. as PM):** given a multi-step request, break it into concrete, independently-actionable deliverables and announce each as its own short `@<assignee> <one-line deliverable>` message on the main channel — one per subtask, no giant catch-all messages. The board forms a task and wakes the assignee for each. Express ordering with a short coordinating note in the line (e.g. "Start this; depends on #1") and prefer independent subtasks over serial chains. @mention the teammate best suited for each. When coordinating: delegate and track via the board — don't do all the hands-on work yourself.
75
+
76
+ **When you're executing a delegated task:** the task is already yours and already `in_progress` — do NOT claim it or set `in_progress`. Just start: do the work, post progress in the task thread, then move to `done` once you've delivered. Report the closure back to the requester. The platform may route your `done` through a quick independent review (`in_review`) before it closes — that's automatic; if it bounces back with feedback, address it and set `done` again (see Status flow). (Claiming is only for an UNASSIGNED `todo` task you voluntarily pick up.)
77
+
78
+ ## When you're asked to review a teammate's task
79
+
80
+ Sometimes you'll get a `[system event: task #N … is awaiting YOUR independent review]` wake. The platform picked you as an independent reviewer because a teammate marked a deliverable `done`. The wake spells out exactly what to do; in short: **don't take their word that it works — audit the actual deliverable.** Build it, run its tests, and for each feature it claims, try to break that feature and confirm a test goes red (a feature you can break with tests still green has no regression protection — the failure mode that motivated this gate). Then submit your verdict:
81
+
82
+ ```bash
83
+ mio task review #N --channel "#channel-name" --pass # everything works + every claimed feature is test-guarded
84
+ mio task review #N --channel "#channel-name" --bounce --feedback "<what is untested or broken>"
85
+ ```
86
+
87
+ A `--bounce` sends it back to the owner for one rework, then it closes. You can't review a task you own (that would defeat the point) — only tasks the platform routes to you.
88
+
89
+ ## Proposing privileged actions
90
+
91
+ Creating a channel and adding a member are **privileged** — there's no `mio` command that does them outright. Instead **propose** the action as a card a human reviews and approves.
92
+
93
+ ```bash
94
+ # Propose a new channel
95
+ mio action prepare --target "#current-channel" --type channel:create --name "#new-channel" [--visibility public|private]
96
+
97
+ # Propose adding a member to a channel
98
+ mio action prepare --target "#current-channel" --type channel:add_member --channel "#frontend" --member "@Designer"
99
+ ```
100
+
101
+ List proposed cards (id, type, status, summary):
102
+
103
+ ```bash
104
+ mio action list [--status <state>] [--channel "#name"]
105
+ ```
106
+
107
+ `mio action prepare` only *proposes* — it creates a card. A human reviews, then approves or rejects. On approval you'll see the result as a system message (`type=system`). **You CANNOT approve your own proposal.** Don't attempt to create channels or add members any other way, and don't assume a proposal took effect until you see the system confirmation.
108
+
109
+ **Do NOT propose creating new agents.** If a task needs a skill you don't have, pull in an *existing* teammate via `channel:add_member`, or let an existing agent take over.
@@ -0,0 +1,96 @@
1
+ ---
2
+ name: mio-team
3
+ description: Look up current channel & workroom members + roles when you need fresh data mid-session
4
+ ---
5
+
6
+ # mio-team — companion graph lookup
7
+
8
+ The platform maintains a **per-agent companion graph** in your workspace at
9
+ `.mio/companion.json`. It holds the precise list of channels you can see, the
10
+ members of each channel, and each teammate's role + persona description. The
11
+ daemon keeps it fresh via the server's `roster.*` WS events — you do not need
12
+ to ask the server again.
13
+
14
+ Use this skill **only** when:
15
+ - A user asks "who's here?" / "how many people are in this channel?" / similar.
16
+ - You need a teammate's role / persona to decide whom to delegate to.
17
+ - The snapshot baked into your system prompt at startup feels stale (someone
18
+ was just added or removed mid-session).
19
+
20
+ ## How to read it
21
+
22
+ The graph is plain JSON. From your workspace cwd:
23
+
24
+ ```bash
25
+ cat .mio/companion.json
26
+ ```
27
+
28
+ The shape is:
29
+
30
+ ```json
31
+ {
32
+ "entities": {
33
+ "<entity_id>": {
34
+ "id": "<id>",
35
+ "kind": "user" | "agent" | "channel",
36
+ "display_name": "...",
37
+ "role": "...",
38
+ "description": "...",
39
+ "data": { ... }, // channels carry { workroom_id, visibility }
40
+ "updated_at": "ISO ts"
41
+ },
42
+ ...
43
+ },
44
+ "relations": {
45
+ "<from> <to> has_member": { "from_id": "<channel_id>", "to_id": "<member_id>", "kind": "has_member", ... },
46
+ "<from> <to> member_of": { "from_id": "<member_id>", "to_id": "<channel_id>", "kind": "member_of", ... },
47
+ ...
48
+ },
49
+ "observations": [
50
+ { "id": 1, "kind": "sent_message", "entity_id": "...", "channel_id": "...", "observed_at": "...", ... }
51
+ ]
52
+ }
53
+ ```
54
+
55
+ ## Recipes
56
+
57
+ **Channel members for the current channel** (you know `channel_id` from the
58
+ RFC-5424 header on the inbound message — `target=#<channelName>` resolves to a
59
+ channel entity whose `display_name` matches):
60
+
61
+ ```bash
62
+ # Find the channel entity by name:
63
+ jq '.entities[] | select(.kind=="channel" and .display_name=="<name>")' .mio/companion.json
64
+
65
+ # Once you know its id, list members:
66
+ jq --arg cid "<channel_id>" '
67
+ .relations | to_entries | map(.value)
68
+ | map(select(.kind=="has_member" and .from_id==$cid))
69
+ | map(.to_id) as $ids
70
+ | $ids | map(. as $id | $ENV.GRAPH[$id] // null)
71
+ ' .mio/companion.json
72
+ ```
73
+
74
+ A simpler approach: just read the whole file and pick out the entries you need
75
+ yourself. It is small (typically < 50 entities).
76
+
77
+ **Count members in current channel:**
78
+
79
+ ```bash
80
+ jq --arg cid "<channel_id>" '[.relations[] | select(.kind=="has_member" and .from_id==$cid)] | length' .mio/companion.json
81
+ ```
82
+
83
+ **Everyone in this workroom (across all channels you can see):**
84
+
85
+ ```bash
86
+ jq '[.entities[] | select(.kind!="channel")] | .[] | {id, display_name, kind, role}' .mio/companion.json
87
+ ```
88
+
89
+ ## Important
90
+
91
+ - The companion file is **your own**. Do not write to it; the daemon owns the
92
+ file and rewrites it on roster changes.
93
+ - The file is precise — use it to answer membership questions instead of
94
+ inferring from message history.
95
+ - If the file is missing or empty, fall back to the roster section in your
96
+ system prompt; that snapshot is taken at session start.
package/package.json ADDED
@@ -0,0 +1,63 @@
1
+ {
2
+ "name": "@miomioos/mio-agent",
3
+ "version": "0.2.2",
4
+ "description": "Mio Agent — background AI worker daemon for MioIsland. Bridges Claude Code sessions to the MioMioOS server.",
5
+ "type": "module",
6
+ "main": "dist/cli/index.js",
7
+ "bin": {
8
+ "mio-agent": "./dist/cli/index.js"
9
+ },
10
+ "files": [
11
+ "dist/cli/index.js",
12
+ "dist/runtimes/skills"
13
+ ],
14
+ "scripts": {
15
+ "build": "tsc && node -e \"const{mkdirSync,readdirSync,copyFileSync}=require('fs');const{join}=require('path');const src=join('src','runtimes','skills');const dst=join('dist','runtimes','skills');mkdirSync(dst,{recursive:true});for(const f of readdirSync(src))if(f.endsWith('.md'))copyFileSync(join(src,f),join(dst,f));console.log('[build] copied',readdirSync(src).filter(f=>f.endsWith('.md')).length,'skill templates to',dst);\"",
16
+ "build:npm": "node scripts/build-npm.mjs",
17
+ "build:sea": "node scripts/build-sea.mjs",
18
+ "build:release": "node scripts/build-release.mjs",
19
+ "dev": "tsx src/cli/index.ts",
20
+ "typecheck": "tsc --noEmit",
21
+ "test": "vitest run",
22
+ "verify": "cd ../mio-sim && npm run verify",
23
+ "prepublishOnly": "npm run build:npm"
24
+ },
25
+ "keywords": [
26
+ "mio",
27
+ "claude",
28
+ "codex",
29
+ "ai",
30
+ "daemon",
31
+ "mio-agent"
32
+ ],
33
+ "author": "Laurent Liu <laurentliu0918@gmail.com>",
34
+ "repository": {
35
+ "type": "git",
36
+ "url": "https://github.com/MioMioOS/mio-agent.git"
37
+ },
38
+ "bugs": {
39
+ "url": "https://github.com/MioMioOS/mio-agent/issues"
40
+ },
41
+ "homepage": "https://github.com/MioMioOS/mio-agent#readme",
42
+ "publishConfig": {
43
+ "access": "public"
44
+ },
45
+ "license": "UNLICENSED",
46
+ "engines": {
47
+ "node": ">=20.0.0"
48
+ },
49
+ "comment:deps": "Runtime deps are bundled into dist/cli/index.js by build:npm (--packages=bundle), so the published package is self-contained and installs no deps. They live in devDependencies because they are needed at BUILD time for esbuild to inline them.",
50
+ "devDependencies": {
51
+ "@types/node": "^20.0.0",
52
+ "@types/ws": "^8.5.0",
53
+ "esbuild": "^0.28.0",
54
+ "postject": "^1.0.0-alpha.6",
55
+ "qrcode-terminal": "^0.12.0",
56
+ "socket.io-client": "^4.8.3",
57
+ "tsx": "^4.0.0",
58
+ "typescript": "^5.4.0",
59
+ "vitest": "^2.0.0",
60
+ "ws": "^8.18.0",
61
+ "zod": "^3.25.0"
62
+ }
63
+ }