Repository navigation
Conversation
Gives developers a path from an app that works locally to one that keeps running after the local process stops, using the Slack CLI deploy hook so the skill never handles a token itself. The hook script is provider-agnostic and sources a small per-target file, so adding a provider is one reference file rather than a change to the script. Railway and Heroku ship; both run the app in Socket Mode. Adds four tool-selection eval scenarios, two that should route to the new skill and two that pin the boundaries against slack-cli and slack-docs.
… in real runs A real end-to-end Railway deploy surfaced a prompt Step 5 did not cover. 'slack deploy' asks which app to target, and in a non-interactive shell that prompt is fatal: the CLI reports that the input device is not a TTY and nothing deploys. '--team' and '--app deployed' answer it, and '--app deployed' is the one most easily missed because the prompt only appears on a project that has never been deployed. A real Heroku run surfaced two more. Salesforce-managed accounts cannot own a personal app, so 'apps:create' needs '--team'; the target script now takes HEROKU_TEAM. And 'apps:info' reports the same 'Couldn't find that app' for an app that does not exist and one owned by a stranger, because Heroku app names are globally unique, so a generic name fails later at create time instead.
…cost claim A real Heroku deploy ran two copies of the app. The Node buildpack contributes a default 'web' process type even though the Procfile declares only 'worker', and Heroku starts it on the first release. That second copy opened its own Socket Mode connection, so Slack reported "num_connections": 2 and delivered events to whichever copy it picked, and it never booted successfully either, because a Socket Mode app binds no port and Heroku kills a web dyno that does not bind $PORT within 60 seconds. It sat in a restart loop, opening a fresh connection every cycle, and billed as a second dyno. The worker's own logs looked healthy throughout, so nothing about this was visible from the place a developer would look. 'target_deploy' now scales worker up and web down in one call. The same run disproved the cost line. A team app cannot use the Eco plan and gets Basic dynos billed per dyno, so the '$5/month' figure only holds for a personal app. Salesforce-managed accounts cannot own a personal app at all, which makes the team case the default rather than the exception for anyone in that position.
🦋 Changeset detectedLatest commit: 44d032e The changes in this PR will be included in the next version bump. This PR includes changesets to release 1 package
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
Replace the orchestrator + four-function contract with one linear, self-contained deploy script per provider, on disk, syntax-highlighted. The agent no longer extracts bash out of a fenced markdown block. - Delete references/deploy.sh and its target_* seam. - Add references/heroku/deploy.sh and references/railway/deploy.sh as real executable files. - Reduce references/heroku.md and references/railway.md to prose: cost, caveats, install, project prereqs, env vars, re-deploy, verifying. - Collapse SKILL.md Step 4 from three sub-steps to two. Behaviour is unchanged. The Railway path was re-verified end to end on macOS against a fresh bolt-js-starter-template scaffold. Windows support becomes additive: two .ps1 files beside the two .sh files, no orchestrator to port twice.
…y-<provider>.sh Keep the deploy script out of the project root and name it after the provider, so it sits beside hooks.json and says which host it targets. The hook now points at ./.slack/deploy-railway.sh or ./.slack/deploy-heroku.sh. - Rename references/railway/deploy.sh and references/heroku/deploy.sh to references/deploy-railway.sh and references/deploy-heroku.sh, so each source file shares its installed name. - Update SKILL.md Step 4 for the new paths, and ask before changing an existing deploy key that points at a different script. - Note in each script that the CLI runs the hook from the project root, so its relative paths still resolve there.
The skill is installed on developer machines and can outlive a provider's price list, so a quoted plan or trial term can go stale without us shipping an update. Replace prices, plan names, and trial terms with links to each provider's pricing page, and tell the agent to read or link those pages rather than quote from memory. - Keep the lasting reasons to pick a provider: secrets on stdin, deploy from the working directory vs from git, and personal vs team billing. - Replace the Render and Fly.io comparison with the two checks that apply to any provider: an always-on worker process type, and how it is billed. - Generalise the Heroku idle-sleep check so it no longer names a plan or a timeout.
… app The deploy creates a second Slack app with its own app ID in .slack/apps.json. The old wording read as if the local development app kept running on the host.
Fetching and summarising two pricing pages spends the developer's tokens on every deploy. The skill now hands over the links and keeps only the cost facts that do not change with the price list.
… note An agent reads this after the developer has already chosen Heroku, so the Railway aside invites a mid-deploy provider switch or a --stdin flag Heroku does not have. Step 2 already makes the comparison where the choice happens.
… agent runs Railway: wait for the build with --ci instead of --detach, pass --workspace when set, bound every logs command with --lines, and name RAILWAY_API_TOKEN for headless auth. Heroku: scale web=0 only when a web process type exists (the Python buildpack adds none), restart instead of an empty commit on an up-to-date push, reuse the app named by the heroku git remote, require a committed Procfile and at least one commit, and verify config without printing the tokens. Skill: add a Prepare the Provider step, show how provider variables reach the hook, keep the language-specific get-hooks value, cover Bolt for Python and remote manifests, and drop repeated notes.
…verlap Found in a live Railway run: the skill said to ask when an account has several workspaces without saying how to check, and a re-deploy briefly shows num_connections 2 while Railway removes the old deployment.
…st-deploy gaps Found in live Heroku runs with Bolt for JavaScript and Bolt for Python. slack create does not run git init, so a project inside another repository passed the git checks and would have pushed the parent's code. The deploy script now stops in that case. The docs now say to commit .slack/apps.json after the first deploy, to add a .python-version for Bolt for Python, and that num_connections 2 is expected while the first release's web dyno shuts down.
3 tasks done
mwbrooks
commented
Oct 6, 2026
mwbrooks
commented
Oct 6, 2026
Comment on lines
+24
to
+31
| EXPECTED_SKILLS = ( | ||
| "create-slack-app", | ||
| "block-kit", | ||
| "deploy-slack-app", | ||
| "slack-api", | ||
| "slack-cli", | ||
| "slack-docs", | ||
| ) |
This was referenced Oct 6, 2026
… skill The description no longer says "Socket Mode only, on macOS and Linux", which told agents to skip the skill for those developers before they could see why the case is unsupported. The Request URL and Windows stop messages now ask the developer to update the plugin, since support may have shipped, and link #172 and #171 to upvote. Two routing evals pin both cases.
Step 8 deletes the provider's copy and the deployed Slack app after one confirmation, and leaves the development app in place. Verified end to end on both providers: `railway unlink` needs `--yes`, `heroku apps:destroy` removes the git remote itself, and `slack app delete --force` removes `.slack/apps.json`. Railway schedules the project's removal, so the reference explains why it stays listed. Adds a routing eval for teardown.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
This pull request gives developers a way to deploy a Socket Mode Bolt app to Railway or Heroku, from macOS or Linux, as a separate, always-on Slack app with its own app ID. The local development app is unchanged. It uses the Slack CLI's
deployhook, which runs after the CLI has installed the app, so the bot and app-level tokens are already in the script's environment and nobody has to copy a secret anywhere.Each provider has one self-contained script, copied into the project as
.slack/deploy-railway.shor.slack/deploy-heroku.sh, so adding a host or a PowerShell version later means adding a file rather than changing a shared one. The skill links each provider's pricing page instead of quoting prices, because plans change faster than installed skills get updated.Testing
bolt-js-starter-templateproject.hellomessage and/sample-commandin Slack with nothing running locally, matched to thechat.postMessageandslash_commandsentries in the host's logs.bolt-js-starter-templateandbolt-python-starter-templateprojects. Both deployed, re-deployed with a code change, and answeredhelloin Slack with nothing running locally. The JavaScript project was also re-deployed with no change.slack deployexited 1 with the build error, and the previous deployment stayed live.bolt-js-starter-templateandbolt-python-starter-templateprojects on a Heroku team. Both deployed, re-deployed with and without a code change, and answeredhelloin Slack with nothing running locally. The no-change re-deploys restarted the dynos, and the Python app scaled its worker without awebprocess type.slack deployexited 1 with the npm error, and the previous release stayed current.bolt-js-starter-templatedeploys against Slack CLI v4.9.0. Railway stopped the service right away and scheduled the project's removal, Heroku destroyed the app, andslack app delete --forceremoved the deployed app without a prompt.Manual testing
slack create my-app --template slack-samples/bolt-js-starter-template. Thebolt-python-starter-templateworks too.my-app, ask Claude Code to deploy it to Railway or Heroku, and log in to the provider CLI when it asks.slack run, then sendhelloto the deployed app in Slack. It should reply.slack app delete --app localif you're done with it.Notes
slack deployneeds--app deployedand--teamin a non-interactive shell, or it exits on a prompt the developer never sees.webprocess type, so the app ran as two copies holding two Socket Mode connections until the script scaledwebto zero. The worker's own logs looked healthy the entire time.HEROKU_TEAMis required for them.Requirements
make testand the tests pass. Unit (21) and eval (36) pass, and typecheck is clean.make lintpasses.