dingtalk-pingo 0.0.0-stage → 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/README.md CHANGED
@@ -1,3 +1,247 @@
1
- # Temporary Holding Version
1
+ # dingtalk-pingo
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ Send text and Markdown messages from your terminal, scripts, or AI coding
4
+ agents straight to your phone through a DingTalk robot — no server, no
5
+ polling, no runtime dependencies beyond Node itself.
6
+
7
+ ```bash
8
+ pingo send --type success --message "Build finished, 42 tests passing."
9
+ ```
10
+
11
+ ## Why
12
+
13
+ You're running a long task over SSH/tmux, or an AI coding agent (Kiro,
14
+ Codex, Claude Code, ...) is working unattended, and you want to know when
15
+ it's actually done — without watching a terminal. `pingo` is a single CLI
16
+ command any script or agent can call to push a one-off notification to
17
+ your phone via DingTalk's one-to-one robot messaging API.
18
+
19
+ It is deliberately one-directional and stateless: it sends a message and
20
+ exits. It does not receive messages, does not run as a background
21
+ service, and does not poll anything.
22
+
23
+ ## Who this is for
24
+
25
+ - Developers who use DingTalk and want build/deploy/test notifications
26
+ pushed to their phone from shell scripts, CI, or cron.
27
+ - People running AI coding agents unattended who want a reliable "it's
28
+ done" / "it needs your input" signal, without a chat-based control
29
+ loop.
30
+ - Anyone who wants a minimal, auditable CLI for DingTalk robot messaging
31
+ instead of a heavier notification framework.
32
+
33
+ ## Install
34
+
35
+ Requires Node.js 18+.
36
+
37
+ ```bash
38
+ npm install -g dingtalk-pingo
39
+ ```
40
+
41
+ This installs a single `pingo` command. The package ships as one bundled
42
+ file with no runtime dependencies.
43
+
44
+ ## Set up your own DingTalk robot
45
+
46
+ Pingo sends through **your own** DingTalk enterprise-internal app and
47
+ robot — there is no shared or hosted robot. You need:
48
+
49
+ 1. A DingTalk enterprise account at <https://open.dingtalk.com/>.
50
+ 2. An enterprise-internal application, which gives you an **AppKey**
51
+ (`clientId`) and **AppSecret** (`clientSecret`).
52
+ 3. A robot created under that application, which gives you a
53
+ **robotCode**.
54
+ 4. Your own DingTalk **userId** (the recipient) — the person the robot
55
+ will message.
56
+ 5. Robot permission to send one-to-one ("private chat") messages, granted
57
+ to the application in the DingTalk admin console.
58
+
59
+ Exact steps change over time; follow DingTalk's current documentation at
60
+ <https://open.dingtalk.com/> and verify the "send one-to-one messages in
61
+ batch" API (`robot/oToMessages/batchSend`) works for your app before
62
+ relying on it.
63
+
64
+ ## Configure
65
+
66
+ Create `~/.pingo/config.yaml` (on Windows: `%USERPROFILE%\.pingo\config.yaml`)
67
+ and restrict its permissions, since it holds a secret:
68
+
69
+ ```bash
70
+ mkdir -p ~/.pingo
71
+ chmod 700 ~/.pingo
72
+ touch ~/.pingo/config.yaml
73
+ chmod 600 ~/.pingo/config.yaml
74
+ ```
75
+
76
+ ```yaml
77
+ device:
78
+ id: work-mac
79
+ name: Work Mac
80
+ icon: "🏢"
81
+
82
+ dingtalk:
83
+ clientId: <your AppKey>
84
+ clientSecret: <your AppSecret> # or: clientSecretEnv: DINGTALK_CLIENT_SECRET
85
+ robotCode: <your robotCode>
86
+ userId: <your DingTalk userId>
87
+
88
+ message:
89
+ defaultType: info
90
+ preferredFormat: markdown # markdown | text
91
+ fallbackFormat: text
92
+ timeoutMs: 10000
93
+
94
+ templates: # optional: override the built-in templates
95
+ success:
96
+ title: "{typeIcon} {deviceIcon} {device} · done"
97
+ ```
98
+
99
+ Credentials can also come from environment variables, which take
100
+ precedence over the file: `DINGTALK_CLIENT_ID`, `DINGTALK_CLIENT_SECRET`,
101
+ `DINGTALK_ROBOT_CODE`, `DINGTALK_USER_ID`, plus `PINGO_DEVICE_ID`,
102
+ `PINGO_DEVICE_NAME`, `PINGO_DEVICE_ICON` for device identity. This is
103
+ useful in CI or containers where you don't want a config file at all.
104
+
105
+ If you run multiple machines against the same robot (e.g. a work laptop
106
+ and a home desktop), give each one a distinct `device` block so messages
107
+ on your phone are easy to tell apart.
108
+
109
+ > All machines sharing one DingTalk app share one AppSecret — there is no
110
+ > per-device key isolation in this tool. Treat the secret accordingly and
111
+ > rotate it if it may have leaked.
112
+
113
+ ## Usage
114
+
115
+ ```bash
116
+ pingo doctor # self-check: config, permissions, can we get a token?
117
+ pingo config validate # validate config and show where it was loaded from
118
+ pingo config show # print merged config (secrets masked)
119
+
120
+ pingo send --type info --message "Stage 1 complete"
121
+ pingo send --type success --title "Deploy finished" \
122
+ --message "Build and tests passed" --agent kiro --project payment-sdk
123
+ pingo send --type warning --action-required --message "Please review the token permission change"
124
+ pingo send --markdown ./report.md --type success # body from a Markdown file
125
+ pingo send --message "preview this" --dry-run # preview only, no credentials needed
126
+ pingo send --message "x" --json # machine-readable output
127
+ ```
128
+
129
+ Run `pingo --help` for the full option list.
130
+
131
+ ## AI agent skills
132
+
133
+ The package ships two [Agent Skills](https://developers.openai.com/codex/skills/create-skill)
134
+ (a folder with a `SKILL.md`) that teach an AI coding agent when and how
135
+ to call `pingo`:
136
+
137
+ - **`pingo`** — send a one-off message, report, or "done" summary when you
138
+ explicitly ask the agent to ("send me this via pingo", "notify me on
139
+ DingTalk when finished"). It never notifies on its own.
140
+ - **`pingo-follow`** — opt-in, session-scoped follow-up. After you turn it
141
+ on (for example `/pingo-follow`, or `/pingo-follow only notify me when
142
+ you need my review`), the agent notifies you only at major milestones,
143
+ blockers, or when your approval is needed, and stays silent otherwise.
144
+ Turning it on does not itself send a DingTalk message.
145
+
146
+ Install them into the tools you use:
147
+
148
+ ```bash
149
+ pingo skills install # interactive: choose Kiro / Claude Code / Codex
150
+ pingo skills install --tool kiro,claude # non-interactive (required when there is no terminal)
151
+ pingo skills uninstall # removes only links created by this package
152
+ ```
153
+
154
+ `install` creates symlinks `~/.kiro/skills/<name>`, `~/.claude/skills/<name>`,
155
+ and `~/.codex/skills/<name>` that point at the skills shipped inside this
156
+ package. It never overwrites or deletes anything it did not create: if a
157
+ path already exists and is not one of its own links, it is reported as a
158
+ conflict and skipped (exit code 2). Re-running `install` is safe, and it
159
+ repairs links that went stale after you changed Node versions or moved the
160
+ global `node_modules` directory. Start a new session in the tool afterwards
161
+ so it discovers the skills.
162
+
163
+ How to invoke them explicitly: type `/pingo-follow` in Kiro and Claude
164
+ Code, or `$pingo-follow` (or `/skills`) in Codex.
165
+
166
+ ## Exit codes
167
+
168
+ | Code | Meaning |
169
+ |---|---|
170
+ | 0 | DingTalk accepted the request (not the same as the user having read it) |
171
+ | 1 | Usage error |
172
+ | 2 | Missing or invalid configuration, or a skill-install conflict |
173
+ | 3 | Authentication failed |
174
+ | 4 | Invalid content (missing required fields, or too long) |
175
+ | 5 | DingTalk temporarily unavailable or rate-limited (retried twice) |
176
+ | 6 | Result unknown — **the message may have already been sent**; don't resend |
177
+
178
+ ## Message format limits (measured against the live API)
179
+
180
+ - Markdown does **not** support tables or task-list checkboxes
181
+ (`- [ ]`); use plain lists instead.
182
+ - The request body limit is roughly 20000 bytes; Pingo enforces an 8000-byte
183
+ local limit on `msgParam` and rejects oversized content up front rather
184
+ than letting DingTalk reject it (no automatic splitting yet). Each CJK
185
+ character costs roughly 3 bytes.
186
+ - DingTalk accepts a request with a missing title/body without erroring —
187
+ it sends the literal placeholder text `#title#` / `#text#` to the
188
+ phone. Pingo validates required fields locally so that can't happen.
189
+ - Markdown is only downgraded to plain text when DingTalk rejects it as
190
+ an invalid format; a request whose result is unknown (e.g. a timeout)
191
+ is never retried, to avoid duplicate messages.
192
+
193
+ ## Development
194
+
195
+ ```bash
196
+ npm test # unit tests (requires Node ≥ 24 to run .ts directly)
197
+ npm run typecheck
198
+ npm run build # produce dist/pingo.js
199
+ npm run check:dist # verify dist/pingo.js matches the current source
200
+ ```
201
+
202
+ If you change anything under `src/`, run `npm run build` and commit the
203
+ updated `dist/pingo.js` — `npm run check:dist` verifies they match, and
204
+ `prepublishOnly` runs the full check before `npm publish`.
205
+
206
+ ## Status
207
+
208
+ This is an early release: the CLI, configuration, templates, and
209
+ single-recipient text/Markdown sending are implemented and covered by
210
+ unit tests, plus manual verification against a live DingTalk robot. The
211
+ `pingo` and `pingo-follow` skills and `pingo skills install` are
212
+ implemented and covered by unit tests; how reliably each AI tool follows
213
+ `pingo-follow` has not been verified end to end yet (see below).
214
+ Image/screenshot sending is not implemented yet.
215
+
216
+ ## Known limitations
217
+
218
+ - **Skill directories.** `~/.kiro/skills`, `~/.claude/skills` and
219
+ `~/.codex/skills` are the locations `pingo skills install` uses. Kiro
220
+ and Claude Code document their skill folders; for Codex the official
221
+ pages describe the `SKILL.md` format and `$skill` / `/skills`
222
+ invocation but `~/.codex/skills` could not be confirmed as the default
223
+ directory from documentation — it matches the directory Codex uses on
224
+ the author's machine. If your Codex setup reads skills from somewhere
225
+ else, link `skills/pingo*` there yourself.
226
+ - **`pingo-follow` is advisory.** It is plain instructions, not a
227
+ background service. Its on/off state lives only in the agent's
228
+ conversation context, so it can be lost after a context compaction,
229
+ a crash, or a new session (a new session always starts with it off).
230
+ Delivery is best-effort. How strictly each tool honors "only when
231
+ explicitly enabled" is unverified.
232
+ - **Explicit-only invocation is not enforced by the tool.** Claude Code
233
+ has a `disable-model-invocation` frontmatter field that would stop the
234
+ model from loading a skill on its own, but it also hides the skill's
235
+ description from the model, which would break natural-language
236
+ activation such as "follow this task and notify me when done". It is
237
+ therefore not used here, and it could not be confirmed that Kiro or
238
+ Codex honor it. The
239
+ skill's description and body tell the agent to activate only on an
240
+ explicit request; that is guidance, not a hard guarantee.
241
+ - **Skill links follow the package location.** The links point at the
242
+ globally installed package. After changing Node version or moving the
243
+ global `node_modules` directory, re-run `pingo skills install` to
244
+ repair them.
245
+ - **No image sending yet.** The `pingo` skill tells the agent to send a
246
+ text description instead and to say plainly that the image was not
247
+ sent.