slack-term 1.47.0 → 1.49.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 +86 -2
- package/SKILL.md +3 -2
- package/dist/cli.js +346 -242
- package/locales/en.json +32 -0
- package/locales/ja.json +31 -0
- package/package.json +15 -1
- package/ts/ask.ts +47 -46
- package/ts/botIntent.ts +1 -1
- package/ts/choiceHint.ts +30 -0
- package/ts/cli.ts +774 -126
- package/ts/inbox.ts +191 -0
- package/ts/locales.ts +113 -0
- package/ts/readback.ts +102 -0
- package/ts/redact.ts +225 -0
- package/ts/relayInit.ts +209 -0
- package/ts/scope.ts +472 -0
- package/ts/slack.ts +40 -2
- package/ts/stream.ts +4 -1
- package/ts/tick.ts +47 -0
- package/ts/vendor/gitleaks.LICENSE +21 -0
- package/ts/vendor/gitleaks.toml +3209 -0
- package/worker/README.md +216 -0
- package/worker/src/hub.ts +203 -0
- package/worker/src/index.ts +308 -0
- package/worker/src/slack.ts +127 -0
package/README.md
CHANGED
|
@@ -308,6 +308,60 @@ Notes:
|
|
|
308
308
|
are **never** cached — they are exactly the values that change, and Slack's search index
|
|
309
309
|
already lags. A corrupt or unwritable cache is ignored and the command runs uncached.
|
|
310
310
|
|
|
311
|
+
### .slack-term/ — aliases and settings per directory
|
|
312
|
+
|
|
313
|
+
`slack init` makes a `.slack-term/` in the current directory. `slack` uses the nearest one walking up from where it runs, like `.git`. So each repo, or each agent lane's `tree/<lane>`, has its own aliases and reply prefix, with no pid or env var needed. Without one, it uses `~/.config/slack-term/`. The dir holds a `.gitignore` of `*`, so nothing in it is committed.
|
|
314
|
+
|
|
315
|
+
```sh
|
|
316
|
+
slack init --prefix "[design]" # .slack-term/{README.md,.gitignore,settings.yml,inbox,outbox,sent,archived}
|
|
317
|
+
slack alias set board <permalink> # a reply's permalink names its thread ROOT
|
|
318
|
+
slack alias ls # name channel thread_ts file
|
|
319
|
+
slack read board # the thread
|
|
320
|
+
slack reply board 'done' # posts "[design] done" in it, behind the --code gate
|
|
321
|
+
slack reply --to <permalink> 'on it' # replies in the thread where that message is
|
|
322
|
+
slack reply board 'on it' --to <permalink> # exit 2 when that message is in another thread (--any-thread overrides)
|
|
323
|
+
slack send '#chan:<ts>' 'x' --to <permalink> # the same check on send
|
|
324
|
+
slack alias unset board
|
|
325
|
+
slack tick <permalink> 2 # ⬜ 2. → ✅ 2. in a posted checklist, nothing else changed
|
|
326
|
+
slack thread C00000001 <ts> --since <ts> --format tsv # <ts> TAB <user|bot id> TAB <escaped text> [files: N], every page
|
|
327
|
+
slack edit <permalink> 'new text' # in a [lane] scope the lane tag the message was posted with is kept
|
|
328
|
+
```
|
|
329
|
+
|
|
330
|
+
- **`settings.yml`** is for people to edit. It holds `prefix`, `channel` (used for a bare `<ts>` destination), `as_bot` and `subscriptions`.
|
|
331
|
+
- **`settings.local.yml`** is written by `slack alias set/unset`, under a lock and with an atomic rename. It has the same keys and overrides `settings.yml`.
|
|
332
|
+
- **The prefix is never doubled.** A text that already starts with `[design] ` (or `[design@host] `) keeps only one.
|
|
333
|
+
- `reply` only posts in threads. Use `send` for a top-level post.
|
|
334
|
+
|
|
335
|
+
**Inbox and outbox.** These are files, one per message, written atomically:
|
|
336
|
+
|
|
337
|
+
- **Inbox:** `slack stream --inbox` writes each match into `inbox/` of every registered `.slack-term/` that subscribes its thread. `slack init` registers the dir in `~/.config/slack-term/scopes`. An entry is text only: who, where, the text, the permalink, and a count of files (attachments are never downloaded).
|
|
338
|
+
- **Redaction:** secrets in the text are replaced with `[redacted:<rule>]` before the entry is written (gitleaks' rules plus ours, `ts/redact.ts`). `slack read <permalink>` fetches the original live.
|
|
339
|
+
- **Handled:** `slack done <file|ts>` moves an entry to `archived/`. So does a reply sent with `outbox add … --in-reply-to <ts>` and then `outbox flush`, which records each sent reply's ts and permalink in `sent/`.
|
|
340
|
+
|
|
341
|
+
```sh
|
|
342
|
+
slack inbox listen --timeout 3600 --thread <ts> --from U00000001 # one JSON line per new message, filtered
|
|
343
|
+
slack outbox add board 'fixed' --in-reply-to <ts> && slack outbox flush # then flush again with its --code
|
|
344
|
+
slack alias who D00000001 <thread_ts> --json # for a relay: which lane dir owns a thread
|
|
345
|
+
slack alias set t-<ts> <permalink> --shared --dir <lane tree> # the owner adds to a lane's allowlist
|
|
346
|
+
slack alias import allowlist.tsv --channel D00000001 --lane-dir design=~/ws/x/tree/design
|
|
347
|
+
```
|
|
348
|
+
|
|
349
|
+
**Settings only `settings.yml` can hold:** `restrict_to_subscriptions: true`, `auto_subscribe: [<channel>]` and `nudge_after_min` (see `slack inbox nudge`).
|
|
350
|
+
|
|
351
|
+
- With `restrict_to_subscriptions`, only the `settings.yml` subscriptions count. `alias set` without `--shared` refuses, and `reply` and `outbox flush` refuse any other thread.
|
|
352
|
+
- Who the lane posts as (`prefix`, `as_bot`, `channel`) also comes from `settings.yml` only. `--prefix` and a differing `--as-bot` are refused.
|
|
353
|
+
- `owner: <dir>` names the allowlist's owner. `--shared` writes run only from under that directory, and are refused for everyone when no owner is named. Every lane runs as the same uid, so only the CLI can tell them apart.
|
|
354
|
+
- `auto_subscribe` subscribes a new top-level message in that channel to this dir as `t-<ts>`.
|
|
355
|
+
|
|
356
|
+
### Language packs (locales/*.json)
|
|
357
|
+
|
|
358
|
+
slack-term's own text (help, errors, logs, hints) is English. Language packs hold only two things: text it posts to **people**, and patterns it looks for in **their** messages.
|
|
359
|
+
|
|
360
|
+
- `ask`'s copy is `ask.*`. It follows the readers' Slack locale, then the question's language, then the system locale, and finally `en`. Keys marked `(WIRE)` are matched back on questions already posted, so never reword them.
|
|
361
|
+
- `choice_patterns` are regexes (flags `iu`). Every pack's patterns are applied, so a "(yes/no)?" question is spotted in any language. `send`/`reply` then print a hint to use `slack ask` instead (a hint only, never a block).
|
|
362
|
+
- Packs are read at call time and cached by mtime, so an edit takes effect on the next command with no rebuild.
|
|
363
|
+
- A `.slack-term/locales/<lang>.json` overrides the package's keys. A new file there adds a language.
|
|
364
|
+
|
|
311
365
|
### pinlog — a pinned status board that keeps a log
|
|
312
366
|
|
|
313
367
|
A **pinlog** is one pinned top-level message that always holds the *current* state
|
|
@@ -435,8 +489,8 @@ slack stream --grep '<@U00000001>' --replies-to self --json # + every reply in
|
|
|
435
489
|
between printing a match and saving the cursor repeats that line, so dedupe on
|
|
436
490
|
`channel.id + ts`. A lock file keeps two streams off the same state.
|
|
437
491
|
- **Transport: the relay is the primary mode; polling is the fallback.** Deploy
|
|
438
|
-
|
|
439
|
-
[
|
|
492
|
+
the relay (a Cloudflare Worker on Slack's Events API — see
|
|
493
|
+
[Setting up the relay](#setting-up-the-relay)) and set `SLACK_RELAY_URL` and
|
|
440
494
|
`SLACK_RELAY_TOKEN`: the stream then hears a *doorbell* — `{channel, ts, thread_ts}`,
|
|
441
495
|
no text — within a second of each post, reads that one message through the Web API
|
|
442
496
|
with its own token and runs it through the same `--grep`. While the relay is
|
|
@@ -471,6 +525,34 @@ slack stream --grep '<@U00000001>' --replies-to self --json # + every reply in
|
|
|
471
525
|
SIGINT/SIGTERM; `2` `--once` found nothing; `3` transport/auth failure (stderr says
|
|
472
526
|
which); `1` bad arguments (e.g. an invalid regex).
|
|
473
527
|
|
|
528
|
+
#### Setting up the relay
|
|
529
|
+
|
|
530
|
+
No clone needed — the relay ships in the npm package as `slack-term/worker`:
|
|
531
|
+
|
|
532
|
+
```sh
|
|
533
|
+
slack relay init my-relay # writes package.json, wrangler.jsonc, src/index.ts, .gitignore, README.md
|
|
534
|
+
```
|
|
535
|
+
|
|
536
|
+
It writes local files only (no network; refuses to overwrite without `--force`) and
|
|
537
|
+
prints a freshly generated `RELAY_TOKEN` (never saved to disk) with the next steps:
|
|
538
|
+
`npm install`, `npx wrangler login` (or `CLOUDFLARE_API_TOKEN` + `CLOUDFLARE_ACCOUNT_ID`),
|
|
539
|
+
`npx wrangler deploy` (Node ≥ 22), `wrangler secret put SLACK_SIGNING_SECRET` /
|
|
540
|
+
`RELAY_TOKEN` / optional `SLACK_TEAM_ID`, then the Slack app's Event Subscriptions
|
|
541
|
+
Request URL `https://<worker>/slack/events`. Check it with `slack relay health`
|
|
542
|
+
(GET `/health` using `SLACK_RELAY_URL` / `SLACK_RELAY_TOKEN`) and `slack stream`,
|
|
543
|
+
which says `relay connected (websocket)`.
|
|
544
|
+
|
|
545
|
+
An existing Worker project needs only the re-export (plus the `RELAY` Durable
|
|
546
|
+
Object binding and a `new_sqlite_classes: ["Relay"]` migration in wrangler config):
|
|
547
|
+
|
|
548
|
+
```ts
|
|
549
|
+
// src/index.ts
|
|
550
|
+
export { default, Relay } from "slack-term/worker";
|
|
551
|
+
```
|
|
552
|
+
|
|
553
|
+
Endpoints, privacy and protocol: [worker/README.md](worker/README.md), which also
|
|
554
|
+
covers deploying straight from a clone of this repo (for contributors).
|
|
555
|
+
|
|
474
556
|
## Configuration
|
|
475
557
|
|
|
476
558
|
Requires a Slack user token (`xoxp-...`) with the following scopes:
|
|
@@ -587,6 +669,8 @@ A write-up of the design decisions behind the confirm gate lives on the agent-ye
|
|
|
587
669
|
|
|
588
670
|
## License
|
|
589
671
|
|
|
672
|
+
`ts/vendor/gitleaks.toml` is gitleaks' default rule set (v8.30.1, MIT, © 2019 Zachary Rice, `ts/vendor/gitleaks.LICENSE`). slack-term runs it in-process (`ts/redact.ts`) to redact secrets from anything it writes to disk.
|
|
673
|
+
|
|
590
674
|
MIT
|
|
591
675
|
|
|
592
676
|
### Print the active token (TypeScript CLI)
|
package/SKILL.md
CHANGED
|
@@ -54,8 +54,9 @@ slack msgs
|
|
|
54
54
|
|
|
55
55
|
# Every new message matching a regex, across all channels + threads (long-running;
|
|
56
56
|
# resumable cursor; as the bot when SLACK_BOT_TOKEN is set). Exit 0 match / 2 none / 3 failure.
|
|
57
|
-
# Real time = the relay (primary mode):
|
|
58
|
-
#
|
|
57
|
+
# Real time = the relay (primary mode): `slack relay init` scaffolds a Cloudflare Worker
|
|
58
|
+
# (local files only; prints a RELAY_TOKEN and the deploy steps), then set
|
|
59
|
+
# SLACK_RELAY_URL + SLACK_RELAY_TOKEN; `slack relay health` checks it. Without it the stream falls back to POLLING and
|
|
59
60
|
# warns on stderr ("WARNING: polling mode") — a fallback only: paced (--calls-per-min 40),
|
|
60
61
|
# cursor-only reads each --interval (45s), full --thread-window re-read every --thread-scan (3m).
|
|
61
62
|
slack stream --grep '<@U00000001>|@mybot' --json
|