Skip to content

BippinShekar/askr

Repository files navigation

askr

Autonomous session orchestration for Claude Code. Built for developers who ship with Claude.

Three problems. One tool.

  1. Session exhaustion — Claude hits context or quota limits mid-task. Work stops. Recovery is manual.
  2. Team drift — your co-founder doesn't know what you built last night. You explain it again. On Slack. Like animals.
  3. Implementation holes — Claude sounds confident, you approve the approach, an hour later you're reverting because it conflicted with something already built.

Askr fixes all three. It monitors your sessions, checkpoints before Claude degrades, resumes automatically, keeps project state in git so both developers always start informed, and catches architectural mistakes before the first file is touched.

Claude may stop. Work must not. And what it builds must be right.


What's Shipped

Session Orchestration (Phase 2 ✅)

Askr runs a background daemon that watches your Claude Code session via the JSONL transcript file. Two triggers:

Trigger A: Context near compaction (~90%)

Context window approaching limit
→ Askr intercepts before lossy auto-compact fires
→ Writes handover.md with full session state
→ Commits + pushes to git
→ Stops session, starts new one immediately
→ Claude continues from exact next step

Trigger B: Quota window nearly exhausted

5-hour usage window running low
→ Askr checkpoints + commits
→ Stops session
→ Waits for exact reset time (derived from JSONL first-entry + 5h)
→ Auto-resumes after reset
→ Claude continues from exact next step

Project State (Phase 1 ✅)

Structured markdown files committed to git on every checkpoint. Both developers pull this state at session start. Claude reads it automatically.

File What it tracks
handover_<dev>.md Last session's objective, next step, files changed
current_task_<dev>.md Last 5 user prompts with timestamps
decisions.jsonl Append-only timestamped decision log (union-merge safe)
implementation_<dev>.jsonl Per-developer action log — file edits + commands, typed, timestamped, with session ID
architecture.md System overview, modules, patterns
goals.jsonl Today's goals, backlog, done — tracked across sessions (union-merge safe)

Goals (auto-managed)

Goals can be set manually or inferred automatically:

  • At session start: if today has no goals, Haiku reads your last handover and suggests 1-2 goals, added automatically
  • During session: Claude sees your goals in context and works toward them
  • At session end: Haiku infers which goals were completed based on what was actually built

Always-On Daemon + caffeinate

askr init installs a launchd service (com.askr.daemon) that starts at login and runs silently in the background. No askr launch needed.

What it does automatically:

  • Detects when a Claude Code session starts (by watching session_stats.json freshness)
  • Starts caffeinate -i — prevents system idle sleep, allows display to dim
  • Monitors context and quota thresholds every 30s
  • Fires Trigger A or B when thresholds are crossed
  • Releases caffeinate when the session ends or goes idle

Battery note: caffeinate -i cannot prevent sleep when the lid is closed on battery. Plug in for overnight runs. Askr warns you at askr init and when a session starts on battery.

askr launch           # show daemon status + current session
askr launch --stop    # kill daemon manually (restarts at next login)
askr launch --restart # force restart now

To disable permanently:

launchctl unload ~/Library/LaunchAgents/com.askr.daemon.plist

IDE Status Bar

Live context usage shown in Cursor / VS Code bottom status bar:

askr 45% ↺3h42m          ← normal (green)
askr 76% ↺2h10m          ← high usage (amber)
askr 88% ↺1h30m !        ← near limit (red)
askr 93% ↺0h55m ⚠        ← checkpoint imminent (bright red)
askr 67% ↺1h20m …        ← stale, no active session (grey)

Hover shows: current chat context (tokens used / 200k), quota reset countdown, and what each number means.

The ask CLI

During quota resets, ask fills dead time with grounded answers from your codebase:

ask "cto: best way to structure the auth layer?"
ask "debug: getting a 401 on every login attempt"
ask "quick: what does buildContextInjection return?"

Fast (~$0.001/query), grounded in your codebase snapshot, works from any directory.

Notifications + Morning Report (Phase 3 ✅)

Discord webhook notifications for checkpoints, session resumes, and goal completions — see Discord Notifications below for setup. askr report sends a PNG morning report card (sessions run, active time, goals completed) and prints a summary to stdout.

Implementation Guard (Phase 3.5 — partial)

  • Blocking path (real, running): pre_tool_use.py runs a synchronous check before significant Write/Edit/MultiEdit calls — first new file, 3rd file edit in a session, or an edit to a file flagged as a shared interface in architecture.md. On a real architectural issue it blocks the tool call, sends a Discord alert, and appends to askr_state/guard_log.md, forcing Claude to self-correct before the write goes through.
  • Non-blocking IDE popup: not wired up. guard_runner.py writes a guard_warning entry meant for the IDE status bar to render as a soft warning, but nothing invokes it — it's not in HOOK_MAP (askr/cli/askr.py), not in .claude/settings.json, not spawned as a subprocess anywhere. It's dead code today. The extension itself isn't the blocker, though: it has a generic fallback that renders any unrecognized notification type as a plain info toast, so a guard_warning payload would still surface something if it were ever emitted — just not a purpose-built guard-styled popup with its own formatting. Only the blocking path above is currently visible to a developer.

Install

Homebrew

# one-liner (tap + install in one shot)
brew install BippinShekar/askr/askr

# or tap once, then install/upgrade by name from then on
brew tap BippinShekar/askr
brew install askr

Bare brew install askr (no tap) only works for formulas in homebrew-core, which requires a notability review Askr doesn't qualify for yet. One of the two commands above is the real install path for now.

From source

git clone https://github.com/BippinShekar/askr.git
cd askr
python3 -m venv venv
source venv/bin/activate
pip install -r requirements.txt
cp .env.example .env
# add ANTHROPIC_API_KEY to .env
bash install.sh
source ~/.zshrc

Setup (per project)

cd ~/your-project
ask init       # index codebase — generates snapshot for architecture.md
askr init      # configure for this project, install hooks + IDE extension

askr init does in one step:

  • Saves developer name + project path
  • Generates askr_state/architecture.md from codebase snapshot (Haiku)
  • Creates all state files from templates
  • Installs Claude Code hooks (SessionStart, UserPromptSubmit, PostToolUse, Stop, PreCompact)
  • Wires the statusLine command into .claude/settings.json
  • Installs the status bar extension to ~/.cursor/extensions/ and ~/.vscode/extensions/

Reload your IDE window after askr init to activate the status bar.


Discord Notifications (optional)

Askr can send checkpoints, goal completions, and session events to a Discord channel. Solo developers and teams both supported.

Solo setup (personal server)

  1. Create a Discord server (e.g. "askr notifications")
  2. Go to Server Settings → Integrations → Webhooks → New Webhook
  3. Name it, select the channel (e.g. #general), click Copy Webhook URL
  4. Add to your .env:
    ASKR_DISCORD_WEBHOOK=https://discord.com/api/webhooks/...
    

Team setup (shared channel)

  1. In your shared Discord server, create a #dev-activity channel
  2. Go to Channel Settings → Integrations → Webhooks → New Webhook
  3. Each developer adds that same webhook URL to their own .env

All team members' session events (checkpoints, goals completed, session resumes) post to the shared channel — a passive async standup feed. No duplicate notifications: each developer's askr instance posts its own events only.

What gets posted

Event Message
Checkpoint (context/quota hit) Trigger type, developer, timestamp
Session resumed Reason + next goal
Goal completed Goal text
Session ended Goals completed + files changed (standup replacement)
Claude notification (HITL) Forwarded overnight so you don't miss it
askr report Full daily summary on demand

Commands

# Session
askr init                   # set up in this project
askr status                 # show current state + session context %
askr status --line          # one-line output for scripts / terminal

# Daemon (always-on via launchd — installed by askr init)
askr launch                 # show daemon status + current session
askr launch --stop          # kill daemon (restarts at next login)
askr launch --restart       # force restart now

# Goals
askr goals                  # show today, backlog, done
askr goal add "..."         # add a goal for today (just records it)
askr goal add "..." --backlog   # add to backlog
askr goal add "..." --launch    # add for today AND start an autonomous Claude session on it now
askr goal done "..."        # mark a goal complete

# Notifications
askr report                 # send daily report to Discord (sessions, time saved, next goal)

# Codebase Q&A
ask "cto: ..."              # architectural decision
ask "ceo: ..."              # product/business framing
ask "debug: ..."            # bug fix (includes recent git diff)
ask "deep: ..."             # thorough explanation
ask "quick: ..."            # one-liner answer
ask "web: ..."              # live web search
ask init                    # index codebase
ask snap                    # force snapshot rebuild
ask log                     # show usage + cost this week

Session Lifecycle

Developer opens Claude Code
         ↓
SessionStart hook fires
  → git pull (get teammate's latest state)
  → inject handover + goals into context
  → if no goals today: Haiku suggests from last handover
         ↓
Developer works with Claude
  → PostToolUse hook: appends to implementation_<dev>.jsonl
                      writes session_stats.json for status bar
  → UserPromptSubmit hook: records last 5 prompts to current_task.md
         ↓
Daemon polls session_stats.json every 30s
  → context ≥ 90%  → Trigger A
  → quota window ≤ 30min → Trigger B
         ↓
On trigger: safe_pause check → checkpoint → git commit+push
  Trigger A: start new Claude immediately
  Trigger B: sleep until reset, then start new Claude
         ↓
New session starts
  → SessionStart fires again
  → Claude reads handover, continues from next step

Project Structure

askr/                        # Python package
  cli/
    ask.py                   # ask command — codebase Q&A
    askr.py                  # askr command — session orchestration
  hooks/                     # Claude Code hook scripts
    session_start.py         # git pull + context injection + goal suggestion
    user_prompt_submit.py    # strip IDE tags, record last 5 prompts
    post_tool_use.py         # track activity + write session stats
    stop.py                  # generate handover, commit, push
    pre_compact.py           # emergency checkpoint fallback
    notification.py          # HITL forwarding — logs + Discord alert on WARNING/ERROR
  session/                   # session orchestration
    monitor.py               # read JSONL → context%, session start time
    forecast.py              # context label (ok/high/near limit/checkpoint)
    checkpoint.py            # handover + git commit+push, shared by stop + lifecycle
    lifecycle.py             # background daemon: poll, trigger, kill, resume
    safe_pause.py            # check git clean, no tests running, no active writes
  state/                     # state file management
    config.py                # developer name, project path
    writer.py                # write/append to all state files
    reader.py                # build context injection for Claude
    goals.py                 # goals CRUD + Haiku inference
    templates/               # markdown templates for state files
  qa/                        # ask CLI pipeline
    pipeline.py, snapshot.py, graph.py, context_loader.py, modes.py
  clients/
    claude.py                # Anthropic SDK client
    openai.py                # OpenAI fallback
  ide/
    vscode-extension/        # status bar extension (Cursor + VS Code)
      extension.js
      package.json
  utils/
    config.py, display.py, logger.py, env.py

askr_state/                  # project state data (committed to git)
  handover_<dev>.md
  current_task_<dev>.md
  decisions.jsonl
  implementation_<dev>.jsonl
  architecture.md
  blockers.md
  goals.jsonl

Coming Next

Implementation Guard — non-blocking warnings (known gap)

  • guard_runner.py's guard_warning notification path is dead code — never invoked from pre_tool_use.py, HOOK_MAP, or .claude/settings.json
  • The extension's generic fallback would render it as a plain info toast if it were ever emitted, but a dedicated guard_warning (and task_approval_pending) case with its own formatting is still worth adding
  • Until guard_runner.py is wired up, non-blocking guard warnings have no visible surface — only the blocking guard path (Phase 3.5, shipped) alerts a developer today

Phase 4 — Public Launch

  • Homebrew install shipped (see Install) — v0.1.0 tagged, BippinShekar/homebrew-askr tap live, real pinned sha256/url
  • Polished README with GIF of status bar + morning report
  • Twitter/X launch thread

Limitations

  • macOS only (uses pbcopy for clipboard, lsof for write detection)
  • Quota reset time derived from JSONL session start + 5h (accurate but indirect)
  • IDE status bar requires Cursor or VS Code; reload window after askr init
  • Autonomous overnight mode requires askr launch to be running

Building in Public

Following development on Twitter/X — real usage, real numbers, real problems.

Contributions welcome. Open an issue or PR.

About

Context-aware reasoning layer over your codebase with enforced efficiency and structured outputs.

Resources

License

Stars

0 stars

Watchers

0 watching

Forks

Packages

 
 
 

Contributors