Hachiko is an always-on Slack agent that listens for code change requests, confirms intent, edits the code in GitHub, opens a pull request, and posts the result — all inside the same Slack thread.
Like its namesake — the loyal dog who waited patiently every day — Hachiko sits in your team's channel, ready the moment someone asks.
Small changes get discussed in chat constantly:
"The website still shows $15, but we changed it to $20."
This is a 30-second fix. But someone still has to:
- See the message
- Context-switch out of what they're doing
- Open the repo
- Find the right file
- Make the edit
- Create a branch
- Commit and push
- Open a PR
That's 8 steps and 10+ minutes of engineering time for a one-line change.
Multiply that by every small request that starts in chat, every day.
Hachiko compresses the entire workflow into one conversation:
Slack message --> Confirmation --> Code change --> Pull request --> Slack update
No context switching. No waiting. The team reports the issue where they already work, and Hachiko handles the rest.
Teammate "The website still shows $15, but we changed it to $20."
Hachiko "I can update that and open a pull request. Proceed?"
Teammate "Yes"
Hachiko "Starting now."
Hachiko "Done. Pull request created: https://github.com/..."
Summary: updated homepage price from $15 to $20.
| Without Hachiko | With Hachiko |
|---|---|
| Someone notices an issue in Slack | Someone notices an issue in Slack |
| An engineer picks it up manually | Hachiko detects the request |
| Opens repo, finds file, makes edit | Hachiko asks for confirmation |
| Creates branch, commits, pushes | Hachiko creates the PR |
| Opens a PR | PR link appears in the same thread |
| ~10 minutes, 8 steps | ~30 seconds, 1 reply |
Hachiko is not a one-off script or a chatbot that answers questions. It is a persistent, event-driven automation that:
- Stays running and available at all times
- Is triggered by real Slack messages — not manual invocation
- Performs actual engineering work — not just conversation
- Produces a real artifact — a GitHub pull request
Trust comes from restraint:
- Confirmation required — always asks before acting, never assumes
- PR-only output — creates reviewable pull requests, never auto-merges
- Bounded scope — works in one known repo with predictable changes
- Deterministic execution — same request always produces the same result
- Duplicate prevention — ignores repeated confirmations in the same thread
Slack (Socket Mode) LLM Classifier GitHub App
| | |
message received classify intent create branch
| extract prices update file
thread reply { oldPrice, newPrice } commit change
| or null open PR
confirmation | return PR URL
| | |
+------------- state machine ------------------- +
(in-memory thread tracking)
Stack: Node.js, Slack Bolt, OpenAI API, Octokit, GitHub App Auth
src/
app.js Bolt app + Socket Mode — wires everything together
classifier.js LLM classifier — understands natural language intent
confirmation.js Thread state machine — tracks conversation flow
messages.js Bot message templates — consistent, clean replies
github-auth.js GitHub App auth — JWT + installation tokens
github-pipeline.js PR pipeline — branch, edit, commit, open PR
config.js Environment configuration
Every Slack thread moves through a strict state flow:
IDLE --> AWAITING_CONFIRMATION --> PROCESSING --> DONE
|
ERROR
This prevents duplicate execution, handles failures gracefully, and keeps each thread self-contained.
- Node.js 18+
- Slack App with Socket Mode
- GitHub App with repository access
- OpenAI API key
git clone https://github.com/terdessa/hachiko.git
cd hachiko
npm install
cp .env.example .envSLACK_BOT_TOKEN=xoxb-...
SLACK_APP_TOKEN=xapp-...
OPENAI_API_KEY=sk-...
SLACK_CHANNEL_ID=C...
GITHUB_APP_ID=...
GITHUB_APP_INSTALLATION_ID=...
GITHUB_APP_PRIVATE_KEY_PATH=./your-key.pem
GITHUB_OWNER=your-org
GITHUB_REPO=your-repo
GITHUB_TARGET_FILE=src/price.jsnode src/app.jsGitHub App authenticated
Hachiko is running (Socket Mode)
npm test # 22 tests across 5 suites- Create app at api.slack.com/apps
- Enable Socket Mode — create app-level token with
connections:write - Add bot scopes:
app_mentions:read,chat:write,channels:history - Subscribe to event:
message.channels - Install to workspace, invite bot to channel
- Create app at github.com/settings/apps
- Permissions: Contents (Read & Write), Pull Requests (Read & Write)
- Install on target repository
- Download private key
.pemto project root
The current demo handles price updates — intentionally narrow to prove the loop works. The architecture is designed to expand to any small, well-bounded code change:
- Copy and content updates
- Configuration changes
- Simple code fixes
- Dependency version bumps
- Documentation edits
The pattern stays the same: chat request, confirmation, code change, pull request.
| Principle | Why |
|---|---|
| Chat-native | Works where the team already communicates |
| Always-on | Triggered by real events, not manual runs |
| Confirmation-first | Asks before acting — builds trust |
| PR-only | Never auto-merges — always reviewable |
| Narrow and reliable | Does less, does it well |
Built for the Cursor Guild Hackathon Track: Always-On Agents | Side Quest: Best Developer Tool