An AI-powered autonomous coding assistant that works while you sleep.
Night Shift Agent is a Python-based autonomous coding agent powered by Gemini AI (with automatic failover to Claude, OpenRouter, and Ollama). It reads a task list, writes code, verifies builds, creates pull requests, and monitors CI—all without human intervention.
Most AI coding agents run in the cloud or sandboxed environments. Night Shift Agent runs locally on your machine—because mobile development demands it.
Mobile apps require platform SDKs (Android SDK, Xcode), emulators, proprietary build systems (Gradle, CocoaPods), and hardware-specific testing that simply can't run in a generic cloud container. This agent is designed to work with your local development environment, not around it.
# 1. Clone the agent
git clone https://github.com/chrishonson/night-shift-agent.git
cd night-shift-agent
# 2. Setup Python environment
python -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
# 3. Configure
cp .env.example .env
# Edit .env with your credentials
# 4. Run against your project
python agent_night_shift.py --project-dir /path/to/your/project┌─────────────────────────────────────────────────────────────────┐
│ Night Shift Agent v3.6 │
│ │
│ tasks.txt ──▶ LLM (Gemini/Claude) ──▶ Code Changes ──▶ PR │
│ │ │
│ ┌─────────┴─────────┐ │
│ │ 7 Tools │ │
│ ├───────────────────┤ │
│ │ read_file │ │
│ │ write_file │ │
│ │ replace │ │
│ │ list_files │ │
│ │ run_shell │ │
│ │ run_tests │ │
│ │ verify_build │ │
│ └───────────────────┘ │
└─────────────────────────────────────────────────────────────────┘
The agent operates in a TDD loop:
- Read the next uncompleted task from
tasks.txt - Understand the codebase using
list_filesandread_file - Write tests first using
write_file(TDD red phase) - Run tests with
run_teststo confirm they fail - Implement code to make tests pass (TDD green phase)
- Verify with
verify_build(build + tests + coverage) - Commit when verification passes
- Repeat until all tasks are complete
- Push and create Pull Request
The agent supports automatic failover between LLM providers:
- Gemini CLI (primary) - uses
geminicommand - Claude CLI - uses
claude --print - OpenRouter API - requires
OPENROUTER_API_KEY - Ollama - local inference at
localhost:11434
When any provider hits a rate limit or quota, it automatically switches to the next.
Create a .env file (copy from .env.example):
# Required
GH_BOT_TOKEN=ghp_xxxxxxxxxxxxxxxxxxxx # GitHub PAT with repo access
# Optional - Agent Configuration
BOT_USERNAME=agentnightshift # Git commit author (default: agentnightshift)
PREFERRED_AGENT_MODEL=gemini-2.5-flash-lite # Gemini model (default: gemini-2.5-flash-lite)
# Optional - Additional Providers
OLLAMA_MODEL=deepseek-r1:32b # Ollama model (default: deepseek-r1:32b)
OPENROUTER_API_KEY=sk-or-... # OpenRouter API key
OPENROUTER_MODEL=google/gemini-2.0-flash-exp:free # OpenRouter modelYour GH_BOT_TOKEN needs these permissions:
- Contents: Read and write
- Pull requests: Read and write
- Metadata: Read-only
- Actions: Read-only (for CI monitoring)
Create a tasks.txt in your target project:
Add a dark mode toggle to the settings screen
Implement unit tests for UserStore
Fix the login button accessibility label
After processing:
[x] Add a dark mode toggle to the settings screen
[x] Implement unit tests for UserStore
[!] Fix the login button accessibility label
[x]= Completed successfully[!]= Failed (agent couldn't complete)- Lines starting with
#are ignored (comments)
The agent cannot modify these critical build files (configurable in script):
build.gradle.ktssettings.gradle.ktsgradle.propertieslibs.versions.tomlgradle-wrapper.propertiestasks.txt
Session logs are saved to .agent_logs/ in the target project directory:
.agent_logs/
├── session_20251225_144005.log # Main agent activity log
├── prompts_20251225_144005.log # Full LLM prompts & responses
└── ...
| File | Contents |
|---|---|
session_*.log |
Agent operations, tool calls, build results |
prompts_*.log |
Complete LLM conversations (useful for debugging) |
The agent includes several safeguards to prevent runaway failures:
After each successful build, the agent saves a snapshot of all modified files. If the agent encounters 5 consecutive build failures, it will:
- Automatically revert all changed files to the last known-good checkpoint
- Notify itself to "try a simpler approach"
- Reset the failure counter and continue
This prevents the agent from spiraling into an infinite loop of failed attempts.
Log example:
⚠️ Consecutive build failures: 5/5
🔄 AUTO-REVERT: 5 consecutive failures, restoring checkpoint...
↩️ Reverted: ChatService.kt
↩️ Reverted: App.kt
📸 Reverted 2 files to checkpoint. Agent notified to try simpler approach.
To prevent command spam (e.g., retrying the same failing build), the agent enforces rate limits:
- Same command limit: Max 3 identical commands within 30 seconds
- When rate-limited, the agent is told to read error logs and try a different approach
When conversation context exceeds 30,000 characters, the agent automatically drops the oldest message pairs (preserving system prompt and current task) to stay within limits.
See kmp-agentic-ci-template for a complete example including:
- MVI Architecture documentation
- GitHub Actions CI pipeline
- Self-hosted runner setup for UI tests
- Branch protection configuration
-
Enable Branch Protection
- Since the agent needs write access, you MUST protect your
mainbranch. - Go to Repo Settings → Branches → Add Rule →
main→ Check "Require a pull request before merging".
- Since the agent needs write access, you MUST protect your
-
Create an
ARCHITECTURE.mdin your project root describing patterns/conventions.Click to see ARCHITECTURE.md example
# Project Architecture ## Patterns - We use MVI (Model-View-Intent) architecture - State is immutable - ViewModels are called "Stores" ## Naming Conventions - Screen composables: `[Name]Screen.kt` - State classes: `[Name]State` - Intent sealed interfaces: `[Name]Intent` ## Testing - Unit tests go in `src/test/` - UI tests go in `src/androidTest/`
-
Create a
tasks.txtwith your tasks (and maybe add it to.gitignore!). -
Run the agent:
python agent_night_shift.py --project-dir /path/to/projectIf your project includes UI tests that run on a self-hosted runner (like connectedAndroidTest), you'll need to configure your local machine as a GitHub Actions runner.
Follow the complete setup in your project's docs/RUNNER_SETUP.md.
If you already have a runner configured for a different repo:
# 1. Stop the current runner service
cd ~/actions-runner
sudo ./svc.sh stop
# 2. Remove the old configuration
./config.sh remove
# 3. Get a new token from GitHub:
# Go to: GitHub → YOUR_NEW_REPO → Settings → Actions → Runners → New self-hosted runner
# Copy the registration token shown
# 4. Configure for the new repo
./config.sh --url https://github.com/OWNER/NEW_REPO --token YOUR_NEW_TOKEN
# 5. Restart the service
sudo ./svc.sh start
# 6. Verify it's running
sudo ./svc.sh statusRegister a runner at the organization level instead:
- Go to:
github.com/organizations/YOUR_ORG/settings/actions/runners - Add a new runner at org level
- The runner will be available to all repos in that org
| Issue | Solution |
|---|---|
GH_BOT_TOKEN not set |
Add token to .env file |
No tasks.txt found |
Create tasks.txt in project root |
| Agent modifies wrong files | Add files to PROTECTED_FILES in agent_night_shift.py |
| Build always fails | Check that build command works manually |
| CI status not detected | Verify gh CLI is authenticated |
- Small, focused tasks — "Add a logout button" works better than "Refactor the entire auth flow"
- Context is King — A detailed
ARCHITECTURE.mdhelps the agent mimic your coding style - Review PRs — The agent is autonomous but not infallible; always review code before merging
- Branch Protection — Use CI guardrails to prevent broken code from hitting main
This project explores agentic CI/CD—the idea that an AI agent can:
- Receive high-level tasks
- Autonomously implement them
- Verify correctness through existing guardrails (builds, tests, linters)
- Submit changes for human review via pull requests
- Iterate on feedback by continuing work on rejected PRs
| Document | Description |
|---|---|
| KMP Template | Example mobile project |