@avanderhoorn/toy-box-slack 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 +77 -2
- package/package.json +40 -4
- package/toy-box-slack +5 -0
- package/toy-box-slack-darwin-arm64 +4 -0
package/README.md
CHANGED
|
@@ -1,3 +1,78 @@
|
|
|
1
|
-
#
|
|
1
|
+
# toy-box-slack
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
One local bridge lets a [Toy Box](https://github.com/lostintangent/toy-box) channel's Copilot lead answer allowed people in one Slack channel, publish scheduled release notes there, and bring useful activity back to Toy Box.
|
|
4
|
+
|
|
5
|
+
The four v1 guarantees are: only allowlisted people can open requests, only the owner widens access, uncertain posts are never resent, and events survive acknowledgement with gaps recovered or reported. Rare channel or policy changes suspend the link for owner review. The bridge keeps only what its links need, by default what allowed people say and the threads they ask in, and forgets any Slack text 30 days after it last changed. See [operations](docs/operations.md) for recovery and retention limits.
|
|
6
|
+
|
|
7
|
+
No DMs, attachments, Slack Connect, org-wide installs, rotating tokens or non-Copilot leads. Slack text the lead reads reaches Copilot and its selected model provider. Obtain company approval first and read the [reviewer guide](docs/security-review.md).
|
|
8
|
+
|
|
9
|
+
## Before you start
|
|
10
|
+
|
|
11
|
+
On an Apple silicon Mac, install [Node 24](https://nodejs.org/en/download). With the Mac's default zsh, put `~/.local/bin` on your PATH, then install Copilot, Toy Box and toy-box-slack:
|
|
12
|
+
|
|
13
|
+
```sh
|
|
14
|
+
export PATH="$HOME/.local/bin:$PATH"
|
|
15
|
+
printf '%s\n' 'export PATH="$HOME/.local/bin:$PATH"' >> "$HOME/.zshrc"
|
|
16
|
+
npm install --global --prefix "$HOME/.local" @github/copilot @lostintangent/toy-box @avanderhoorn/toy-box-slack
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
Run `copilot`, use `/login` to sign in, then exit. Start Toy Box **from this PATH**, so its leads can find `toy-box-slack`:
|
|
20
|
+
|
|
21
|
+
```sh
|
|
22
|
+
toy-box --host 127.0.0.1
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
Toy Box has no authentication. Never expose it publicly or through a tunnel.
|
|
26
|
+
|
|
27
|
+
## Set up
|
|
28
|
+
|
|
29
|
+
Toy Box keeps its terminal, so use another for these three steps.
|
|
30
|
+
|
|
31
|
+
1. **Create the Slack app.** At <https://api.slack.com/apps>, choose **Create New App > From a manifest**, choose the approved workspace, and paste [docs/manifest.yaml](docs/manifest.yaml). Review the eight bot scopes and create the app. Install it to that workspace from **OAuth & Permissions**, which then shows its **Bot User OAuth Token** (`xoxb-...`). Under **Basic Information > App-Level Tokens**, generate an app-level token (`xapp-...`) with `connections:write`. The manifest already enables Socket Mode, so no public Request URL is needed. Do not enable token rotation.
|
|
32
|
+
|
|
33
|
+
2. **Start the bridge.** Run `toy-box-slack serve` and keep it running. The first time, it asks for both tokens and for a passphrase you choose, typed twice. Paste the tokens only there, never into Toy Box, Slack or the repository. Nothing you type is shown. `link`, `allow` and `resume` ask for the passphrase before they widen who can make the lead act, so make it strong and unique, and never put it in Toy Box or Slack. Each time it starts, `serve` installs the skill leads learn the CLI from, and names the file.
|
|
34
|
+
|
|
35
|
+
3. **Link the channels.** Invite the app into the Slack channel with `/invite` and select **Toy Box**. Open <http://127.0.0.1:3000> and create a channel with a Copilot lead (tested with `claude-sonnet-5`). To use a lead that was already running instead, ask it to read the file `serve` named, since Copilot reads skills when a lead's session starts or resumes. Copy the Slack channel ID from the bottom of its details and the allowed people's member IDs from their profiles, then ask the lead to set up Slack for those IDs. It creates its inbox routine and prints the exact `link` and `allow` commands. Run them yourself in another terminal, and review each preview before you enter the passphrase. Their forms are:
|
|
36
|
+
|
|
37
|
+
```sh
|
|
38
|
+
toy-box-slack link --channel TOYBOX_ID --slack-channel SLACK_ID
|
|
39
|
+
toy-box-slack allow --channel TOYBOX_ID USER_ID
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
Defaults are `--requests mention --observe requesters`; `--requests all` accepts any allowed person's top-level post, and `--observe channel` lets a digest read other people's text too. Ask the lead for opt-in digest or release-note routines if wanted.
|
|
43
|
+
|
|
44
|
+
Send a **new** mention by selecting the app in Slack's mention menu. An allowed person's question should get eyes and one threaded answer within minutes. If it does not, check `toy-box-slack status` and the [operations guide](docs/operations.md).
|
|
45
|
+
|
|
46
|
+
## Several leads in one Slack channel
|
|
47
|
+
|
|
48
|
+
People tell leads apart by the bot they mention, so leads in the same Slack channel each need a Slack app of their own, while leads in different Slack channels share one. Create another Slack app, add it to the bridge with `toy-box-slack add-app <name>`, and link through it with `--app <name>`, as [operations](docs/operations.md#add-or-remove-an-app) describes. Ask people there to mention the lead they mean, since a reply that mentions no one reaches every lead its author asked in that thread. Two links with `--requests all` both answer each top-level post that mentions no one, from someone they both allow.
|
|
49
|
+
|
|
50
|
+
## Keep it running
|
|
51
|
+
|
|
52
|
+
The bridge answers only while `serve` runs. Ctrl-C stops it. When `serve` runs again, it catches up on what it missed, within the [limits](docs/operations.md#deletion-and-limits) of catch-up. To start it at login instead, see [operations](docs/operations.md#start-the-bridge-at-login).
|
|
53
|
+
|
|
54
|
+
`serve` keeps the tokens and the passphrase's hash in `~/.toy-box-slack/credentials.env`, which only you can read. The bridge reads this file, not a `.env`, and environment variables of the same names override it. `TOY_BOX_SLACK_HOME` selects another data folder, and `TOY_BOX_URL` a Toy Box other than <http://127.0.0.1:3000>. `toy-box-slack passphrase` changes the passphrase, given the old one, without a restart.
|
|
55
|
+
|
|
56
|
+
To update, run `npm install --global --prefix "$HOME/.local" @avanderhoorn/toy-box-slack` again, then restart `serve`, or the [login job](docs/operations.md#start-the-bridge-at-login) that runs it. `serve` installs the new release's skill, so ask your leads to set their routines again from it, since a routine keeps the prompt it was created with.
|
|
57
|
+
|
|
58
|
+
## Commands
|
|
59
|
+
|
|
60
|
+
**Lead:** `inbox`, `reply`, `dismiss`, `activity`, `mark-read`, `publish`, `retract`. **Owner:** `passphrase`, `add-app`, `link`, `allow`, `resume`. **Lead or terminal:** `status`, `deny`, `pause`, `unlink`. **Operator:** `serve`.
|
|
61
|
+
|
|
62
|
+
`toy-box-slack <command> --help` gives flags. See [operations](docs/operations.md) for status, pauses, uncertain posts, deletion and starting at login, [AGENTS.md](AGENTS.md) for architecture, and [research](docs/research) for evidence.
|
|
63
|
+
|
|
64
|
+
## Developing
|
|
65
|
+
|
|
66
|
+
1. Install [Bun](https://bun.com/docs/installation) 1.4.4, which CI builds with, and clone this repo
|
|
67
|
+
1. Run `bun install`, which also points Git at the pre-commit hook
|
|
68
|
+
1. Run `bun run check` and `bun test`, which CI runs on every push and pull request
|
|
69
|
+
|
|
70
|
+
`./cli/index.ts` runs the CLI from source. `bun run build` compiles the binary the npm package ships, and `./toy-box-slack` runs it as npm installs it.
|
|
71
|
+
|
|
72
|
+
## Publishing
|
|
73
|
+
|
|
74
|
+
Update `package.json` to the next stable version and keep its release notes under a matching `## 📅 vX.Y.Z (date)` heading in `CHANGELOG.md`. Commit and push those changes, then select **Actions → Publish → Run workflow** on the branch to release.
|
|
75
|
+
|
|
76
|
+
The workflow reads the version and notes from that exact commit, rejects an already published npm version, runs checks and tests, and builds the Apple silicon macOS CLI. It publishes the tested package through npm trusted publishing, then creates the matching GitHub tag and release with the changelog notes and npm tarball attached. No npm token or separately entered release version is needed.
|
|
77
|
+
|
|
78
|
+
If a run fails before npm publication, fix the failure and rerun. If npm succeeds but GitHub release creation fails, recover the tarball from npm with `npm pack @avanderhoorn/toy-box-slack@X.Y.Z --ignore-scripts`, verify its registry integrity, and use that tarball and the original commit's changelog notes to finish the GitHub release manually. Do not rebuild or republish the same npm version.
|
package/package.json
CHANGED
|
@@ -1,6 +1,42 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@avanderhoorn/toy-box-slack",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"
|
|
5
|
-
"
|
|
6
|
-
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Let a Toy Box channel's lead watch and answer a Slack channel",
|
|
5
|
+
"repository": {
|
|
6
|
+
"type": "git",
|
|
7
|
+
"url": "git+https://github.com/avanderhoorn/toy-box-connectors.git"
|
|
8
|
+
},
|
|
9
|
+
"bin": {
|
|
10
|
+
"toy-box-slack": "toy-box-slack"
|
|
11
|
+
},
|
|
12
|
+
"files": [
|
|
13
|
+
"toy-box-slack",
|
|
14
|
+
"toy-box-slack-darwin-arm64"
|
|
15
|
+
],
|
|
16
|
+
"os": [
|
|
17
|
+
"darwin"
|
|
18
|
+
],
|
|
19
|
+
"cpu": [
|
|
20
|
+
"arm64"
|
|
21
|
+
],
|
|
22
|
+
"type": "module",
|
|
23
|
+
"publishConfig": {
|
|
24
|
+
"access": "public"
|
|
25
|
+
},
|
|
26
|
+
"scripts": {
|
|
27
|
+
"build": "bun build cli/index.ts --compile --minify --target=bun-darwin-arm64 --no-compile-autoload-dotenv --no-compile-autoload-bunfig --outfile toy-box-slack-darwin-arm64",
|
|
28
|
+
"check": "bun fmt --check && oxlint && bun check",
|
|
29
|
+
"prepare": "git config core.hooksPath .githooks 2>/dev/null || true"
|
|
30
|
+
},
|
|
31
|
+
"dependencies": {},
|
|
32
|
+
"devDependencies": {
|
|
33
|
+
"@slack/socket-mode": "3.1.0",
|
|
34
|
+
"@slack/web-api": "8.2.0",
|
|
35
|
+
"bun-types": "^1.4.4",
|
|
36
|
+
"citty": "^0.2.2",
|
|
37
|
+
"cron-parser": "^5.10.2",
|
|
38
|
+
"oxlint": "^1.90.0",
|
|
39
|
+
"oxlint-tsgolint": "^7.0.2005",
|
|
40
|
+
"zod": "^4.6.7"
|
|
41
|
+
}
|
|
42
|
+
}
|
package/toy-box-slack
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
#!/bin/sh
|
|
2
|
+
# The command npm installs, which runs the compiled CLI beside it. Toy Box sets BUN_BE_BUN in every
|
|
3
|
+
# agent's shell, and a compiled Bun program run with it set runs as Bun instead, so it's cleared here.
|
|
4
|
+
unset BUN_BE_BUN
|
|
5
|
+
exec "$(dirname "$(realpath "$0")")/toy-box-slack-darwin-arm64" "$@"
|