Safe GitHub Copilot agent sandboxing for Android (Kotlin) and iOS (Swift) developers.
kote prep → isolated git worktree → agent works safely → kote cleanup --accept
KoteGuard runs Copilot agents in isolated git worktrees so they can never accidentally commit secrets, break your main branch, or touch real signing credentials. Every session is planned, gated, validated, and audited.
| Problem | Without KoteGuard | With KoteGuard |
|---|---|---|
Agent pushes to main |
💥 Happens | --deny-tool='shell(git push)' blocks it |
Agent reads your .jks / .p12 |
💥 Full access | Replaced with stubs before session starts |
| No record of what the agent did | 😬 Nothing | Per-session audit.jsonl + validation-report.md |
| Agent goes off-script | 😬 No way to know | PLAN.md hard gate + change validation on cleanup |
| Context bloat across sessions | 😬 Expensive | --compact accumulates knowledge into WORKSPACE.md |
- 🔍 Smart project analysis — auto-detects Android/iOS, parses
build.gradle+Info.plist, scans docs - 📋 Interactive planning wizard — builds
PLAN.mdwith a refine loop and a hardYESgate - 🌿 Isolated git worktrees — agent works on a dedicated branch, never touches
main - 🔒 Sensitive file stubs —
.jks,google-services.json,.p12,.envreplaced with safe placeholders - 🤖 Copilot CLI ready — generates the complete
copilot --deny-tool=...command for you - 📊 Session tracking — rich status table with plan title, age, Android CLI status, skills loaded, context pressure
- ✅ Auto-validation — validates PLAN.md + changed files on
kote cleanup --accept - 🧰 Android Skills — official guides synced nightly from
github.com/android/skills;kote android updatefetches the latest - 🍎 iOS Skills — bundled SwiftUI, Swift Concurrency, and XCTest guides; auto-detected from your Swift source
- 🔧 Global config —
kote initwizard sets agent mode, IDE, and worktrees directory - 🗂️ Session hygiene —
kote sessions pruneremoves stale session metadata on your schedule - 🧠 Token hygiene —
--compactsaves session knowledge back intoWORKSPACE.md
pip install koteguardRequires Python 3.12+
Or install from source:
git clone https://github.com/alisen/KoteGuard.git
cd KoteGuard
pip install -e ".[dev]"Local install (no GitHub push needed — for testing before publishing):
# Using pipx (recommended for CLI tools)
brew install pipx && pipx ensurepath
pipx install /path/to/KoteGuard
# Or with pip directly
pip install /path/to/KoteGuard# One-time setup (optional — configure your defaults)
kote init
cd your-android-or-ios-project
# 1. Run the wizard — it detects your project, plans, creates the worktree
kote prep
# 2. See what it created
kote status
# 3. Copy the ready-to-run Copilot CLI command
kote cli
# 4. Inside the worktree, make sure the agent committed its changes
# KoteGuard diffs branch commits — uncommitted changes will not be merged
# cd /path/to/worktree && git add -A && git commit -m "agent: apply changes"
# 5. Back in your project root — validate + merge back
cd your-android-or-ios-project # same dir as step 1
kote cleanup --accept
# 6. Or throw it away
kote cleanup --discardkote prep --android-first
# → detects Compose/Navigation/AGP usage
# → shows checkbox to select which skill guides to inject
# → pre-populates PLAN.md with selected skillskote prep
│
├── Phase 0: Scan project
│ detect Android/iOS · parse build.gradle/Info.plist
│ scan docs · detect Android CLI · suggest skills
│
├── Phase 1: Interactive planning
│ title · objectives · tasks · definition of done · risks
│ ──── HARD GATE: type YES to proceed, refine to re-edit ────
│
└── Phase 2: Create worktree
new git branch (kote/<session-id>-<slug>)
writes: PLAN.md · TASK.md · AGENTS.md · WORKSPACE.md
.github/copilot-instructions.md
.github/instructions/security.instructions.md
stubs: google-services.json · *.jks · *.p12 · etc.
logs: sessions/<id>/context/ · logs/ · output/
kote cli
└── prints: cd /worktree && COPILOT_CUSTOM_INSTRUCTIONS_DIRS=... copilot --deny-tool=...
[agent works here]
kote cleanup --accept
├── auto-validates PLAN.md + changed files
├── generates sessions/<id>/output/validation-report.md
├── merges branch back
└── archives PLAN · TASK · diff · audit · report → .kote/history/
| Command | Description |
|---|---|
kote prep |
Full wizard: analyse → plan → worktree → IDE |
kote prep --android-first |
Wizard with Android skills selection |
kote prep --agent-mode <mode> |
Override agent mode: copilot-cli | copilot-plugin | none |
kote prep --dry-run |
Simulate without creating a worktree |
kote ide [session] |
Launch Android Studio or Xcode for a session |
kote cli [session] |
Print complete copilot command + open terminal |
kote status |
Rich table: all sessions with age, skills, context pressure |
kote cleanup --accept |
Run from the original project root. Validate → merge → archive history. Auto-picks most recent active session. |
kote cleanup <session-id> --accept |
Target a specific session by ID (find IDs with kote status) |
kote cleanup --discard |
Throw away changes, preserve audit trail |
kote cleanup --accept --force |
Accept even when validation has errors or uncommitted changes are detected |
kote cleanup --accept --compact |
Accept + save session summary to WORKSPACE.md |
kote validate [plan.md] |
Validate PLAN.md against schema |
kote validate -w WORKSPACE.md |
Also validate WORKSPACE.md |
kote android skills |
List all skills (cached + bundled) + suggest for current project |
kote android update |
Sync latest skill guides from github.com/android/skills |
kote android update --token <PAT> |
Same, with a GitHub token to avoid rate limits |
kote android docs |
Android KB links + worktree status |
kote ios skills |
List bundled iOS skill guides + suggest for current project |
kote sessions prune |
Remove completed/discarded session metadata older than 30 days |
kote sessions prune --days N |
Prune sessions older than N days |
kote sessions prune --dry-run |
Preview which sessions would be pruned |
kote init |
Interactively configure global defaults (agent mode, IDE, worktrees dir) |
kote version |
Print version |
-
Run
kote cleanupfrom the project root — the same directory where you rankote prep. Running it from a different directory causes git operations (diff, merge, branch deletion) to target the wrong repository. -
The agent must commit its changes — KoteGuard detects what changed by diffing branch commits against
main. If the agent modifies files but never runsgit commit, those changes do not exist as commits and will not be merged. KoteGuard will block cleanup with a clear error and recovery instructions when this is detected. Use--forceto skip the block and proceed (the uncommitted changes will not be merged). -
"No changed files detected" warning — means the agent branch has no new commits relative to
main. Check the worktree for uncommitted files before accepting. If the session was already committed and merged manually, this is expected. -
Find session IDs — run
kote statusto see all sessions, their IDs, age, and whether the worktree still exists.
KoteGuard bundles best-practice SKILL.md guides that get injected into the agent's context. The scanner auto-detects which ones are relevant based on your build.gradle.
| Skill | Triggered by | Guide covers |
|---|---|---|
navigation3 |
androidx.navigation dependency |
Type-safe NavHost, @Serializable routes, no string routes |
edge-to-edge |
enableEdgeToEdge / API 35 target |
windowInsetsPadding, Scaffold insets, API 35 enforcement |
agp9 |
AGP 9.x in libs.versions.toml |
JDK 21 requirement, namespace, declarative Kotlin DSL |
compose-migration |
androidx.compose dependency |
State hoisting, collectAsStateWithLifecycle, LazyColumn keys |
kote android update # sync latest skill guides from github.com/android/skills
kote android skills # see all skills (official + bundled) + what's suggested
kote android docs # Android developer documentation linksKoteGuard also runs a nightly GitHub Actions workflow (.github/workflows/sync-android-skills.yml) that automatically checks github.com/android/skills for updates and opens a PR against main whenever skill content changes — so bundled guides stay up to date without any manual work.
KoteGuard also bundles best-practice guides for iOS/Swift developers. The scanner auto-detects relevant guides based on your Swift source files.
| Skill | Triggered by | Guide covers |
|---|---|---|
swiftui-patterns |
import SwiftUI / @Observable |
State management, NavigationStack, scene lifecycle, performance rules |
swift-concurrency |
async/await/actor usage |
Structured concurrency, AsyncStream, cancellation, @MainActor |
xctest |
import XCTest / SnapshotTesting |
Async tests, protocol mocking, snapshot testing, performance tests |
kote ios skills # see what's available + what's suggested for your projectEvery PLAN.md KoteGuard creates has a machine-readable YAML block at the top. This is the source of truth — not just documentation.
---
spec_version: '1.0'
title: Implement login screen
tasks:
- id: t1
description: Create LoginViewModel
done: false
- id: t2
description: Wire up UI
done: false
definition_of_done:
- All tests pass
- Reviewed
---
# Implement login screen
...The agent is instructed to update done: true for each task it completes, directly inside that YAML block. When you run kote cleanup --accept, KoteGuard:
- Parses the YAML — reads exactly which tasks were marked done
- Validates semantically — checks that changed files actually match each task's keywords (CamelCase-aware:
NavGraph→ searches fornav,graphin file paths) - Warns if tasks are undone — if files changed but all tasks are still
done: false, it flags it - Survives corruption — if the agent breaks the YAML, a regex fallback recovers the plan silently
This is why PLAN.md is not just a text document — it's a live spec the agent writes back to.
KoteGuard is designed so that even a misbehaving agent can't cause lasting damage.
| Layer | Mechanism |
|---|---|
| Planning gate | Must type YES (or refine) — no accidental starts |
| Branch isolation | Agent never touches main — always a kote/<id> branch |
| Secret stubs | google-services.json, .jks, .p12 etc. swapped for placeholders before the session |
| Deny-tool flags | git push, git clone, git remote add/set-url are CLI-level blocked |
| Dual instructions | Agent gets both a task brief and a security rules file |
| Validation on accept | PLAN.md compliance + file change analysis before any merge |
| Audit trail | Every event written to sessions/<id>/logs/audit.jsonl + global ~/.kote/audit.jsonl |
| History archival | PLAN, TASK, diff, audit, report copied to .kote/history/ on every accept or discard |
kote cli prints this — ready to paste:
cd /path/to/worktree && \
COPILOT_CUSTOM_INSTRUCTIONS_DIRS=".github/instructions" \
copilot \
--deny-tool='shell(git push)' \
--deny-tool='shell(git remote add)' \
--deny-tool='shell(git remote set-url)' \
--deny-tool='shell(git clone)'src/koteguard/
├── cli.py # Typer CLI (kote + kote android subgroup)
├── models.py # Pydantic v2 models + Android v1.1 skill models
├── config.py # TOML config · session audit · worktree context check
├── project_scanner.py # Phase 0: file-signature detection + gradle parsing + doc analysis
├── worktree.py # Git worktree engine · session subdirs · history archival
├── sensitive_files.py # Sensitive file stub injection
├── planning.py # PLAN.md · WORKSPACE.md · Copilot instructions rendering
├── launcher.py # IDE launcher · build_copilot_cli_command()
├── validation.py # Plan/change/skills validation · report generation
└── templates.py # Template file management
templates/
├── PLAN.md # Includes Token & Context Rules section
├── WORKSPACE.md # Includes Android Agent Stack section
├── TASK.md
├── instructions.md # Includes model selection guidance
├── security.instructions.md # applyTo: "**/*" · Android + iOS deny rules
├── AGENTS.md
├── config.toml
├── android-skills/
│ ├── navigation3.skill.md
│ ├── edge-to-edge.skill.md
│ ├── agp9.skill.md
│ └── compose-migration.skill.md
└── ios-skills/
├── swiftui-patterns.skill.md
├── swift-concurrency.skill.md
└── xctest.skill.md
- Python 3.12+
- Git 2.5+ (for worktree support)
- GitHub Copilot CLI (
copilotbinary) for the terminal workflow - Android Studio or Xcode (optional, for IDE auto-launch)
KoteGuard supports three ways to run the Copilot agent. Set the default in ~/.kote/config.toml or override per session with kote prep --agent-mode.
| Mode | How it runs | kote cli output |
|---|---|---|
copilot-cli (default) |
Terminal binary with --deny-tool security flags |
Full copy-pasteable command |
copilot-plugin |
IDE chat panel (Android Studio, VS Code) | Open IDE at worktree path |
none |
Instructions injected only — bring your own agent | cd <worktree> |
Set defaults interactively:
kote init # guided wizard — sets all fields belowOr edit ~/.kote/config.toml directly:
agent_mode = "copilot-cli" # copilot-cli | copilot-plugin | none
default_ide = "auto" # auto | android | ios
android_cli_enabled = true
worktrees_dir = "~/.kote/worktrees"Override per session:
kote prep --agent-mode copilot-plugingit clone https://github.com/alisen/KoteGuard.git
cd KoteGuard
python -m venv .venv && source .venv/bin/activate
pip install -e ".[dev]"
pytestMIT © Alishen
