slack-term 1.26.7 → 1.27.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
@@ -93,6 +93,36 @@ slack delete "<permalink>"
93
93
  slack react "#general:1700000000.000100" white_check_mark
94
94
  slack react "<permalink>" eyes --remove # take a reaction back
95
95
 
96
+ # Ask a question with its choices pre-seeded as 1️⃣..🔟 reactions — answering is
97
+ # one tap on an existing pill, no emoji picker. Same two-step confirm gate as send.
98
+ slack ask "@bob" "本番に出してよい?" "出してよい" "待って"
99
+ # --wait blocks until answered and prints ONLY the answer on stdout, so it composes:
100
+ ANS=$(slack ask "@bob" "本番に出してよい?" "出してよい" "待って" --code=<code> --wait)
101
+ # exit 0 = answered, 2 = timed out (--timeout, default 3600s), 3 = transport failure.
102
+ #
103
+ # The question must say WHO may answer — only their reaction/reply is taken as the
104
+ # answer, so a bystander can't decide it for them. `ask` refuses to post otherwise.
105
+ slack ask "#eng" "@alice この PR 出してよい?" "出す" "待つ" # only alice's answer counts
106
+ slack ask "#eng" "@here 誰か見れる?" "見る" "あとで" # anyone in #eng; real broadcast
107
+ # (In a 1:1 DM the other party counts automatically — no tag needed.)
108
+ #
109
+ # With no choices the question asks for a free-text reply and the reply is the answer.
110
+ # In a DM a plain reply counts; in a channel only reactions and thread replies do.
111
+ # Once answered, the question is edited to "✅ …回答済み > <answer>" and the unpressed
112
+ # seeds are removed, leaving the chosen pill visible.
113
+ #
114
+ # WITHOUT --wait, stdout is the command that collects the answer later:
115
+ RESUME=$(slack ask "@bob" "本番に出してよい?" "出してよい" "待って" --code=<code>)
116
+ # -> slack ask --waitFor='https://acme.slack.com/archives/C00000001/p1700000000000100'
117
+ # Run it whenever you like: it re-reads the question from Slack, so nothing is
118
+ # stored locally and any machine holding the link can collect. Same stdout/exit
119
+ # contract as --wait, plus --timeout 0 = check once (exit 2 while still open),
120
+ # which is what a periodic monitor should use instead of parking on --wait.
121
+ eval "$RESUME --timeout 0" && echo answered
122
+ # A pressed pill is invisible to `slack tail` (it only sees `type: "message"`
123
+ # events and drops `message_changed`), so this is the only way to hear about an
124
+ # answer to a question you did not block on.
125
+
96
126
  # Task tracking on top of reactions — :pushpin: marks a message as a task,
97
127
  # a second reaction carries its progress (see "todo" below)
98
128
  slack todo ls # my open tasks
@@ -238,7 +268,12 @@ Requires a Slack user token (`xoxp-...`) with the following scopes:
238
268
  - `channels:read`, `groups:read`, `im:read`, `mpim:read` — for channel listing
239
269
  - `users:read` — for resolving display names
240
270
  - `chat:write` — for sending messages
241
- - `reactions:write` — for `react` (add/remove reactions)
271
+ - `reactions:write` — for `react` and for `ask` (seeding / clearing the choice pills)
272
+
273
+ `ask` needs no `reactions:read`: it reads the answers back from
274
+ `conversations.history`, which returns each message's `reactions` (with the user
275
+ list) under the `*:history` scopes above. `reactions.get` would need
276
+ `reactions:read`, so it is deliberately not used.
242
277
 
243
278
  > Add each scope to the **token type the CLI actually uses**. The CLI defaults to the
244
279
  > **user token** (`xoxp-...`), so `reactions:write` must be under **User Token Scopes**.
package/SKILL.md CHANGED
@@ -85,6 +85,14 @@ slack delete "<permalink>"
85
85
  slack react "#general:1700000000.000100" white_check_mark
86
86
  slack react "<permalink>" eyes --remove # take it back
87
87
 
88
+ # Ask a question with its choices pre-seeded as 1️⃣..🔟 reactions (same confirm gate)
89
+ # The question MUST @tag whoever may answer — only their reaction/reply counts.
90
+ slack ask "#eng" "@alice この PR 出してよい?" "出す" "待つ"
91
+ ANS=$(slack ask "@bob" "出してよい?" "はい" "待って" --code=<code> --wait) # blocks
92
+ RESUME=$(slack ask "@bob" "出してよい?" "はい" "待って" --code=<code>) # does not
93
+ # RESUME -> slack ask --waitFor='<permalink>' # collect the answer later
94
+ eval "$RESUME --timeout 0" # check once: 0 answered / 2 still open
95
+
88
96
  # Task tracking on reactions — 📌 marks a task, a second reaction holds progress
89
97
  slack todo ls # EVERYONE's open tasks (has:)
90
98
  slack mytodo ls # only tasks YOU reacted to (hasmy:)
@@ -138,6 +146,37 @@ and no one has replied since — `⚠ 相手はまだ返信していません…
138
146
  on that message instead of piling on a new one. Reply-status based, not time-based; opt
139
147
  out with `SLACK_UNREPLIED_WARN=0`.
140
148
 
149
+ ### ask — a question whose answer is one tap
150
+
151
+ Choices are posted as 1️⃣..🔟 reactions on the question itself, so answering costs one tap
152
+ on an existing pill. Reactions, not Block Kit buttons: `block_actions` are delivered only
153
+ to a Request URL or a Socket Mode socket, neither of which a short-lived CLI can own
154
+ without losing clicks. A reaction is durable state anyone can read back later.
155
+
156
+ - **The question must @tag whoever may answer** (`@alice`, or `@here`/`@channel` for the
157
+ whole channel). Only their reaction/reply is taken as the answer; an unaddressed
158
+ question is refused (exit 3) rather than let the first bystander decide it. In a 1:1 DM
159
+ the other party counts automatically.
160
+ - **Answer paths**: a pill, or free text. In a DM a plain reply counts; in a channel only
161
+ reactions and thread replies do (a channel carries unrelated traffic).
162
+ - **Two pills pressed = no answer.** Changing your mind leaves both reactions in place, so
163
+ `ask` says so in the thread once and keeps waiting rather than guessing.
164
+ - **Exit codes** are the contract: `0` answered (the answer alone on stdout), `2` timed
165
+ out, `3` transport/config failure. Everything human-facing goes to stderr, so
166
+ `ANS=$(slack ask … --wait)` is safe.
167
+
168
+ **Collecting an answer you did not block on.** Without `--wait`, stdout is a runnable
169
+ `slack ask --waitFor='<permalink>'`. Run it any time — it re-reads the question from Slack
170
+ and recovers everything it needs by parsing the message, so nothing is stored locally and
171
+ any machine with the link can collect. It reports an already-answered question (the
172
+ ✅-stamped body) immediately, and refuses (exit 3) a message that is not an ask.
173
+ `--timeout 0` checks exactly once, which is what a periodic monitor should use: `--wait`
174
+ parks the process, and a parked lane still looks *active* in `ay ls`.
175
+
176
+ This path is not optional convenience — **a pressed pill is invisible to `slack tail`**,
177
+ which only sees `type: "message"` events and drops `message_changed`. Without `--waitFor`
178
+ an answer can be pressed and nobody ever hears about it.
179
+
141
180
  ### todo — tasks as reactions
142
181
 
143
182
  A task is any message carrying the marker reaction 📌 `:pushpin:`. Progress lives in a