@xiaotianxt/skills 0.1.0

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.
Files changed (120) hide show
  1. package/EXCLUDED.md +42 -0
  2. package/LICENSE +21 -0
  3. package/README.md +165 -0
  4. package/SECURITY.md +23 -0
  5. package/SOURCES.md +45 -0
  6. package/bin/skills.mjs +241 -0
  7. package/package.json +38 -0
  8. package/skills/1password/SKILL.md +94 -0
  9. package/skills/1password/agents/openai.yaml +4 -0
  10. package/skills/1password/references/item-management.md +80 -0
  11. package/skills/1password/references/op-cli.md +107 -0
  12. package/skills/apple-calendar-event/SKILL.md +81 -0
  13. package/skills/apple-calendar-event/agents/openai.yaml +4 -0
  14. package/skills/apple-calendar-event/scripts/calendar_audit.py +201 -0
  15. package/skills/apple-calendar-event/scripts/calendar_event.py +164 -0
  16. package/skills/bro-browser/SKILL.md +118 -0
  17. package/skills/bro-browser/agents/openai.yaml +4 -0
  18. package/skills/bro-browser/references/tool-map.md +102 -0
  19. package/skills/bro-browser/references/workflows.md +146 -0
  20. package/skills/bro-browser/scripts/bro-call.mjs +189 -0
  21. package/skills/calendar/SKILL.md +182 -0
  22. package/skills/calendar/agents/openai.yaml +4 -0
  23. package/skills/calendar/references/operations.md +255 -0
  24. package/skills/calendar/scripts/calendar_list_review.py +157 -0
  25. package/skills/calendar/scripts/event_dedupe_preview.py +155 -0
  26. package/skills/canvas/SKILL.md +70 -0
  27. package/skills/canvas/agents/openai.yaml +4 -0
  28. package/skills/canvas/references/canvas-api.md +76 -0
  29. package/skills/course-exam-review-planner/SKILL.md +127 -0
  30. package/skills/cx/SKILL.md +25 -0
  31. package/skills/gh-fix-ci/LICENSE.txt +201 -0
  32. package/skills/gh-fix-ci/SKILL.md +81 -0
  33. package/skills/gh-fix-ci/agents/openai.yaml +6 -0
  34. package/skills/gh-fix-ci/assets/github-small.svg +3 -0
  35. package/skills/gh-fix-ci/assets/github.png +0 -0
  36. package/skills/gh-fix-ci/scripts/inspect_pr_checks.py +509 -0
  37. package/skills/gh-review-workflow/SKILL.md +61 -0
  38. package/skills/gh-review-workflow/agents/openai.yaml +4 -0
  39. package/skills/gh-review-workflow/references/workflow.md +48 -0
  40. package/skills/gh-review-workflow/scripts/fetch_review_state.py +222 -0
  41. package/skills/gh-review-workflow/scripts/resolve_review_threads.py +83 -0
  42. package/skills/github/SKILL.md +74 -0
  43. package/skills/github/agents/openai.yaml +6 -0
  44. package/skills/github/assets/github-small.svg +3 -0
  45. package/skills/github/assets/github.png +0 -0
  46. package/skills/gws-calendar/SKILL.md +126 -0
  47. package/skills/gws-calendar-agenda/SKILL.md +52 -0
  48. package/skills/gws-calendar-insert/SKILL.md +66 -0
  49. package/skills/gws-docs/SKILL.md +48 -0
  50. package/skills/gws-docs-write/SKILL.md +49 -0
  51. package/skills/gws-drive/SKILL.md +137 -0
  52. package/skills/gws-drive-upload/SKILL.md +52 -0
  53. package/skills/gws-gmail/SKILL.md +62 -0
  54. package/skills/gws-gmail-forward/SKILL.md +55 -0
  55. package/skills/gws-gmail-reply/SKILL.md +58 -0
  56. package/skills/gws-gmail-reply-all/SKILL.md +62 -0
  57. package/skills/gws-gmail-send/SKILL.md +57 -0
  58. package/skills/gws-gmail-triage/SKILL.md +50 -0
  59. package/skills/gws-gmail-watch/SKILL.md +58 -0
  60. package/skills/gws-shared/SKILL.md +27 -0
  61. package/skills/helium-browser-mcp/SKILL.md +137 -0
  62. package/skills/helium-browser-mcp/agents/openai.yaml +4 -0
  63. package/skills/helium-browser-mcp/scripts/obmcp.mjs +92 -0
  64. package/skills/helium-browser-mcp/scripts/openbrowsermcp-stdio-proxy.mjs +170 -0
  65. package/skills/learn/SKILL.md +122 -0
  66. package/skills/learn/agents/openai.yaml +7 -0
  67. package/skills/learn/assets/AGENTS.template.md +33 -0
  68. package/skills/learn/assets/errorlog.template.typ +61 -0
  69. package/skills/learn/assets/reading-sequence.template.md +23 -0
  70. package/skills/learn/assets/source-index.template.md +17 -0
  71. package/skills/learn/assets/tasklog.template.typ +57 -0
  72. package/skills/learn/assets/workbook.template.typ +60 -0
  73. package/skills/learn/references/learning-science.md +103 -0
  74. package/skills/learn/scripts/init_learning_workspace.py +70 -0
  75. package/skills/macos-messages/SKILL.md +258 -0
  76. package/skills/memory/SKILL.md +33 -0
  77. package/skills/memory/codex.md +186 -0
  78. package/skills/memory/opencode.md +164 -0
  79. package/skills/mimestreamctl/SKILL.md +170 -0
  80. package/skills/mimestreamctl/agents/openai.yaml +4 -0
  81. package/skills/mimestreamctl/scripts/mimestreamctl +33 -0
  82. package/skills/mon/SKILL.md +51 -0
  83. package/skills/mon/scripts/mon_spend_review.py +458 -0
  84. package/skills/ocr/SKILL.md +136 -0
  85. package/skills/ocr/agents/openai.yaml +4 -0
  86. package/skills/ocr/references/local-ocr-best-practices.md +297 -0
  87. package/skills/ocr/references/mineru-api.md +159 -0
  88. package/skills/ocr/scripts/ocr-router +22 -0
  89. package/skills/ocr/scripts/ocr_router.py +741 -0
  90. package/skills/panopto-mp4-bulk-download/SKILL.md +57 -0
  91. package/skills/panopto-mp4-bulk-download/agents/openai.yaml +4 -0
  92. package/skills/panopto-mp4-bulk-download/references/url-patterns.md +26 -0
  93. package/skills/panopto-mp4-bulk-download/scripts/panopto_bulk_mp4.sh +213 -0
  94. package/skills/rust-systems-style/SKILL.md +109 -0
  95. package/skills/rust-systems-style/agents/openai.yaml +4 -0
  96. package/skills/rust-systems-style/references/rust-review-checklist.md +77 -0
  97. package/skills/rust-systems-style/references/style-sources.md +68 -0
  98. package/skills/ship-ai-native-cli/SKILL.md +76 -0
  99. package/skills/ship-ai-native-cli/agents/openai.yaml +4 -0
  100. package/skills/ship-ai-native-cli/references/case-notes.md +83 -0
  101. package/skills/ship-ai-native-cli/references/product-method.md +82 -0
  102. package/skills/ship-ai-native-cli/references/release-checklist.md +147 -0
  103. package/skills/ship-ai-native-cli/references/rust-cli-shape.md +111 -0
  104. package/skills/telegram-mtproto-session/SKILL.md +125 -0
  105. package/skills/telegram-mtproto-session/agents/openai.yaml +4 -0
  106. package/skills/telegram-mtproto-session/scripts/telegram_session.py +687 -0
  107. package/skills/tg/SKILL.md +173 -0
  108. package/skills/things3-manager/SKILL.md +116 -0
  109. package/skills/things3-manager/scripts/things +42 -0
  110. package/skills/things3-manager/scripts/things_cli.py +514 -0
  111. package/skills/web-artifacts-builder/LICENSE.txt +202 -0
  112. package/skills/web-artifacts-builder/SKILL.md +74 -0
  113. package/skills/web-artifacts-builder/scripts/bundle-artifact.sh +54 -0
  114. package/skills/web-artifacts-builder/scripts/init-artifact.sh +379 -0
  115. package/skills/web-artifacts-builder/scripts/shadcn-components.tar.gz +0 -0
  116. package/skills/yeet/LICENSE.txt +201 -0
  117. package/skills/yeet/SKILL.md +71 -0
  118. package/skills/yeet/agents/openai.yaml +6 -0
  119. package/skills/yeet/assets/yeet-small.svg +3 -0
  120. package/skills/yeet/assets/yeet.png +0 -0
@@ -0,0 +1,186 @@
1
+ # Codex — Memory queries
2
+
3
+ Codex stores sessions as individual JSONL files organized by date, plus a session
4
+ index and a prompt history file.
5
+
6
+ ## File layout
7
+
8
+ ```
9
+ ~/.codex/
10
+ ├── session_index.jsonl # maps session ID → title + date
11
+ ├── history.jsonl # prompt log: {session_id, ts, text}
12
+ └── sessions/
13
+ └── YYYY/
14
+ └── MM/
15
+ └── DD/
16
+ └── rollout-YYYY-MM-DDTHH-mm-ss-UUID.jsonl
17
+ ```
18
+
19
+ ## Session index format
20
+
21
+ Each line in `session_index.jsonl`:
22
+
23
+ ```json
24
+ {"id": "019cdb9f-e66d-...", "thread_name": "Implement MAGIC...", "updated_at": "2026-03-11T06:40:24.9048Z"}
25
+ ```
26
+
27
+ ## Session file format
28
+
29
+ Each line in a session JSONL file is one event, discriminated by `type`:
30
+
31
+ | `type` | Contains |
32
+ |---|---|
33
+ | `session_meta` | `payload.id`, `payload.cwd`, `payload.cli_version`, `payload.model_provider` |
34
+ | `event_msg` | `payload.type` (`task_started`, etc.), `payload.turn_id` |
35
+ | `turn_context` | `payload.turn_id`, `payload.cwd`, `payload.model` |
36
+ | `response_item` → `message` / `user` | User input: `payload.content[].text` |
37
+ | `response_item` → `message` / `assistant` | Assistant output: `payload.content[].text` + `payload.phase` (`"commentary"` or `"final"`) |
38
+ | `response_item` → `message` / `developer` | System/developer instructions |
39
+ | `response_item` → `reasoning` | Thinking blocks: `payload.encrypted_content` (encrypted) or `payload.content` |
40
+ | `response_item` → `function_call` | Tool call: `payload.name`, `payload.arguments`, `payload.call_id` |
41
+ | `response_item` → `function_call_output` | Tool result: `payload.call_id`, `payload.output` |
42
+ | `response_item` → `custom_tool_call` | Custom tool invocation |
43
+ | `response_item` → `custom_tool_call_output` | Custom tool result |
44
+ | `response_item` → `web_search_call` | Web search usage |
45
+
46
+ ## Query recipes
47
+
48
+ ### List all sessions (sorted by updated)
49
+
50
+ ```bash
51
+ python3 -c "
52
+ import json
53
+ sessions = []
54
+ with open('$HOME/.codex/session_index.jsonl') as f:
55
+ for line in f:
56
+ s = json.loads(line)
57
+ sessions.append((s.get('updated_at',''), s['id'], s.get('thread_name','')))
58
+ for ts, sid, name in sorted(sessions, reverse=True)[:30]:
59
+ print(f'{sid} {ts[:10]} {name[:80]}')
60
+ "
61
+ ```
62
+
63
+ ### Find a session file by ID
64
+
65
+ ```bash
66
+ # Session IDs are UUIDs in the filename after the time portion
67
+ find ~/.codex/sessions -name "*SESSION_ID_SHORT*.jsonl" 2>/dev/null
68
+ ```
69
+
70
+ Or by date from the index:
71
+
72
+ ```bash
73
+ # First get the date from index
74
+ python3 -c "
75
+ import json
76
+ with open('$HOME/.codex/session_index.jsonl') as f:
77
+ for line in f:
78
+ s = json.loads(line)
79
+ if s['id'] == 'YOUR_SESSION_ID':
80
+ print(s['updated_at'][:10]) # YYYY-MM-DD
81
+ break
82
+ "
83
+ ```
84
+
85
+ ### Search sessions by keyword (fast, uses `rg`)
86
+
87
+ ```bash
88
+ # Search across all session files
89
+ rg -l "keyword" ~/.codex/sessions/
90
+
91
+ # Search and show matching lines with context
92
+ rg -C 2 "keyword" ~/.codex/sessions/2026/03/11/
93
+
94
+ # Restrict to user messages only
95
+ rg '"type":"input_text"' ~/.codex/sessions/ -l | xargs rg "keyword"
96
+ ```
97
+
98
+ ### Search prompts only
99
+
100
+ ```bash
101
+ rg "keyword" ~/.codex/history.jsonl
102
+ ```
103
+
104
+ ### Read human-readable conversation for a session
105
+
106
+ ```bash
107
+ python3 -c "
108
+ import json, sys
109
+ with open('PATH_TO_SESSION_FILE') as f:
110
+ for line in f:
111
+ obj = json.loads(line)
112
+ t = obj['type']
113
+ if t == 'response_item':
114
+ p = obj.get('payload', {})
115
+ if p.get('type') == 'message':
116
+ role = p.get('role', '?')
117
+ phase = p.get('phase', '')
118
+ for c in p.get('content', []):
119
+ ct = c.get('type', '')
120
+ text = c.get('text', '')
121
+ if text:
122
+ label = f'{role}'
123
+ if phase == 'commentary':
124
+ label += ' (commentary)'
125
+ elif phase == 'final':
126
+ label += ' (final)'
127
+ print(f'[{label}] {text[:500]}')
128
+ print('---')
129
+ elif p.get('type') == 'function_call':
130
+ print(f'[tool] {p[\"name\"]}: {p.get(\"arguments\",\"\")[:200]}')
131
+ elif p.get('type') == 'function_call_output':
132
+ output = p.get('output', '')
133
+ # output contains chunk headers, skip for readability
134
+ print(f'[tool_result] call_id={p[\"call_id\"]}')
135
+ "
136
+ ```
137
+
138
+ ### Extract user prompts only
139
+
140
+ ```bash
141
+ python3 -c "
142
+ import json
143
+ with open('PATH_TO_SESSION_FILE') as f:
144
+ for line in f:
145
+ obj = json.loads(line)
146
+ if obj.get('type') == 'response_item':
147
+ p = obj.get('payload', {})
148
+ if p.get('type') == 'message' and p.get('role') == 'user':
149
+ for c in p.get('content', []):
150
+ text = c.get('text', '')
151
+ if text:
152
+ print(text[:500])
153
+ print('---')
154
+ "
155
+ ```
156
+
157
+ ### Read session metadata
158
+
159
+ ```bash
160
+ python3 -c "
161
+ import json
162
+ with open('PATH_TO_SESSION_FILE') as f:
163
+ for line in f:
164
+ obj = json.loads(line)
165
+ if obj.get('type') == 'session_meta':
166
+ p = obj['payload']
167
+ print(f'Session: {p[\"id\"]}')
168
+ print(f'CWD: {p.get(\"cwd\",\"?\")}')
169
+ print(f'Version: {p.get(\"cli_version\",\"?\")}')
170
+ print(f'Model: {p.get(\"model_provider\",\"?\")}')
171
+ break
172
+ "
173
+ ```
174
+
175
+ ## Notes
176
+
177
+ - **Reasoning is encrypted**: The `reasoning` events usually contain
178
+ `encrypted_content` (base64-encoded), not plaintext. You cannot read
179
+ reasoning content from the JSONL files directly.
180
+ - **File path convention**: Session filenames include the UUID after a
181
+ timestamp, e.g. `rollout-2026-03-11T02-40-15-019cdb9f-e66d-7601-8cfe-303c6bbab575.jsonl`.
182
+ The session ID is `019cdb9f-e66d-7601-8cfe-303c6bbab575`.
183
+ - **`history.jsonl`**: Contains only user prompts (truncated to first ~3KB),
184
+ keyed by `session_id`. Good for fast prompt-only search.
185
+ - **Function call output**: Contains chunk headers and metadata. For clean
186
+ output, search for the actual stdout content within the output string.
@@ -0,0 +1,164 @@
1
+ # OpenCode — Memory queries
2
+
3
+ OpenCode stores sessions in a SQLite database with WAL mode. All paths below are
4
+ relative to `~/.local/share/opencode/`.
5
+
6
+ ## Database
7
+
8
+ ```
9
+ ~/.local/share/opencode/opencode.db
10
+ ```
11
+
12
+ Safe to query while opencode is running. Companion files (`-wal`, `-shm`) are
13
+ WAL support files — do not delete them.
14
+
15
+ ## Schema
16
+
17
+ | Table | Key columns | Purpose |
18
+ |---|---|---|
19
+ | `session` | `id`, `title`, `directory`, `time_created`, `time_updated` | Session metadata |
20
+ | `message` | `id`, `session_id`, `data` (JSON) | Messages per session |
21
+ | `part` | `id`, `message_id`, `session_id`, `data` (JSON) | Message content parts |
22
+
23
+ The actual text content lives in the `part` table, joined to `message` via
24
+ `message_id`. The `data` column in both tables is JSON.
25
+
26
+ ### `message.data` (minimal)
27
+
28
+ | Field | Notes |
29
+ |---|---|
30
+ | `role` | `"user"` or `"assistant"` |
31
+ | `agent` | agent name string |
32
+ | `model.providerID`, `model.modelID` | model info |
33
+ | `summary.title`, `summary.diffs` | user message only |
34
+ | `parentID`, `cost`, `tokens`, `finish` | assistant message only |
35
+
36
+ ### `part.data` (discriminated by `type`)
37
+
38
+ | `type` | Content field(s) |
39
+ |---|---|
40
+ | `text` | `.text` — visible message text |
41
+ | `reasoning` | `.text` — thinking/reasoning content |
42
+ | `tool` | `.tool`, `.callID`, `.state.status`, `.state.input`, `.state.output` |
43
+ | `step-start` | `.snapshot` |
44
+ | `step-finish` | `.reason`, `.cost`, `.tokens` |
45
+
46
+ Query with `json_extract(m.data, '$.field')` and
47
+ `json_extract(p.data, '$.type')` / `json_extract(p.data, '$.field')`.
48
+
49
+ ## Query recipes
50
+
51
+ ### List sessions (CLI, preferred)
52
+
53
+ ```bash
54
+ opencode session list
55
+ opencode session list -n 20
56
+ opencode session list --format json
57
+ ```
58
+
59
+ ### List sessions (SQL)
60
+
61
+ ```bash
62
+ sqlite3 ~/.local/share/opencode/opencode.db \
63
+ "SELECT id, title, directory,
64
+ datetime(time_updated/1000, 'unixepoch', 'localtime') as updated
65
+ FROM session ORDER BY time_updated DESC LIMIT 20;"
66
+ ```
67
+
68
+ ### Search sessions by keyword in any message
69
+
70
+ ```bash
71
+ sqlite3 ~/.local/share/opencode/opencode.db "
72
+ SELECT DISTINCT s.id, s.title, s.directory,
73
+ datetime(s.time_updated/1000, 'unixepoch', 'localtime') as updated
74
+ FROM message m
75
+ JOIN session s ON m.session_id = s.id
76
+ WHERE lower(m.data) LIKE '%keyword%'
77
+ ORDER BY s.time_updated DESC
78
+ LIMIT 20;"
79
+ ```
80
+
81
+ ### Search sessions by title or directory
82
+
83
+ ```bash
84
+ sqlite3 ~/.local/share/opencode/opencode.db \
85
+ "SELECT id, title, directory,
86
+ datetime(time_updated/1000, 'unixepoch', 'localtime') as updated
87
+ FROM session
88
+ WHERE lower(title) LIKE '%keyword%'
89
+ ORDER BY time_updated DESC
90
+ LIMIT 10;"
91
+ ```
92
+
93
+ ### Read text messages for a session
94
+
95
+ ```bash
96
+ sqlite3 ~/.local/share/opencode/opencode.db "
97
+ SELECT json_extract(m.data, '$.role') as role,
98
+ json_extract(p.data, '$.text') as text
99
+ FROM message m
100
+ JOIN part p ON p.message_id = m.id
101
+ WHERE m.session_id='SESSION_ID'
102
+ AND json_extract(p.data, '$.type') = 'text'
103
+ ORDER BY p.time_created;"
104
+ ```
105
+
106
+ ### Read tool calls
107
+
108
+ ```bash
109
+ sqlite3 ~/.local/share/opencode/opencode.db "
110
+ SELECT json_extract(p.data, '$.tool') as tool,
111
+ json_extract(p.data, '$.state.status') as status,
112
+ substr(json_extract(p.data, '$.state.output'), 1, 300) as output
113
+ FROM message m
114
+ JOIN part p ON p.message_id = m.id
115
+ WHERE m.session_id='SESSION_ID'
116
+ AND json_extract(p.data, '$.type') = 'tool'
117
+ ORDER BY p.time_created;"
118
+ ```
119
+
120
+ ### Read reasoning
121
+
122
+ ```bash
123
+ sqlite3 ~/.local/share/opencode/opencode.db "
124
+ SELECT substr(json_extract(p.data, '$.text'), 1, 500) as reasoning
125
+ FROM message m
126
+ JOIN part p ON p.message_id = m.id
127
+ WHERE m.session_id='SESSION_ID'
128
+ AND json_extract(p.data, '$.type') = 'reasoning'
129
+ ORDER BY p.time_created;"
130
+ ```
131
+
132
+ ### Find sessions in a working directory
133
+
134
+ ```bash
135
+ sqlite3 ~/.local/share/opencode/opencode.db \
136
+ "SELECT id, title, datetime(time_updated/1000, 'unixepoch', 'localtime') as updated
137
+ FROM session
138
+ WHERE directory LIKE '%/path/here%'
139
+ ORDER BY time_updated DESC
140
+ LIMIT 10;"
141
+ ```
142
+
143
+ ### Count
144
+
145
+ ```bash
146
+ sqlite3 ~/.local/share/opencode/opencode.db "SELECT COUNT(*) FROM session;"
147
+ sqlite3 ~/.local/share/opencode/opencode.db "SELECT COUNT(*) FROM message;"
148
+ ```
149
+
150
+ ## Export
151
+
152
+ ```bash
153
+ opencode export SESSION_ID
154
+ ```
155
+
156
+ ## Prompt history (supplementary)
157
+
158
+ ```
159
+ ~/.local/state/opencode/prompt-history.jsonl
160
+ ```
161
+
162
+ ```bash
163
+ tail -20 ~/.local/state/opencode/prompt-history.jsonl
164
+ ```
@@ -0,0 +1,170 @@
1
+ ---
2
+ name: mimestreamctl
3
+ description: "Use when Codex needs to work with Mimestream mail on this Mac: investigate local mail, search receipts or support threads, identify actual recipients from sent mail, read selected messages, draft or reply in Mimestream, visually verify compose windows, or perform explicit mailbox actions. Prefer Gmail API skills for server-authoritative send/delivery/label/thread state that does not depend on Mimestream."
4
+ ---
5
+
6
+ # Mimestream Control
7
+
8
+ This skill exists to keep agents from guessing in email workflows. Use it as a mail forensics and drafting interface, not as a generic UI-clicking script.
9
+
10
+ ## First Principles
11
+
12
+ Email tasks have four different truth sources. Pick the right one before running commands:
13
+
14
+ 1. **Local cache truth**: Mimestream's SQLite cache is best for searching, timelines, receipts, old sent mail, headers, and evidence.
15
+ 2. **Visible UI truth**: the front Mimestream window is best only for "the message/draft currently on screen."
16
+ 3. **Server truth**: Gmail/API state is best for whether a message is actually sent, delivered, trashed, labeled, or threaded.
17
+ 4. **Human intent**: sending, trashing, spam, unsubscribe, and bulk actions require explicit user intent.
18
+
19
+ Default route: local cache for facts, UI for visible draft verification, Gmail API for server-authoritative state.
20
+
21
+ ## Entry Point
22
+
23
+ ```bash
24
+ ~/.codex/skills/mimestreamctl/scripts/mimestreamctl --help
25
+ ```
26
+
27
+ If the wrapper behaves oddly, retry:
28
+
29
+ ```bash
30
+ ~/dev/mimestreamctl/mimestreamctl --help
31
+ ```
32
+
33
+ UI commands require Mimestream running in the logged-in macOS desktop session with Accessibility and Automation permissions. Run UI commands serially.
34
+
35
+ ## Decision Tree
36
+
37
+ **Need facts from mail?** Use `mail search`, `mail get`, `mail headers`, `mail thread`, or `mail sent-search`. Do not start from the front UI.
38
+
39
+ **Need to know who to send to?** Search past sent mail and headers. Do not infer from a visible received message.
40
+
41
+ **Need to reply in an existing thread?** Verify the selected message, then use `reply` or `reply-all`. Do not create a new compose unless the user wants a new thread.
42
+
43
+ **Need a new draft?** Write the body to a file, open a visible draft, then verify To/Cc/From/Subject/body. Do not send unless explicitly asked.
44
+
45
+ **Need to move/delete/send?** Verify the exact target first. Destructive and send commands need `--confirm`.
46
+
47
+ ## Golden Paths
48
+
49
+ ### Evidence Or Timeline
50
+
51
+ ```bash
52
+ ~/.codex/skills/mimestreamctl/scripts/mimestreamctl mail accounts
53
+ ~/.codex/skills/mimestreamctl/scripts/mimestreamctl mail search --query hertz --since 2026-01-01 --limit 100 --include-transactional --show-addresses
54
+ ~/.codex/skills/mimestreamctl/scripts/mimestreamctl mail get --id 12345 --include-html --show-addresses
55
+ ~/.codex/skills/mimestreamctl/scripts/mimestreamctl mail headers --id 12345
56
+ ~/.codex/skills/mimestreamctl/scripts/mimestreamctl mail thread --id 12345
57
+ ```
58
+
59
+ For billing, travel, legal-ish, school, or support disputes:
60
+
61
+ 1. Search broad by brand/domain.
62
+ 2. Search exact identifiers.
63
+ 3. Separate reservation/order records, receipts, user-sent complaints, bounces, and human replies.
64
+ 4. Use `mail thread --id` on promising sent messages or support replies to connect "what I sent" to "what they replied."
65
+ 5. Extract dates, amounts, ids, account, sender, recipient, and thread/case ids.
66
+ 6. Build the answer from source message ids.
67
+ 7. State missing or ambiguous evidence.
68
+
69
+ Use `--include-transactional` for receipts, confirmations, support, billing, security, and travel records.
70
+
71
+ ### Recipient Discovery
72
+
73
+ ```bash
74
+ ~/.codex/skills/mimestreamctl/scripts/mimestreamctl mail sent-search --query hertz --since 2025-11-01 --limit 20
75
+ ~/.codex/skills/mimestreamctl/scripts/mimestreamctl mail sent-search --to hertz.com --since 2025-11-01 --limit 50
76
+ ~/.codex/skills/mimestreamctl/scripts/mimestreamctl mail headers --id 12345
77
+ ~/.codex/skills/mimestreamctl/scripts/mimestreamctl mail thread --id 12345
78
+ ```
79
+
80
+ Classify addresses before drafting:
81
+
82
+ - **Intake address**: new outbound complaints that later produce case replies.
83
+ - **Case-reply address**: works for existing case threads.
84
+ - **No-reply/bounce address**: avoid for new disputes.
85
+ - **Specialized address**: marketing, loyalty, receipts, verification, etc.
86
+
87
+ When uncertain, propose `To`/`Cc` with rationale instead of silently choosing.
88
+
89
+ ### Current Selected Message
90
+
91
+ ```bash
92
+ ~/.codex/skills/mimestreamctl/scripts/mimestreamctl selection --json --first
93
+ ~/.codex/skills/mimestreamctl/scripts/mimestreamctl read --full --max-chars 4000
94
+ ~/.codex/skills/mimestreamctl/scripts/mimestreamctl links --resolve-redirects
95
+ ```
96
+
97
+ If subject/body/window do not match, stop and re-verify the Mimestream selection. UI state can drift.
98
+
99
+ ### New Draft
100
+
101
+ ```bash
102
+ ~/.codex/skills/mimestreamctl/scripts/mimestreamctl compose \
103
+ --to person@example.com \
104
+ --cc team@example.com \
105
+ --subject "Subject" \
106
+ --body-file /tmp/body.txt
107
+ ```
108
+
109
+ If `compose` fails with application-name resolution but Mimestream is installed:
110
+
111
+ ```bash
112
+ open -b com.mimestream.Mimestream "mailto:..."
113
+ ```
114
+
115
+ Before saying the draft is ready, verify:
116
+
117
+ - To/Cc/Bcc are intended.
118
+ - From account is intended.
119
+ - Subject is correct for new case vs existing thread.
120
+ - Body starts and ends correctly.
121
+ - No placeholders or private tokens remain.
122
+ - The message is still a draft.
123
+
124
+ Use AX text when available; otherwise use a screenshot or visible window inspection. A zero exit code only means the open request returned.
125
+
126
+ ### Reply Draft
127
+
128
+ ```bash
129
+ ~/.codex/skills/mimestreamctl/scripts/mimestreamctl read --no-body --json
130
+ ~/.codex/skills/mimestreamctl/scripts/mimestreamctl reply --body-file /tmp/reply.txt
131
+ ~/.codex/skills/mimestreamctl/scripts/mimestreamctl reply-all --body-file /tmp/reply.txt
132
+ ```
133
+
134
+ Use `reply-all` only when thread continuity and participant preservation matter.
135
+
136
+ ### Explicit Actions
137
+
138
+ ```bash
139
+ ~/.codex/skills/mimestreamctl/scripts/mimestreamctl archive
140
+ ~/.codex/skills/mimestreamctl/scripts/mimestreamctl trash --confirm
141
+ ~/.codex/skills/mimestreamctl/scripts/mimestreamctl send --confirm
142
+ ```
143
+
144
+ For bulk unsubscribe or trash, dry-run first, save exact ids, inspect summaries, then confirm only after user approval.
145
+
146
+ ## Command Semantics
147
+
148
+ - `mail search`: search cache by account/from/to/subject/query/date. Add `--show-addresses` when recipient or threading context matters.
149
+ - `mail sent-search`: search sent mail and always include To/Cc/Bcc and threading headers.
150
+ - `mail get --id`: read one cached message. It does not filter out transactional mail.
151
+ - `mail headers --id`: read addressing, state, message-id, reply-to, in-reply-to, and references for one message.
152
+ - `mail thread --id`: list messages in the same local Mimestream thread, with addresses and state.
153
+ - `selection`, `read`, `links`, `list`: inspect visible Mimestream UI state.
154
+ - `compose`, `reply`, `reply-all`, `insert-text`: create or edit visible drafts.
155
+ - `archive`, `move`, `trash`, `spam`, `send`: mutate mail or draft state.
156
+
157
+ ## Failure Handling
158
+
159
+ - If a message appears in `mail search` but body extraction is poor, use `mail get --include-html` and convert HTML to visible text.
160
+ - If local cache evidence conflicts with server state, use Gmail API skills for the authoritative answer.
161
+ - If UI automation fails, bring Mimestream forward and retry once; then fall back to bundle-id `open` or visible screenshot verification.
162
+ - If recipient choice depends on previous successful workflows, use `sent-search` and support replies, not memory.
163
+ - Never edit Mimestream SQLite directly.
164
+
165
+ ## Safety
166
+
167
+ - Never send, trash, spam, bulk unsubscribe, or bulk delete without explicit intent and confirmation.
168
+ - Never rely on the front window for bulk work.
169
+ - Never expose full tracking links, unsubscribe tokens, private message links, or secrets.
170
+ - Keep summaries evidence-based: cite message ids in working notes and report only the relevant facts to the user.
@@ -0,0 +1,4 @@
1
+ interface:
2
+ display_name: "Mimestream Control"
3
+ short_description: "Search, inspect, draft, and verify Mimestream mail on macOS."
4
+ default_prompt: "Use $mimestreamctl to investigate local Mimestream mail, reconstruct threads, draft replies, and verify visible compose windows safely."
@@ -0,0 +1,33 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+
4
+ SOURCE="${BASH_SOURCE[0]}"
5
+ while [[ -h "$SOURCE" ]]; do
6
+ DIR="$(cd -P "$(dirname "$SOURCE")" && pwd)"
7
+ TARGET="$(readlink "$SOURCE")"
8
+ if [[ "$TARGET" != /* ]]; then
9
+ SOURCE="$DIR/$TARGET"
10
+ else
11
+ SOURCE="$TARGET"
12
+ fi
13
+ done
14
+
15
+ SCRIPT_DIR="$(cd -P "$(dirname "$SOURCE")" && pwd)"
16
+ REPO_BIN="$(cd "$SCRIPT_DIR/../../.." && pwd)/mimestreamctl"
17
+ HOME_BIN="$HOME/dev/mimestreamctl/mimestreamctl"
18
+
19
+ if [[ -n "${MIMESTREAMCTL_BIN:-}" && -x "${MIMESTREAMCTL_BIN}" ]]; then
20
+ exec "${MIMESTREAMCTL_BIN}" "$@"
21
+ fi
22
+
23
+ if [[ -x "$REPO_BIN" ]]; then
24
+ exec "$REPO_BIN" "$@"
25
+ fi
26
+
27
+ if [[ -x "$HOME_BIN" ]]; then
28
+ exec "$HOME_BIN" "$@"
29
+ fi
30
+
31
+ echo "Error: could not find a runnable mimestreamctl binary." >&2
32
+ echo "Checked MIMESTREAMCTL_BIN, repo-local mimestreamctl, and ~/dev/mimestreamctl/mimestreamctl." >&2
33
+ exit 1
@@ -0,0 +1,51 @@
1
+ ---
2
+ name: mon
3
+ description: Use when Codex needs to access Monarch Money through the local mon CLI for auth status, accounts, transactions, custom GraphQL queries, or diagnostics while keeping local tokens private.
4
+ ---
5
+
6
+ # mon
7
+
8
+ Use this skill when you need to access Monarch Money from the local `mon` CLI.
9
+
10
+ ## Commands
11
+
12
+ - `mon auth login`: login and save a local token.
13
+ - `mon auth status --online`: verify saved auth.
14
+ - `mon auth status --browser --json`: verify the logged-in Helium/Monarch browser session through OpenBrowserMCP.
15
+ - `mon accounts --json`: fetch linked accounts.
16
+ - `mon accounts --browser --json`: fetch accounts through an already logged-in Monarch browser tab.
17
+ - `mon transactions --search TEXT --start-date YYYY-MM-DD --end-date YYYY-MM-DD --json`: search transactions.
18
+ - `mon transactions --browser --start-date YYYY-MM-DD --end-date YYYY-MM-DD --json`: search transactions through the browser session.
19
+ - `mon gql --operation NAME --query-file FILE --variables '{}'`: run a custom GraphQL document.
20
+ - `mon gql --browser --operation NAME --query-file FILE --variables '{}'`: run GraphQL inside the Monarch web app tab.
21
+ - `mon doctor`: inspect local paths and auth state.
22
+ - `scripts/mon_spend_review.py --input transactions.json --format markdown`: locally review exported transactions for likely shared-expense reimbursements, merchant credits, and adjusted consumption spend.
23
+
24
+ ## Auth Strategy
25
+
26
+ - Use the saved token path for durable unattended CLI work: `mon auth status --online`, then `mon ... --json`.
27
+ - If the saved token is expired or password login risks CAPTCHA/rate limits, prefer `--browser` when Helium is already logged in to `https://app.monarch.com/`.
28
+ - Browser mode reads the local OpenBrowserMCP bearer token from `~/openbrowsermcp/settings.json`, connects to `http://127.0.0.1:3500/mcp`, finds a Monarch tab, and runs GraphQL from inside that page with browser cookies/CSRF.
29
+ - Do not try to print, scrape, or import a Monarch browser token into `~/.mon/session.json`; recent Monarch browser state may not expose a reusable API token.
30
+ - Use `--browser-tab-id TAB_ID` when multiple Monarch tabs are open.
31
+
32
+ ## Binary Selection
33
+
34
+ The Homebrew `mon` may lag local source changes. If `mon transactions --help`
35
+ does not show `--browser`, use `/Users/yupeit/dev/mon/target/release/mon` for
36
+ browser-mode work, or release/upgrade the Homebrew formula before relying on the
37
+ bare `mon` command.
38
+
39
+ ## Safety
40
+
41
+ Do not print `~/.mon/session.json` or Monarch tokens. Prefer JSON command output
42
+ for agent workflows. Avoid repeated password login attempts; prefer the saved
43
+ session and `mon auth status --online`. When using `--browser`, do not print the
44
+ OpenBrowserMCP bearer token, browser cookies, localStorage values, or raw
45
+ transaction details unless the user explicitly asks for them; aggregate first
46
+ for spending summaries.
47
+
48
+ For spending review, fetch transaction JSON to a local temporary file and run
49
+ `scripts/mon_spend_review.py` against it. Treat matched reimbursement events as
50
+ candidates until the user confirms the event semantics; do not automatically
51
+ edit Monarch categories or notes from heuristic matches.