@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.
- package/EXCLUDED.md +42 -0
- package/LICENSE +21 -0
- package/README.md +165 -0
- package/SECURITY.md +23 -0
- package/SOURCES.md +45 -0
- package/bin/skills.mjs +241 -0
- package/package.json +38 -0
- package/skills/1password/SKILL.md +94 -0
- package/skills/1password/agents/openai.yaml +4 -0
- package/skills/1password/references/item-management.md +80 -0
- package/skills/1password/references/op-cli.md +107 -0
- package/skills/apple-calendar-event/SKILL.md +81 -0
- package/skills/apple-calendar-event/agents/openai.yaml +4 -0
- package/skills/apple-calendar-event/scripts/calendar_audit.py +201 -0
- package/skills/apple-calendar-event/scripts/calendar_event.py +164 -0
- package/skills/bro-browser/SKILL.md +118 -0
- package/skills/bro-browser/agents/openai.yaml +4 -0
- package/skills/bro-browser/references/tool-map.md +102 -0
- package/skills/bro-browser/references/workflows.md +146 -0
- package/skills/bro-browser/scripts/bro-call.mjs +189 -0
- package/skills/calendar/SKILL.md +182 -0
- package/skills/calendar/agents/openai.yaml +4 -0
- package/skills/calendar/references/operations.md +255 -0
- package/skills/calendar/scripts/calendar_list_review.py +157 -0
- package/skills/calendar/scripts/event_dedupe_preview.py +155 -0
- package/skills/canvas/SKILL.md +70 -0
- package/skills/canvas/agents/openai.yaml +4 -0
- package/skills/canvas/references/canvas-api.md +76 -0
- package/skills/course-exam-review-planner/SKILL.md +127 -0
- package/skills/cx/SKILL.md +25 -0
- package/skills/gh-fix-ci/LICENSE.txt +201 -0
- package/skills/gh-fix-ci/SKILL.md +81 -0
- package/skills/gh-fix-ci/agents/openai.yaml +6 -0
- package/skills/gh-fix-ci/assets/github-small.svg +3 -0
- package/skills/gh-fix-ci/assets/github.png +0 -0
- package/skills/gh-fix-ci/scripts/inspect_pr_checks.py +509 -0
- package/skills/gh-review-workflow/SKILL.md +61 -0
- package/skills/gh-review-workflow/agents/openai.yaml +4 -0
- package/skills/gh-review-workflow/references/workflow.md +48 -0
- package/skills/gh-review-workflow/scripts/fetch_review_state.py +222 -0
- package/skills/gh-review-workflow/scripts/resolve_review_threads.py +83 -0
- package/skills/github/SKILL.md +74 -0
- package/skills/github/agents/openai.yaml +6 -0
- package/skills/github/assets/github-small.svg +3 -0
- package/skills/github/assets/github.png +0 -0
- package/skills/gws-calendar/SKILL.md +126 -0
- package/skills/gws-calendar-agenda/SKILL.md +52 -0
- package/skills/gws-calendar-insert/SKILL.md +66 -0
- package/skills/gws-docs/SKILL.md +48 -0
- package/skills/gws-docs-write/SKILL.md +49 -0
- package/skills/gws-drive/SKILL.md +137 -0
- package/skills/gws-drive-upload/SKILL.md +52 -0
- package/skills/gws-gmail/SKILL.md +62 -0
- package/skills/gws-gmail-forward/SKILL.md +55 -0
- package/skills/gws-gmail-reply/SKILL.md +58 -0
- package/skills/gws-gmail-reply-all/SKILL.md +62 -0
- package/skills/gws-gmail-send/SKILL.md +57 -0
- package/skills/gws-gmail-triage/SKILL.md +50 -0
- package/skills/gws-gmail-watch/SKILL.md +58 -0
- package/skills/gws-shared/SKILL.md +27 -0
- package/skills/helium-browser-mcp/SKILL.md +137 -0
- package/skills/helium-browser-mcp/agents/openai.yaml +4 -0
- package/skills/helium-browser-mcp/scripts/obmcp.mjs +92 -0
- package/skills/helium-browser-mcp/scripts/openbrowsermcp-stdio-proxy.mjs +170 -0
- package/skills/learn/SKILL.md +122 -0
- package/skills/learn/agents/openai.yaml +7 -0
- package/skills/learn/assets/AGENTS.template.md +33 -0
- package/skills/learn/assets/errorlog.template.typ +61 -0
- package/skills/learn/assets/reading-sequence.template.md +23 -0
- package/skills/learn/assets/source-index.template.md +17 -0
- package/skills/learn/assets/tasklog.template.typ +57 -0
- package/skills/learn/assets/workbook.template.typ +60 -0
- package/skills/learn/references/learning-science.md +103 -0
- package/skills/learn/scripts/init_learning_workspace.py +70 -0
- package/skills/macos-messages/SKILL.md +258 -0
- package/skills/memory/SKILL.md +33 -0
- package/skills/memory/codex.md +186 -0
- package/skills/memory/opencode.md +164 -0
- package/skills/mimestreamctl/SKILL.md +170 -0
- package/skills/mimestreamctl/agents/openai.yaml +4 -0
- package/skills/mimestreamctl/scripts/mimestreamctl +33 -0
- package/skills/mon/SKILL.md +51 -0
- package/skills/mon/scripts/mon_spend_review.py +458 -0
- package/skills/ocr/SKILL.md +136 -0
- package/skills/ocr/agents/openai.yaml +4 -0
- package/skills/ocr/references/local-ocr-best-practices.md +297 -0
- package/skills/ocr/references/mineru-api.md +159 -0
- package/skills/ocr/scripts/ocr-router +22 -0
- package/skills/ocr/scripts/ocr_router.py +741 -0
- package/skills/panopto-mp4-bulk-download/SKILL.md +57 -0
- package/skills/panopto-mp4-bulk-download/agents/openai.yaml +4 -0
- package/skills/panopto-mp4-bulk-download/references/url-patterns.md +26 -0
- package/skills/panopto-mp4-bulk-download/scripts/panopto_bulk_mp4.sh +213 -0
- package/skills/rust-systems-style/SKILL.md +109 -0
- package/skills/rust-systems-style/agents/openai.yaml +4 -0
- package/skills/rust-systems-style/references/rust-review-checklist.md +77 -0
- package/skills/rust-systems-style/references/style-sources.md +68 -0
- package/skills/ship-ai-native-cli/SKILL.md +76 -0
- package/skills/ship-ai-native-cli/agents/openai.yaml +4 -0
- package/skills/ship-ai-native-cli/references/case-notes.md +83 -0
- package/skills/ship-ai-native-cli/references/product-method.md +82 -0
- package/skills/ship-ai-native-cli/references/release-checklist.md +147 -0
- package/skills/ship-ai-native-cli/references/rust-cli-shape.md +111 -0
- package/skills/telegram-mtproto-session/SKILL.md +125 -0
- package/skills/telegram-mtproto-session/agents/openai.yaml +4 -0
- package/skills/telegram-mtproto-session/scripts/telegram_session.py +687 -0
- package/skills/tg/SKILL.md +173 -0
- package/skills/things3-manager/SKILL.md +116 -0
- package/skills/things3-manager/scripts/things +42 -0
- package/skills/things3-manager/scripts/things_cli.py +514 -0
- package/skills/web-artifacts-builder/LICENSE.txt +202 -0
- package/skills/web-artifacts-builder/SKILL.md +74 -0
- package/skills/web-artifacts-builder/scripts/bundle-artifact.sh +54 -0
- package/skills/web-artifacts-builder/scripts/init-artifact.sh +379 -0
- package/skills/web-artifacts-builder/scripts/shadcn-components.tar.gz +0 -0
- package/skills/yeet/LICENSE.txt +201 -0
- package/skills/yeet/SKILL.md +71 -0
- package/skills/yeet/agents/openai.yaml +6 -0
- package/skills/yeet/assets/yeet-small.svg +3 -0
- 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.
|