{"id":49101092,"url":"https://github.com/arndvs/ctrlshft","last_synced_at":"2026-04-20T23:33:51.099Z","repository":{"id":347182837,"uuid":"1193055869","full_name":"arndvs/ctrlshft","owner":"arndvs","description":"The system your AI agents are missing — synced instructions, workflow skills, hardened secrets, and autonomous loops across every machine.","archived":false,"fork":false,"pushed_at":"2026-04-20T14:24:07.000Z","size":1484,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-04-20T15:34:58.563Z","etag":null,"topics":["ai-agents","claude-code","cross-platform","developer-tools","dotfiles","github-copilot","instructions","productivity","prompt-engineering","secrets-management","vscode"],"latest_commit_sha":null,"homepage":"https://ctrlshft.dev","language":"HTML","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":"kangarko/ai-files","license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/arndvs.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-03-26T20:38:33.000Z","updated_at":"2026-04-20T13:28:17.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/arndvs/ctrlshft","commit_stats":null,"previous_names":["arndvs/dotfiles","arndvs/ctrl","arndvs/ctrlshft"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/arndvs/ctrlshft","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/arndvs%2Fctrlshft","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/arndvs%2Fctrlshft/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/arndvs%2Fctrlshft/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/arndvs%2Fctrlshft/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/arndvs","download_url":"https://codeload.github.com/arndvs/ctrlshft/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/arndvs%2Fctrlshft/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32070656,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-20T21:26:33.338Z","status":"ssl_error","status_checked_at":"2026-04-20T21:26:22.081Z","response_time":94,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["ai-agents","claude-code","cross-platform","developer-tools","dotfiles","github-copilot","instructions","productivity","prompt-engineering","secrets-management","vscode"],"created_at":"2026-04-20T23:33:50.437Z","updated_at":"2026-04-20T23:33:51.090Z","avatar_url":"https://github.com/arndvs.png","language":"HTML","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cp align=\"center\"\u003e\n  \u003cimg src=\"site/assets/ctrl-shift-logo.jpg\" alt=\"ctrl+shft logo\" style=\"width: 100%; max-width: 862px; height: auto;\" /\u003e\n\u003c/p\u003e\n\n# ctrl+shft\n\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)\n\\*\\*\n\n\u003e Dotfiles for AI coding agents. One repo syncs instructions, skills, secrets, and autonomous loops across every machine.\n\u003e\n\u003e **ctrl** is the structure — instructions, skills, rules, secrets, context. **shft** is the autonomous loop — it picks issues, implements, commits, repeats.\n\nEvery developer using Claude Code or Copilot hits the same walls. Context degrades mid-task — the agent repeats itself, compaction loses nuance, quality drops. Instructions drift between your laptop and VPS. Secrets leak into agent context. Irrelevant rules load for every project regardless of stack.\n\nctrl+shft fixes all four. Clone it once, `bootstrap.sh` symlinks your instructions, skills, agents, and rules into `~/.claude/`, and `git pull` updates every machine. `detect-context.sh` loads only the rules that match your current stack. Secrets split into three tiers — config the agent can see, credentials that exist only inside a child process and vanish when it exits (`run-with-secrets.sh`), and AFK iteration tokens (short-lived GitHub App installation tokens) minted per loop. When context gets high, the agent persists its plan to `working/` so a fresh conversation continues exactly where the old one left off.\n\n**Source of truth:** `~/dotfiles/` is canonical. `~/.claude/`, `~/.copilot/`, and `~/.agents/` are consumer targets populated from dotfiles (symlinked where possible, Windows fallback copy when needed). Make all edits in `~/dotfiles/` only.\n\n```bash\ngit clone https://github.com/arndvs/ctrlshft.git ~/dotfiles\nbash ~/dotfiles/bin/bootstrap.sh\n```\n\nBootstrap is idempotent and cross-platform. It symlinks `~/.claude/CLAUDE.md`, `~/.claude/skills/`, `~/.claude/agents/`, and `~/.claude/rules/`, wires shell integration into `~/.bashrc`/`~/.zshrc`, creates `secrets/` from templates, installs Python dependencies from `skills/_local/requirements.txt` into `secrets/.venv` (including `PyJWT` for AFK GitHub App token minting), and adds supply chain protection to `~/.npmrc` and `uv.toml`. Full details in the [Installation](#installation) section.\n\n---\n\n## The pipeline\n\n```\n/grill-me       → Interrogate you about a feature until shared understanding\n/write-a-prd    → Explore codebase, interview, write PRD, submit as GitHub issue\n/architect      → Plan implementation — vertical slices, dependency graphs, acceptance criteria\n/prd-to-issues  → Break the PRD into vertical slices → GitHub issues (AFK vs HITL labeled)\n/do-work        → Understand → Plan → Implement → Validate → Commit (loops)\nshft            → Pick issues from the backlog, implement in a Docker sandbox, commit, repeat\n```\n\n```mermaid\ngraph TD\n    A[Human Intent] --\u003e B[\"/grill-me — interrogation\"]\n    B --\u003e C[\"/write-a-prd — PRD → GitHub Issue\"]\n    C --\u003e AR[\"/architect — vertical slices, dependency graphs\"]\n    AR --\u003e D[\"/prd-to-issues — slices → GitHub Issues\"]\n    D --\u003e E[\"/do-work — Understand → Plan → Implement → Validate → Commit\"]\n    E --\u003e|loop| E\n    E --\u003e|\"context high → persist plan to working/\"| H[\"Fresh conversation picks up @working/plan.md\"]\n    H --\u003e E\n    E --\u003e F[\"shft — AFK loop consuming GitHub issues backlog\"]\n    F --\u003e|loop| F\n    F --\u003e G[\"Human QA + /improve-architecture\"]\n    G --\u003e|new issues| D\n```\n\nUse any skill individually or chain them. The planning pipeline (grill-me → write-a-prd → architect → prd-to-issues → do-work) hands off between stages.\n\n---\n\n## How it works\n\n### One repo, every machine\n\nClone to `~/dotfiles` on your laptop, your VPS, anywhere. `git pull` updates both. That's it.\n\nYou edit `CLAUDE.base.md` (tracked in git). `bootstrap.sh` generates `CLAUDE.md` from it by appending `@`-references to any local instruction files in `instructions/_local/`. The generated file is symlinked to `~/.claude/` and read by Claude Code at runtime.\n\n### Progressive context loading\n\n`detect-context.sh` scans your working directory and exports `ACTIVE_CONTEXTS`. A Next.js project loads Next.js rules. A PHP project loads PHP rules. Nothing leaks between stacks.\n\n```\nVS Code opens a project\n  ↓\nCLAUDE.md → global.instructions.md (always loaded)\n  ↓\ndetect-context.sh → ACTIVE_CONTEXTS=general,nextjs,node,typescript,sanity,prisma\n  ↓\nloads matching instructions/*.md\n  ↓\nrules/ scoped by paths: frontmatter — load only when matching files are touched\n  ↓\nagents/ available as subagent personas — isolated context, read-only tools\n  ↓\nskills/ auto-discovered — workflow + your personal _local/ skills\n```\n\nOne setting enables the chain: `\"chat.instructionsFilesLocations\": {\"~/dotfiles\": true}` — included in `settings.json`, applied by `sync-settings.sh`.\n\n### Private skills and instructions\n\n`skills/_local/` and `instructions/_local/` are gitignored. Drop private or business-specific files there — auto-discovered alongside the public ones, never leave your machine.\n\n```\nskills/\n├── do-work/                 ← public, tracked\n├── systematic-debugging/    ← public, tracked\n└── _local/                  ← GITIGNORED — yours alone\n    └── your-skill/SKILL.md\n```\n\n### Subagent personas\n\n`agents/` defines specialized subagents with their own system prompts, tool restrictions, and model preferences. Each runs in an isolated context window — exploration stays out of your main conversation.\n\nAgents come in **model variants** — choose based on task complexity and cost sensitivity:\n\n| Agent                | Model  | When to use                                           |\n| -------------------- | ------ | ----------------------------------------------------- |\n| `researcher`         | Sonnet | Default. General codebase exploration                 |\n| `researcher-opus`    | Opus   | Complex cross-system analysis, architecture decisions |\n| `researcher-haiku`   | Haiku  | Quick lookups, bulk scanning, simple patterns         |\n| `code-reviewer`      | Sonnet | Default. Standard PR reviews, bug checks              |\n| `code-reviewer-opus` | Opus   | Security-critical code, pre-deploy, complex changes   |\n| `security-auditor`   | Sonnet | OWASP Top 10, secrets exposure, config hardening      |\n\nAll agents use read-only tools (Read, Grep, Glob, Bash) and `memory: user` for persistent cross-project learnings. Add your own: `agents/your-agent.md` — auto-discovered. See [agents/README.md](agents/README.md) for the full model selection guide.\n\n\u003e **Platform limitation:** Runtime model injection is not supported. Neither `search_subagent` nor `runSubagent` accepts a model parameter per-call. Model selection is static — set via `model:` frontmatter in agent files, or `chat.exploreAgent.defaultModel` for VS Code sub-agents. Create variant agent files to benchmark different models on the same task.\n\n### Path-scoped rules\n\n`rules/` contains convention-enforcement files that load only when the agent touches matching files. Each rule uses `paths:` YAML frontmatter to scope itself.\n\n| Rule                   | Scoped to                                       |\n| ---------------------- | ----------------------------------------------- |\n| `test-conventions`     | `**/*.test.*`, `**/*.spec.*`, `**/__tests__/**` |\n| `migration-safety`     | `**/migrations/**`, `**/prisma/migrations/**`   |\n| `env-security`         | `**/.env*`, `**/secrets/**`, `**/credentials*`  |\n| `terminal-workarounds` | Terminal sessions                               |\n\nRules without `paths:` load every session. Add your own: `rules/your-rule.md` — auto-discovered.\n\n### Hardened secrets\n\nThree tiers. Agents see config, never credentials — and AFK loops use AFK iteration tokens instead of long-lived auth tokens.\n\n| File                   | In shell? | Agent-visible? | Contains                     |\n| ---------------------- | --------- | -------------- | ---------------------------- |\n| `secrets/.env.agent`   | Yes       | Yes            | Usernames, hosts, IDs        |\n| `secrets/.env.secrets` | No        | No             | API keys, tokens, passwords  |\n| AFK iteration token    | No        | No             | Minted per loop, expires ~1h |\n\n`run-with-secrets.sh` injects credentials into a child process only — they vanish when it exits. Claude Code deny rules block `env`, `printenv`, `cat secrets/*`, and `echo $*KEY*` at the agent level. Agents can't accidentally inherit what they can't see.\n\n### AFK Docker credential rotation (strong defense)\n\nFor AFK runs, credentials should rotate between Docker iterations:\n\n- Mint an AFK iteration token (short-lived GitHub App installation token) for each loop\n- Inject the token only for that iteration's process\n- Expire naturally (and fail closed on mint failure)\n- Do not allow PAT fallback in AFK mode\n\nThis closes the most common leakage path: one long-lived credential reused across many autonomous runs.\n\n### Exact secure setup after clone\n\nAfter clone + bootstrap, this is the exact secure AFK setup path:\n\n1. Create a GitHub App at `https://github.com/settings/apps/new`.\n   - Name: e.g. `ctrl-shft-bot`\n   - Homepage URL: your own GitHub dotfiles repository URL (e.g. `https://github.com/\u003cyou\u003e/dotfiles`)\n   - Webhook: disable for now (not required for this flow)\n   - Repository permissions (minimum):\n     - Contents: Read \u0026 Write\n     - Issues: Read \u0026 Write\n     - Pull requests: Read \u0026 Write\n     - Workflows: Read \u0026 Write (only if AFK needs to edit `.github/workflows/*`)\n   - Installation target: only your account/org that owns the repo\n2. In the App settings page, click **Generate a private key** and download the `.pem` file.\n3. Install the App on the repo/fork AFK will work on:\n   - Open your app page (e.g. `https://github.com/settings/apps/ctrl-shft-bot`)\n   - Click **Install App**\n   - Choose account/org, then **Only select repositories**, then target repo, then **Install**\n4. Capture your installation ID from the redirect URL after install:\n   - URL format: `https://github.com/settings/installations/\u003cid\u003e`\n   - The numeric trailing segment is `GITHUB_APP_INSTALLATION_ID`\n5. Base64 encode the private key to one line:\n   - Linux / Git Bash: `base64 -w 0 ~/Downloads/your-app-key.pem`\n   - macOS: `base64 \u003c ~/Downloads/your-app-key.pem | tr -d '\\n'`\n   - PowerShell: `[Convert]::ToBase64String([IO.File]::ReadAllBytes(\"$HOME\\\\Downloads\\\\your-app-key.pem\"))`\n6. Fill `~/dotfiles/secrets/.env.secrets` with:\n   - `GITHUB_APP_ID`\n   - `GITHUB_APP_INSTALLATION_ID`\n   - `GITHUB_APP_PRIVATE_KEY_B64`\n7. Run `bash ~/dotfiles/bin/run-with-secrets.sh bash ~/dotfiles/bin/validate-env.sh --afk` and fix any hard-fail messages.\n8. Run token-safe mint verification (prints status/expiry/length, not the raw token):\n\n   ```bash\n   bash ~/dotfiles/bin/verify-github-app-token.sh\n   ```\n\n   Expected shape:\n\n   ```text\n   ================================================================\n   GitHub App Token Smoke Test (safe output)\n   ================================================================\n     ✓ mint_success=yes\n       expires_at=2026-04-14T23:58:47Z\n       token_len=40\n   ================================================================\n   ```\n\n9. Start AFK with one iteration (`shft/afk.sh 1`), then scale iterations once stable.\n\n\u003e **Windows note (important):** On some Windows setups, `python3` resolves to a Microsoft Store alias and fails. AFK scripts now prefer `secrets/.venv` Python automatically. If you hit Python launch/dependency errors, rerun `bash ~/dotfiles/bin/bootstrap.sh` to rebuild the venv and retry.\n\nIf PAT variables are present in AFK mode, treat that as a hard configuration error and remediate before running.\n\nIf `mint_github_app_token.py` reports missing `PyJWT` or `requests`, re-run `bash ~/dotfiles/bin/bootstrap.sh` to refresh `secrets/.venv` packages.\n\nIf a raw token is ever printed to terminal/chat/logs, treat that as an exposure event and rotate immediately:\n\n1. Open `https://github.com/settings/apps/ctrl-shft-bot`\n2. Regenerate (or delete + generate) a new private key\n3. Download new `.pem`\n4. Re-encode: `base64 -w 0 ~/Downloads/your-new-key.pem`\n5. Update `GITHUB_APP_PRIVATE_KEY_B64` in `secrets/.env.secrets`\n6. Re-run the token-safe mint verification command above\n\n---\n\n## Skills\n\nEvery skill's `description` is loaded into the agent's system prompt at session start. The agent reads a skill's full `SKILL.md` when it detects a matching situation. Skills marked ⚡ have broad descriptions that match common task patterns — the agent loads them automatically without you asking. The rest have narrow descriptions and fire only when you invoke them by name or via `/slash-command`.\n\nThe benefit: ⚡ skills act as passive guardrails. You don't remember to say \"use the debugging skill\" — the agent recognizes an error and loads the root-cause-first investigation protocol on its own. Same rigorous process every time, without you thinking about it.\n\n| Skill                     | What it does                                                                                          |\n| ------------------------- | ----------------------------------------------------------------------------------------------------- |\n| `do-work`                 | Detect your stack's feedback loops. Understand → Plan → Implement → Validate → Commit.                |\n| `grill-me`                | Interrogate you about a plan until shared understanding. One question at a time, recommended answers. |\n| `write-a-prd`             | Explore codebase, interview you, sketch module boundaries, write PRD, submit as GitHub issue.         |\n| `prd-to-issues`           | Break a PRD into vertical slices. Label each AFK or HITL. Create GitHub issues with dependencies.     |\n| `architect` ⚡            | Plan implementation — vertical slices, dependency graphs, acceptance criteria.                        |\n| `skill-scaffolder`        | Scaffold new agent skills from production-tested patterns. Interview → architecture → directory.      |\n| `explore` ⚡              | Decompose a topic, spawn parallel sub-agents, synthesize a summary.                                   |\n| `research` ⚡             | Cache expensive exploration into `research.md`. Staleness checks, lifecycle management.               |\n| `codebase-audit` ⚡       | Ruthless code audit — real problems only, grouped by severity. No manufactured issues.                |\n| `improve-architecture` ⚡ | Find shallow-module clusters, spawn parallel design agents, file a GitHub RFC.                        |\n| `tdd`                     | Red-green refactor. Failing test → implement → refactor. Backend only.                                |\n| `systematic-debugging` ⚡ | Root-cause-first — investigate → pattern analysis → hypothesis → fix.                                 |\n| `atomic-commits` ⚡       | Branch-isolated atomic commits. Survey diff, group by seam, commit or ship (push + PR).               |\n| `code-review`             | Focused review of staged or recent changes. Edge cases, logic errors, integration risks.              |\n| `document`                | Write, update, or audit documentation. Accurate, minimal, audience-appropriate.                       |\n| `sanity-best-practices`   | Sanity schema design, GROQ, TypeGen, Visual Editing, Portable Text, framework integrations.           |\n\nAdd your own: `skills/_local/your-skill/SKILL.md` — auto-discovered, gitignored.\n\n---\n\n## Slash Commands\n\nThin launchers in `commands/` that load a skill with your arguments. Type the command in chat — the agent loads the full skill protocol automatically.\n\n| Command     | Loads skill      | What it does                                                         |\n| ----------- | ---------------- | -------------------------------------------------------------------- |\n| `/work`     | `do-work`        | Core execution loop — understand, plan, implement, validate, commit. |\n| `/plan`     | `architect`      | Vertical slices, dependency graphs, acceptance criteria.             |\n| `/audit`    | `codebase-audit` | Ruthless audit — real problems only, grouped by severity.            |\n| `/review`   | `code-review`    | Focused review of staged or recent changes.                          |\n| `/explore`  | `explore`        | Decompose a topic, spawn parallel sub-agents, synthesize.            |\n| `/test`     | `tdd`            | Red-green refactor. Failing test → implement → refactor.             |\n| `/document` | `document`       | Write, update, or audit documentation.                               |\n\nAdd your own: `commands/your-command.md` — auto-discovered. Each file is a prompt template with `$ARGUMENTS` passthrough.\n\n---\n\n## Coding principles\n\nFour behavioral principles baked into `global.instructions.md`, derived from [Andrej Karpathy's observations](https://x.com/karpathy/status/2015883857489522876) on LLM coding pitfalls. These address the most expensive failure modes: building the wrong thing, overengineering, drive-by refactoring, and vague success criteria.\n\n### 1. Think Before Coding\n\n\u003e Don't assume. Don't hide confusion. Surface tradeoffs.\n\nLLMs silently pick an interpretation and run with it. These rules force explicit reasoning:\n\n- **Stop when confused** — Name what's unclear and ask. Never pick an interpretation silently\n- **Present multiple interpretations** — If ambiguity exists, list options and ask which one before implementing\n- **Push back when simpler exists** — If a simpler approach works, say so — even if the user asked for the complex version\n- **State assumptions explicitly** — If uncertain, ask follow-up questions. Think \"What's wrong with this plan?\"\n\n### 2. Simplicity First\n\n\u003e Minimum code that solves the problem. Nothing speculative.\n\nCombat the tendency toward overengineering:\n\n- No features beyond what was asked\n- No abstractions for single-use code\n- No \"flexibility\" or \"configurability\" that wasn't requested\n- No error handling for impossible scenarios\n- If 200 lines could be 50, rewrite it\n\n**The test:** Would a senior engineer say this is overcomplicated? If yes, simplify.\n\n### 3. Surgical Changes\n\n\u003e Touch only what you must. Clean up only your own mess.\n\nWhen editing existing code:\n\n- **Match existing style exactly** — even if you'd write it differently. No formatting, naming, or structural changes outside the task\n- **Don't refactor what isn't broken** — if you notice unrelated problems, mention them — don't fix them\n- **Mention unrelated dead code, don't delete it** — only remove imports/variables/functions that YOUR changes made unused\n- **Don't \"improve\" adjacent code**, comments, or formatting\n\n**The test:** Every changed line should trace directly to the user's request.\n\n### 4. Goal-Driven Execution\n\n\u003e Define success criteria. Loop until verified.\n\nTransform imperative tasks into verifiable goals:\n\n| Instead of...    | Transform to...                                       |\n| ---------------- | ----------------------------------------------------- |\n| \"Add validation\" | \"Write tests for invalid inputs, then make them pass\" |\n| \"Fix the bug\"    | \"Write a test that reproduces it, then make it pass\"  |\n| \"Refactor X\"     | \"Ensure tests pass before and after\"                  |\n\nFor multi-step tasks, state a brief plan with verification at each step. Strong success criteria let the agent loop independently. Weak criteria (\"make it work\") require constant clarification.\n\nctrl extends this with dedicated skills: `tdd` (red-green-refactor), `systematic-debugging` (root-cause-first investigation), and `do-work` (auto-detects feedback loops and validates before committing).\n\n### How to know it's working\n\nThese principles are working if you see:\n\n- **Fewer unnecessary changes in diffs** — only requested changes appear\n- **Fewer rewrites due to overcomplication** — code is simple the first time\n- **Clarifying questions come before implementation** — not after mistakes\n- **Clean, minimal commits** — no drive-by refactoring or \"improvements\"\n\n\u003e **Tradeoff:** These principles bias toward caution over speed. For trivial tasks (typo fixes, obvious one-liners), the agent uses judgment — not every change needs the full rigor.\n\n---\n\n## shft: autonomous agent loop\n\n\u003e `ctrl` is the structure — instructions, skills, rules, secrets, context. `shft` is the autonomous loop — it picks issues, implements, commits, repeats. **ctrl+shft** — you define the rules, shft executes them.\n\nshft is not a framework. It's a bash loop that runs Claude against your GitHub issues backlog — sandboxed in Docker for Away From Keyboard (AFK) mode, direct on host for Human In The Loop (HITL).\n\n### Two modes\n\n| Mode | Script         | Use when                                                      |\n| ---- | -------------- | ------------------------------------------------------------- |\n| HITL | `shft/once.sh` | Learning — runs once while you watch                          |\n| AFK  | `shft/afk.sh`  | Shipping — loops in Docker sandbox with a max iteration guard |\n\nAFK mode: Claude picks a task, implements it, commits, closes the issue, picks the next one. Exits when the backlog is empty (`\u003cpromise\u003eNO MORE TASKS\u003c/promise\u003e`). You review PRs async.\n\n### Task priority order\n\n1. Critical bugfixes — blockers first\n2. Dev infrastructure — tests, types, scripts before features\n3. Tracer bullets — small end-to-end slices that validate approach\n4. Polish and quick wins\n5. Refactors\n\n### Docker sandboxing\n\n`--dangerously-skip-permissions` needs a cage. Docker isolates Claude in a micro-VM. It can run commands, write files, use git — but it can't reach your host filesystem.\n\n```bash\ndocker sandbox run claude .\n```\n\n### Activation checklist\n\n- [ ] Claude Max subscription\n- [ ] Docker Desktop installed\n- [ ] `shft/once.sh`, `shft/afk.sh`, `shft/prompt.md` in place\n- [ ] GitHub App credentials configured in `secrets/.env.secrets` (`GITHUB_APP_ID`, `GITHUB_APP_INSTALLATION_ID`, `GITHUB_APP_PRIVATE_KEY_B64`)\n- [ ] Deny rules validated in sandbox\n- [ ] 5–10 well-formed GitHub issues ready\n- [ ] Start HITL → graduate to AFK (1 iteration) → scale up\n\n---\n\n## What's in the box\n\n```\n~/dotfiles/\n├── CLAUDE.base.md                   ← edit this — bootstrap generates CLAUDE.md from it\n├── CLAUDE.md                        ← GENERATED (gitignored)\n├── global.instructions.md           ← universal rules, always loaded\n├── settings.json                    ← managed VS Code settings\n├── .env.agent.example               ← template for non-sensitive config\n├── .env.citation.example            ← template for citation skill config\n├── .env.secrets.example             ← template for API keys and tokens\n├── instructions/\n│   ├── nextjs.instructions.md\n│   ├── php.instructions.md\n│   ├── sanity.instructions.md\n│   ├── sentry.instructions.md\n│   ├── google-docs.instructions.md\n│   ├── css.instructions.md\n│   ├── ux-prototyping.instructions.md\n│   ├── handoff.instructions.md      ← cross-conversation persistence protocol\n│   └── _local/                      ← GITIGNORED — your private instructions\n├── commands/\n│   ├── audit.md                     /audit → codebase-audit skill\n│   ├── document.md                  /document → document skill\n│   ├── explore.md                   /explore → explore skill\n│   ├── plan.md                      /plan → architect skill\n│   ├── review.md                    /review → code-review skill\n│   ├── test.md                      /test → tdd skill\n│   └── work.md                      /work → do-work skill\n├── agents/\n│   ├── README.md                    model selection guide + agent docs\n│   ├── code-reviewer.md             subagent: bugs, correctness, security (sonnet)\n│   ├── code-reviewer-opus.md        subagent: high-stakes reviews (opus)\n│   ├── researcher.md                subagent: deep codebase exploration (sonnet)\n│   ├── researcher-opus.md           subagent: complex architecture analysis (opus)\n│   ├── researcher-haiku.md          subagent: fast bulk scanning (haiku)\n│   └── security-auditor.md          subagent: OWASP, secrets, config (sonnet)\n├── rules/\n│   ├── test-conventions.md          scoped to **/*.test.*, **/*.spec.*\n│   ├── migration-safety.md          scoped to **/migrations/**\n│   ├── env-security.md              scoped to **/.env*, **/secrets/**\n│   └── terminal-workarounds.md      scoped to terminal sessions\n├── skills/\n│   ├── do-work/\n│   ├── grill-me/\n│   ├── write-a-prd/\n│   ├── prd-to-issues/\n│   ├── architect/\n│   ├── skill-scaffolder/\n│   ├── explore/\n│   ├── research/\n│   ├── codebase-audit/\n│   ├── improve-architecture/\n│   ├── tdd/\n│   ├── systematic-debugging/\n│   ├── atomic-commits/\n│   ├── code-review/\n│   ├── document/\n│   ├── sanity-best-practices/\n│   └── _local/                      ← GITIGNORED — your private skills\n├── shft/\n│   ├── afk.sh                       AFK autonomous loop\n│   ├── once.sh                      HITL single-run\n│   ├── _build_prompt.sh             prompt assembly for shft runs\n│   └── prompt.md                    shared agent prompt\n├── bin/\n│   ├── _lib.sh                      shared shell library\n│   ├── bootstrap.sh                 one-command setup, idempotent\n│   ├── agent-shell.sh               secrets-free shell for agent sessions\n│   ├── sync-settings.sh             deep-merge VS Code settings\n│   ├── load-secrets.sh              sources .env.agent into shell\n│   ├── run-with-secrets.sh          process-scoped secret injection\n│   ├── detect-context.sh            exports ACTIVE_CONTEXTS\n│   ├── validate-env.sh              env + hardening validation\n│   ├── validate-symlinks.sh         verify bootstrap symlinks\n│   ├── mint_github_app_token.py     AFK token minting\n│   └── verify-github-app-token.sh   safe token verification\n├── site/                            ← landing page (ctrlshft.dev)\n│   ├── index.html\n│   ├── CNAME\n│   └── assets/\n├── docs/                            ← architecture decision records\n│   └── adr/\n├── working/                         ← GITIGNORED — cross-conversation plans\n└── secrets/                         ← GITIGNORED\n    ├── .env.agent\n    ├── .env.secrets\n    └── .venv/\n```\n\n\u003cdetails\u003e\n\u003csummary\u003eContext detection signals\u003c/summary\u003e\n\n`detect-context.sh` scans the current directory for these file signatures:\n\n| Signal       | File                                                          | Context        |\n| ------------ | ------------------------------------------------------------- | -------------- |\n| Next.js      | `next.config.{ts,js,mjs}`                                     | `nextjs`       |\n| React Native | `\"react-native\"` in `package.json`                            | `react-native` |\n| React        | `\"react\"` in `package.json` (if not Next/Native)              | `react`        |\n| Node         | `package.json`                                                | `node`         |\n| TypeScript   | `tsconfig.json`                                               | `typescript`   |\n| PHP          | `composer.json`                                               | `php`          |\n| Sanity       | `sanity.config.*`, `sanity.cli.*`                             | `sanity`       |\n| Prisma       | `prisma/schema.prisma`                                        | `prisma`       |\n| Docker       | `Dockerfile`, `docker-compose.yml/.yaml`, `compose.yml/.yaml` | `docker`       |\n| Python       | `requirements.txt`, `pyproject.toml`, `setup.py`, `Pipfile`   | `python`       |\n| Laravel      | `artisan`                                                     | `laravel`      |\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003eKey VS Code settings\u003c/summary\u003e\n\n| Setting                                               | Value                                                | Why                                       |\n| ----------------------------------------------------- | ---------------------------------------------------- | ----------------------------------------- |\n| `chat.instructionsFilesLocations`                     | `{\"~/dotfiles\": true, \".github/instructions\": true}` | Enables instruction/skill discovery chain |\n| `chat.agent.maxRequests`                              | `100000`                                             | Prevents agent from stopping mid-task     |\n| `github.copilot.chat.anthropic.thinking.budgetTokens` | `32000`                                              | Extended thinking for complex reasoning   |\n| `chat.exploreAgent.defaultModel`                      | `Claude Opus 4.6 (copilot)`                          | Model selection for explore subagent      |\n\n\u003c/details\u003e\n\n---\n\n## Installation\n\n\u003e **Before you install:** Bootstrap is mostly idempotent but touches several dotfiles:\n\u003e\n\u003e - **`~/.claude/CLAUDE.md`** — replaced with a symlink (or overwritten on Windows). Back up if you have a custom one.\n\u003e - **`~/.claude/skills/`** — symlinked if absent or a stale link. Existing real directories are left alone (manual merge message shown).\n\u003e - **`~/.claude/agents/`** — symlinked if absent or a stale link. Same behavior as skills/.\n\u003e - **`~/.claude/rules/`** — symlinked if absent or a stale link. Same behavior as skills/.\n\u003e - **`~/.claude/commands/`** — symlinked if absent or a stale link. Slash command wrappers.\n\u003e - **`~/.claude/hooks/`** — symlinked if absent or a stale link. Lifecycle hook scripts.\n\u003e - **`~/.claude/settings.json`** — hook configuration merged (requires jq). Existing settings preserved.\n\u003e - **`~/.bashrc` / `~/.zshrc`** — appends shell integration (load-secrets + context detection). Idempotent on re-runs.\n\u003e - **`~/.npmrc`** — appends `min-release-age=7` for supply chain protection.\n\u003e - **`~/.config/uv/uv.toml`** — adds `exclude-newer` date for supply chain protection.\n\u003e\n\u003e **Not run by bootstrap:** `sync-settings.sh` (VS Code settings merge) is a separate manual step. Run with `--dry-run` first to preview changes.\n\n\u003cdetails\u003e\n\u003csummary\u003eQuick setup (recommended)\u003c/summary\u003e\n\n```bash\ngit clone https://github.com/arndvs/ctrlshft.git ~/dotfiles\nbash ~/dotfiles/bin/bootstrap.sh\n```\n\nBootstrap is idempotent — safe to re-run. It handles:\n\n- Generating `CLAUDE.md` from `CLAUDE.base.md` + your local instruction files\n- Creating `secrets/.env.agent` and `secrets/.env.secrets` from templates\n- Symlinking `~/.claude/CLAUDE.md`, `~/.claude/skills/`, `~/.claude/agents/`, `~/.claude/rules/`, `~/.claude/commands/`, and `~/.claude/hooks/`\n- Merging hook configuration into `~/.claude/settings.json`\n- Creating `skills/_local/` and `instructions/_local/`\n- Wiring `load-secrets.sh` and `detect-context.sh` into `~/.bashrc`\n- Creating the Python venv\n- Installing Python packages from `skills/_local/requirements.txt` into `secrets/.venv` (includes `PyJWT` for AFK token minting)\n\nAfter bootstrap:\n\n```bash\n$EDITOR ~/dotfiles/secrets/.env.agent       # non-sensitive config\n$EDITOR ~/dotfiles/secrets/.env.secrets     # API keys and tokens\nbash ~/dotfiles/bin/sync-settings.sh        # merge VS Code settings\nsource ~/.bashrc\n```\n\n\u003e **Windows:** file symlinks require admin. Bootstrap falls back to copying `CLAUDE.md` and prints upgrade instructions. Directory symlinks work via Developer Mode.\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003eVPS setup\u003c/summary\u003e\n\nSame as local — skip `sync-settings.sh` (VS Code Remote SSH forwards your settings).\n\n```bash\ngit clone https://github.com/arndvs/ctrlshft.git ~/dotfiles\nbash ~/dotfiles/bin/bootstrap.sh\n$EDITOR ~/dotfiles/secrets/.env.agent\n$EDITOR ~/dotfiles/secrets/.env.secrets\nsource ~/.bashrc\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003eManual setup\u003c/summary\u003e\n\n```bash\n# 1. Clone\ngit clone https://github.com/arndvs/ctrlshft.git ~/dotfiles\n\n# 2. Generate CLAUDE.md and symlink\nbash ~/dotfiles/bin/bootstrap.sh   # or manually:\nmkdir -p ~/.claude\nln -sf ~/dotfiles/CLAUDE.md ~/.claude/CLAUDE.md\nln -sf ~/dotfiles/skills ~/.claude/skills\nln -sf ~/dotfiles/agents ~/.claude/agents\nln -sf ~/dotfiles/rules ~/.claude/rules\nln -sf ~/dotfiles/commands ~/.claude/commands\nln -sf ~/dotfiles/hooks ~/.claude/hooks\n\n# 3. Secrets\ncp ~/dotfiles/.env.agent.example ~/dotfiles/secrets/.env.agent\ncp ~/dotfiles/.env.secrets.example ~/dotfiles/secrets/.env.secrets\n\n# 4. Shell integration — add to ~/.bashrc\n[[ -f ~/dotfiles/bin/load-secrets.sh ]] \u0026\u0026 source ~/dotfiles/bin/load-secrets.sh\n_load_context() { [[ -f ~/dotfiles/bin/detect-context.sh ]] \u0026\u0026 source ~/dotfiles/bin/detect-context.sh \u003e /dev/null 2\u003e\u00261; }\ncd() { builtin cd \"$@\" \u0026\u0026 _load_context; }\n_load_context\n\n# 5. VS Code settings\nbash ~/dotfiles/bin/sync-settings.sh\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003eWhat bootstrap touches\u003c/summary\u003e\n\n\u003e Bootstrap is mostly idempotent. Here's everything it modifies:\n\n| File                     | Change                                                                              |\n| ------------------------ | ----------------------------------------------------------------------------------- |\n| `~/.claude/CLAUDE.md`    | Symlinked → `~/dotfiles/CLAUDE.md` (or copied on Windows without admin)             |\n| `~/.claude/skills/`      | Linked to `~/dotfiles/skills/` (or replaced with verified fallback copy on Windows) |\n| `~/.claude/agents/`      | Linked to `~/dotfiles/agents/` (or replaced with verified fallback copy on Windows) |\n| `~/.claude/rules/`       | Linked to `~/dotfiles/rules/` (or replaced with verified fallback copy on Windows)  |\n| `~/.copilot/skills/`     | Linked to `~/dotfiles/skills/` (or replaced with verified fallback copy on Windows) |\n| `~/.agents/skills/`      | Linked to `~/dotfiles/skills/` (or replaced with verified fallback copy on Windows) |\n| `~/.bashrc` / `~/.zshrc` | Appends `load-secrets.sh` + `detect-context.sh` integration (idempotent)            |\n| `~/.npmrc`               | Appends `min-release-age=7` (supply chain protection)                               |\n| `~/.config/uv/uv.toml`   | Adds `exclude-newer` date (supply chain protection)                                 |\n| `secrets/.env.agent`     | Created from `.env.agent.example` if missing                                        |\n| `secrets/.env.secrets`   | Created from `.env.secrets.example` if missing                                      |\n| `secrets/.venv/`         | Python venv created for local skill packages                                        |\n\n**Not run by bootstrap:** `sync-settings.sh` (VS Code settings merge) is manual. Run with `--dry-run` first.\n\n\u003c/details\u003e\n\n---\n\n## Customization\n\n| Want to...                | Do this                                                                                                                                     |\n| ------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------- |\n| Add a new stack           | Create `instructions/yourstack.instructions.md`, add detection to `detect-context.sh`, reference in `CLAUDE.base.md`, re-run `bootstrap.sh` |\n| Add a public skill        | Create `skills/your-skill/SKILL.md` — auto-discovered                                                                                       |\n| Add a private skill       | Create `skills/_local/your-skill/SKILL.md` — auto-discovered, gitignored                                                                    |\n| Add a private instruction | Create `instructions/_local/your-topic.instructions.md`, re-run `bootstrap.sh`                                                              |\n| Add an agent              | Create `agents/your-agent.md` with YAML frontmatter (`name`, `description`, `tools`, `model`) — auto-discovered                             |\n| Add a rule                | Create `rules/your-rule.md` with optional `paths:` frontmatter for file-glob scoping — auto-discovered                                      |\n| Add a command             | Create `commands/your-cmd.md` — thin wrapper that loads a skill with `$ARGUMENTS` passthrough                                               |\n| Add a hook                | Create `hooks/your-hook.sh`, add entry to `hooks/settings-hooks.json`, re-run `bootstrap.sh`                                                |\n| Add config                | Add key to `.env.agent.example`, value to `secrets/.env.agent`                                                                              |\n| Add a secret              | Add key to `.env.secrets.example`, value to `secrets/.env.secrets`                                                                          |\n\n## Updating\n\n```bash\ncd ~/dotfiles \u0026\u0026 git pull\nbash ~/dotfiles/bin/bootstrap.sh        # re-validates, fixes stale symlinks\nbash ~/dotfiles/bin/sync-settings.sh    # local only — skip on VPS\nsource ~/.bashrc\n```\n\n---\n\n## Observability \u0026 Benchmarking (Roadmap)\n\n\u003e Status: **planned** — see [working/observability-benchmarking-plan.md](working/observability-benchmarking-plan.md) for the full implementation plan.\n\nctrl+shft currently operates blind — no token tracking, no cost data, no accuracy metrics. To prove the system as a proof of concept, stakeholders need hard numbers. This roadmap addresses the full observability gap.\n\n### What's available today\n\n| Capability              | Status              | Notes                                                                          |\n| ----------------------- | ------------------- | ------------------------------------------------------------------------------ |\n| OpenTelemetry (VS Code) | Available, disabled | `otel.enabled` and `otel.captureContent` in settings.json — 2 settings to flip |\n| Agent debug logs        | Enabled             | `agentDebugLog.fileLogging.enabled: true` — raw Copilot agent logs to disk     |\n| Model attribution       | Static only         | Agent files declare `model:` in frontmatter. No runtime tracking               |\n| Token/cost tracking     | Not built           | shft deletes raw Claude output after each iteration                            |\n| Accuracy tracking       | Not built           | No scoring, no proxy signals, no trend data                                    |\n| Dashboard               | Not built           | docs/ has Next.js scaffolding ready for a `/telemetry` route                   |\n\n### What's planned\n\n| Slice                  | Type     | What it does                                                                                                                        |\n| ---------------------- | -------- | ----------------------------------------------------------------------------------------------------------------------------------- |\n| shft Telemetry Wrapper | AFK      | Instrument `afk.sh`/`once.sh` with JSONL logging. Persist raw Claude output. Extract token counts and model info from `stream-json` |\n| Cost Calculator        | AFK      | Shell script reads JSONL, applies per-model pricing, outputs markdown cost reports                                                  |\n| Model Variant Agents   | **Done** | Opus/Haiku variants of researcher and code-reviewer for benchmarking                                                                |\n| CI Telemetry Reports   | AFK      | GitHub Actions daily reports + README badge for cost and accuracy                                                                   |\n| Enable OTEL            | HITL     | Turn on VS Code's built-in OpenTelemetry, document what it actually emits                                                           |\n| Accuracy Framework     | HITL     | Human scoring UX + automated proxy signals (test pass/fail, reverts, re-opened issues)                                              |\n| Telemetry Dashboard    | HITL     | Next.js dashboard in docs/ — cost, tokens, model distribution, accuracy, hallucination rate                                         |\n\n### Key constraints\n\n- **Sub-agent model injection is not possible at runtime.** Neither `search_subagent` nor `runSubagent` accepts a model parameter. Workaround: model-variant agent files.\n- **Hallucination detection requires human scoring.** Automated proxy signals (test failures, reverts) augment but cannot replace human judgment.\n- **OTEL schema is undocumented.** Need to enable it and inspect raw spans before building on it.\n\n---\n\n## Troubleshooting\n\n\u003cdetails\u003e\n\u003csummary\u003eCommon issues\u003c/summary\u003e\n\n**Instructions not loading in Copilot Chat**\n\n- `readlink ~/.claude/CLAUDE.md` — should point to `~/dotfiles/CLAUDE.md`\n- If not a symlink, re-run `bash ~/dotfiles/bin/bootstrap.sh`\n- Verify `chat.instructionsFilesLocations` has `\"~/dotfiles\": true`\n\n**`secrets/.env.agent not found` on shell startup**\n\n- `cp ~/dotfiles/.env.agent.example ~/dotfiles/secrets/.env.agent`\n- Fill it in: `$EDITOR ~/dotfiles/secrets/.env.agent`\n\n**`sync-settings.sh` fails on VPS**\n\n- Expected. VS Code Remote SSH forwards local settings — don't run sync on VPS.\n\n**`ACTIVE_CONTEXTS` empty**\n\n- `grep \"detect-context\" ~/.bashrc` — if missing, re-run bootstrap\n- Detection runs on `cd` — navigate into a project first\n\n**Python venv broken**\n\n- `rm -rf ~/dotfiles/secrets/.venv \u0026\u0026 bash ~/dotfiles/bin/bootstrap.sh`\n\n**`mint_github_app_token.py` fails with installation error (wrong ID/path mismatch)**\n\n- Exact error string:\n  - `[mint-github-app-token] GitHub API error while requesting installation token (status=404). Check app id, installation id, key format, and clock skew.`\n- Most common causes:\n  - `GITHUB_APP_INSTALLATION_ID` is wrong\n  - App is not installed on the target repo/account\n  - App ID / key pair does not match the installed app\n- Fix flow:\n  - Reopen app settings → Install App → target repo\n  - Recopy installation ID from `https://github.com/settings/installations/\u003cid\u003e`\n  - Re-run token-safe verification:\n\n    ```bash\n    bash ~/dotfiles/bin/verify-github-app-token.sh\n    ```\n\n\u003c/details\u003e\n\n---\n\n## Prerequisites\n\n- [VS Code](https://code.visualstudio.com/) (stable or Insiders)\n- [GitHub Copilot](https://github.com/features/copilot) (optional — ctrl works with Claude Code alone)\n- Git Bash (Windows) or bash (Linux/macOS)\n- Python 3.10+\n- [`jq`](https://jqlang.github.io/jq/) — JSON processor (required by `shft/afk.sh` token parsing)\n  - Windows: `winget install jqlang.jq` or `choco install jq`\n  - macOS: `brew install jq`\n  - Linux: `sudo apt install jq`\n- [`srt`](https://github.com/anthropic-experimental/sandbox-runtime) — Anthropic Sandbox Runtime (used by `shft/afk.sh`)\n  - Install: `npm install -g @anthropic-ai/sandbox-runtime`\n- [Docker Desktop](https://www.docker.com/products/docker-desktop/) (for shft)\n\n---\n\n\u003e **Naming:** The GitHub repo is `arndvs/ctrlshft` but the on-disk path is `~/dotfiles` — hardcoded across 40+ references. Clone it to `~/dotfiles` and leave it there.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Farndvs%2Fctrlshft","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Farndvs%2Fctrlshft","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Farndvs%2Fctrlshft/lists"}