A self-aware AI assistant that lives entirely in your GitHub repository
GitButler is a personal AI helper that runs on GitHub Actions, communicates via Telegram, and maintains persistent memory using Git. It's completely serverless, costs nothing beyond OpenAI API usage, and can even improve itself through code changes.
- π§ Self-Aware: Loads its own identity and memory before every response
- π¬ Natural Language Only: No slash commands or buttons - just chat naturally
- β‘ GitHub Actions Powered: Runs every minute on free GitHub infrastructure
- π Persistent Memory: Everything stored in Git (soul.md for identity & reflections)
- π§Ύ Per-Run Session Cache: Message logs stay in memory for each action run and clear when it stops
- π Self-Improving: Can create issues/PRs to modify its own code
- π Scheduled Tasks: Cron-based reminders and recurring prompts
- π― Skills System: Extensible with markdown-based skill definitions
- π Private: All data stays in your repo, no external databases
- π Continuous Mode: Long-running mode with ~10 second response time
GitButler now supports continuous mode - a long-running operation mode that keeps the bot active and responsive with near-real-time responses (~10 second polling).
Instead of processing one message and exiting, continuous mode runs in a loop:
- Active Mode (π’): Polls Telegram every 10 seconds for new messages
- Idle Mode (π‘): Polls every 30 seconds (low-power mode)
- Stopped Mode (π€): Bot is sleeping, waiting for wake command
You can control the bot with special commands:
Start the bot:
startwake upwake
Stop the bot:
stopsleeppause
Check status:
status
The bot automatically goes to idle mode after 30 minutes of inactivity to conserve GitHub Actions minutes. This prevents the bot from running indefinitely when not in use.
GitButler supports two modes via the RUN_MODE environment variable:
continuous(default): Long-running mode with ~10 second responsessingle: Process one message and exit (legacy mode)
The workflow is configured with:
- 6-hour timeout: Maximum GitHub Actions allows
- 5-minute schedule fallback: Checks for messages if bot is stopped
- Manual trigger: You can start continuous mode manually via workflow_dispatch
You: start
Bot: π I'm awake and active! Ready to help.
You: What can you do?
Bot: [Responds in ~10 seconds]
You: status
Bot: π Bot Status
Mode: ACTIVE π’
Uptime: 0:15:23
Messages processed: 5
Idle cycles: 0/180
You: stop
Bot: π€ Going to sleep. Send 'start' or 'wake up' to reactivate me.
- Near real-time: ~10 second response time when active
- Cost efficient: Auto-sleeps when idle to save Actions minutes
- Always available: Can stay active for up to 6 hours
- User controlled: Start/stop anytime with simple commands
- Conversational: Natural back-and-forth chat experience
User β Telegram β GitHub Actions (workflow dispatch) β GitButler β Response
β
Git commits (state, memory, soul)
Continuous Mode (Default):
- Start: Bot enters continuous loop checking for messages every 10 seconds
- Process: When message arrives, loads context and sends to GPT-4o-mini
- Respond: Sends response directly to Telegram
- Auto-sleep: After 30 minutes of inactivity, switches to idle mode
- State: Maintains active/idle/stopped state in storage/state.json
Single Message Mode (Legacy):
- Early Check: Before installing any dependencies, checks Telegram API for new messages (lightweight)
- Exit Fast: If no new messages, exits immediately without installing dependencies
- Fetch: If updates exist, installs dependencies and fetches message details
- Process: Loads soul.md + skills, sends to GPT-4o-mini, gets response
- Send: Sends response directly to Telegram (no queue)
- Act: Handles actions (update soul, create issues/PRs, etc.)
- Track: Updates last_update_id in state.json
- Commit: Pushes all changes to Git
Key Design Principles:
- β Continuous mode by default for near real-time responses (~10 seconds)
- β Auto-sleep after 30 min idle to conserve GitHub Actions minutes
- β User control commands (start/stop/status) for manual control
- β State machine (active/idle/stopped) persisted in Git
- β Single message mode still available (RUN_MODE=single)
- β No message queues - direct API calls only
- β Track last processed update_id for Telegram offset
- β Simple function-based architecture (no classes)
agent0/
βββ bot.py # Main Python script (function-based)
βββ check_updates.sh # Early update checker (runs before dependencies)
βββ .github/workflows/
β βββ main.yml # GitHub Actions workflow (workflow_dispatch)
βββ storage/ # Persistent context (OpenClaw pattern)
β βββ soul.md # Core personality & reflections
β βββ IDENTITY.md # Identity card (name, role, capabilities)
β βββ USER.md # User profile & preferences
β βββ MEMORY.md # Long-term episodic memory
β βββ AGENTS.md # Operating instructions & guidelines
β βββ TOOLS.md # Available tools & environment docs
β βββ state.json # Last processed message_id, runtime state
βββ skills/
βββ */skill.md # Modular skill definitions
Note: The queues/ directory has been removed - no more message queuing!
- Message @BotFather on Telegram
- Use
/newbotcommand and follow instructions - Save your bot token
- Get your chat ID by messaging your bot, then visit:
https://api.telegram.org/bot<YOUR_BOT_TOKEN>/getUpdatesLook for"chat":{"id":123456789}in the response
Go to: Settings β Secrets and variables β Actions β New repository secret
Add these secrets (they are already configured for this repo):
OPENAI_API_KEY- Your OpenAI API keyTELEGRAM_TOKEN- Your Telegram bot token from BotFatherTELEGRAM_CHAT_ID- Your Telegram user chat ID (as a string)GITHUB_TOKEN- Already available automatically
Go to Actions tab in your repository and enable workflows if they're not already enabled.
Option A: Continuous Mode (Recommended)
- Go to Actions β GitButler Agent workflow
- Click Run workflow β Select
continuousmode - The bot will run for up to 6 hours or until stopped
- Send a message to your bot - it will respond in ~10 seconds
Option B: Single Message Mode
- Go to Actions β GitButler Agent workflow
- Click Run workflow β Select
singlemode - Bot processes one message and exits
Option C: Schedule (Automatic) The workflow runs every 5 minutes by default to check for new messages when the bot is stopped.
Continuous mode:
You: start
Bot: GitButler session started (sent once per run)
You: What's the weather?
Bot: [Responds in ~10 seconds]
You: status
Bot: π Bot Status - Mode: ACTIVE π’
You: stop
Bot: π€ Going to sleep. Send 'start' or 'wake up' to reactivate me.
Single message mode: Send a message to your Telegram bot, then trigger the workflow to:
- Fetch your message directly from Telegram
- Load its soul and relevant skills
- Think using GPT-4o-mini
- Respond to you directly
- Commit the conversation to Git
Just chat naturally with your bot:
You: Hello! What can you do?
Bot: Hi! I'm GitButler, your personal AI assistant...
You: Remember that I prefer Python over JavaScript
Bot: I've noted your preference for Python...
You: Add "buy groceries" to my todo list
Bot: I've added "buy groceries" to your todo list...
You: Can you improve your error handling?
Bot: I'll create an issue for that improvement...
GitButler uses the OpenClaw pattern for self-awareness: separate markdown files for different aspects of identity and memory, making the bot truly self-aware and maintainable.
All these files are loaded into the bot's context before every response, giving it persistent identity and knowledge:
| File | Purpose | Editable By |
|---|---|---|
storage/soul.md |
Core personality, values, worldview, and reflections | Bot appends reflections, you can edit |
storage/IDENTITY.md |
Quick reference card: name, role, capabilities, version | You edit |
storage/USER.md |
Your profile: name, timezone, preferences, habits | Bot learns & updates, you can edit |
storage/MEMORY.md |
Long-term episodic memory: past conversations, facts learned | Bot appends entries, you can curate |
storage/AGENTS.md |
Operating instructions, tool usage guidelines, safety rails | You edit (comprehensive playbook) |
storage/TOOLS.md |
Available tools, environment docs, API references | You edit |
skills/*/skill.md |
Modular skill definitions injected when relevant | You create/edit |
- Loading Order: SOUL β IDENTITY β USER β MEMORY β AGENTS β TOOLS β skills
- Self-Modification: Bot can append to soul.md, memory.md, and user.md via JSON actions
- Why Markdown? Human + bot readable, git-diff friendly, no schema migrations
- Inspired By: OpenClaw - self-hosted AI agent pattern
The bot can update these files through JSON actions in its responses:
{"update_soul": true, "content": "Reflection: I learned..."}
{"update_memory": true, "content": "User prefers concise answers"}
{"update_user": true, "content": "Timezone: UTC+1"}This makes your bot feel "alive" and continuous β it remembers you and gets better over time.
The scheduled tasks feature has been removed to simplify the bot architecture. The bot now focuses solely on processing incoming messages one at a time.
Create new skills in skills/<name>/skill.md with markdown content and optional YAML frontmatter.
GitButler can improve itself by creating GitHub issues with @copilot mentions for automated implementation.
MIT
Made by motyar