LINE Bot Free Tier Is 200 Messages a Month — I Hit the Cap in a Day and Switched to Slack

« Previous Next »

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 APISlack
Free message limit200 Push Messages / monthNo limit
Reply timeoutReply Token expires in 30 sNone — async delivery
Bot creationLINE Developers channelapi.slack.com/apps
Signature verificationHMAC-SHA256 (required)HMAC-SHA256 (required)
Ease of personal useConvenient — already on everyone’s phoneNeeds 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

Related links

Leave a Comment

Your email address will not be published. Required fields are marked *