I wrote last time about setting up a LINE Bot that lets me control Claude Code from my smartphone. It felt great — until the bot stopped responding the very next day.
Quick recap
In the previous post I connected LINE Messaging API to Claude Code running on my home server, so I could send instructions from my phone and get answers back. Asking “check the logs” or “what does this config say?” from anywhere felt genuinely useful.
This post is the sequel — specifically, the part where things broke.
The bot went silent
The day after building it, I sent a message and got nothing back. Silence from a bot that was working perfectly the night before.
My first guess was a crashed process on the server. I checked the logs: the Webhook had received the message. Claude Code had been invoked. But nothing was sent back to LINE.
I was glad I had proper logging in place. Without it I would have had no way to tell whether the message was lost in transit, crashing on the server, or failing at the reply step.
After a bit more digging, I found the cause: LINE Messaging API’s free plan caps Push Messages at 200 per month. A day of testing — sending messages back and forth to verify the setup — had wiped out the entire monthly quota.
The LINE free tier wall
Under LINE’s free plan, Push Messages are limited to 200 per month. Reply Messages are not counted against this limit, but they come with a 30-second Reply Token timeout, which makes them impractical for Claude Code’s responses that can take several seconds to a few minutes.
The paid plan starts at ¥5,000/month for 3,000 messages — too expensive for a personal home-server hobby project. So I started looking for alternatives.
LINE vs Slack
Before choosing a replacement, I compared the two options.
| LINE Messaging API | Slack | |
|---|---|---|
| Free message limit | 200 Push Messages / month | No limit |
| Reply timeout | Reply Token expires in 30 s | None — async delivery |
| Bot creation | LINE Developers channel | api.slack.com/apps |
| Signature verification | HMAC-SHA256 (required) | HMAC-SHA256 (required) |
| Ease of personal use | Convenient — already on everyone’s phone | Needs an extra app, but free tier is generous |
The absence of a timeout was the deciding factor. Claude Code’s responses sometimes take tens of seconds, and LINE’s 30-second Reply Token had already caused problems in real use.
Switching to Slack
I had never used Slack before, but asking Claude Code for guidance as I went made the whole process feel about as difficult as the LINE setup — which is to say, not very.
1. Create a Slack App
Go to api.slack.com/apps, click “Create New App” → “From scratch”, add chat:write and channels:history to the Bot Token Scopes, and install the app to your workspace.
Two values to save:
- Bot User OAuth Token (
xoxb-...) — for sending messages - Signing Secret — for verifying incoming Webhooks
2. Enable the Events API
Turn on “Event Subscriptions”, register your server’s Webhook endpoint as the Request URL, and add message.channels under “Subscribe to bot events”.
3. Server implementation (Node.js)
const express = require('express');
const crypto = require('crypto');
const { execSync } = require('child_process');
const app = express();
app.use(express.json());
function verifySlackSignature(req) {
const timestamp = req.headers['x-slack-request-timestamp'];
const sig = req.headers['x-slack-signature'];
const base = `v0:${timestamp}:${JSON.stringify(req.body)}`;
const expected = 'v0=' + crypto
.createHmac('sha256', process.env.SLACK_SIGNING_SECRET)
.update(base)
.digest('hex');
return crypto.timingSafeEqual(Buffer.from(sig), Buffer.from(expected));
}
app.post('/slack/events', (req, res) => {
if (req.body.type === 'url_verification') {
return res.json({ challenge: req.body.challenge });
}
if (!verifySlackSignature(req)) return res.sendStatus(403);
const event = req.body.event;
if (!event || event.type !== 'message' || event.bot_id) return res.sendStatus(200);
res.sendStatus(200); // respond to Slack immediately
try {
const result = execSync(
`claude --print "${event.text.replace(/"/g, '\\"')}"`,
{ cwd: '/path/to/repo', timeout: 120000 }
).toString();
fetch('https://slack.com/api/chat.postMessage', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.SLACK_BOT_TOKEN}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({ channel: event.channel, text: result }),
});
} catch (e) {
console.error(e);
}
});
app.listen(3001);
The key difference from LINE: you can call res.sendStatus(200) first and then invoke Claude Code asynchronously. Slack has no timeout concern, so long-running responses are fine.
This article was written via the Slack bot
The draft for this very post was created through the Slack bot. The flow looked like this:
Send message in Slack
│
▼
Home server (Node.js Webhook)
│
▼
Claude Code CLI (running in the repo)
│ creates scripts/post-draft-slack-article.js
▼
WordPress REST API — save as draft
│
▼
Slack reply: "Draft created: id=XXXX"
I sent a single Slack message asking Claude Code to “write the Slack migration article and post it to WordPress as a draft.” Claude Code wrote the script, posted the draft, and replied with “Done.” Writing the migration article through the very tool I had just migrated to — a mildly meta experience.
Takeaways
- LINE Bot free tier (Push Messages) is 200 per month — heavy testing burns through it in a single day
- Proper server logging makes debugging dramatically faster
- Slack has no message-count limit on the free plan and no reply timeout, which makes it a natural fit for Claude Code
- Switching from LINE to Slack turned out to be about the same difficulty
- I wrote this article through the Slack bot the same day I switched — it works