getting started
01 How to use
One command installs everything into ~/.wind — no clone required.
curl -fsSL https://raw.githubusercontent.com/abhijitbansal/claude-skills/main/tools/second-wind/install.sh | shwind init — an interactive wizard scans for your git repos (the scanned roots are saved as scan_roots so you can add more later), lets you pick which ones wind should manage, and choose a global permission preset. Then it offers one choice: configure each repo individually, or apply the global preset + defaults to every selected repo with no per-repo click-through. The presets include auto (--permission-mode bypassPermissions) — accept everything, no prompts — which as of v2.1 is the shipped default for a fresh config (same risk class as --dangerously-skip-permissions; pick acceptEdits/plan/default to reduce autonomy). Use --defaults for the old non-interactive starter file.
wind prompt <repo> — optional: author or edit a repo's first prompt in $EDITOR. Prompt files live at ~/.wind/prompts/<repo>.md by convention; wind seeds the file and wires prompt_file into your config. (One-liners can instead live inline as a repo's prompt string.)
wind add <path> — bring a new git repo under management without re-running init: it appends a {name, path} entry that inherits the global permission preset, launches that repo's tmux session immediately, and refreshes the watcher so the new session is auto-resumed. It writes {name, path} only (no claude_args/agent/prompt from the CLI).
wind up — starts one tmux session per repo, launches the agent in each, sends each repo's initial prompt, and auto-spawns the watcher in its own detached <prefix>-watcher tmux session so it survives closed terminals (one watcher per machine; on macOS it self-caffeinates to keep the machine awake). Pass --no-watch to skip it; run wind watch yourself in the foreground, or wind watch --detach to spawn the detached session by hand. wind down reaps the watcher with the rest.
Check in whenever you like — wind status shows per-session state and the next reset time; tmux attach -t wind-<repo> watches a session live (detach with Ctrl-b d).
wind down — kills all wind sessions when you're finished.
Watch it live
wind dash opens a live dashboard in your browser at http://127.0.0.1:8787. One card per session: state pill, reset countdown, last 30 lines of the pane, all in full color. Click a card to expand it into a full-height modal with a large colorized scrollback and a roomy send box — handy on a small screen for reading a session or answering a question. Actions: resume all, send a message to any session, kill a session, or hit + add repo to pull in a scanned-but-unmanaged repo (found under your persisted scan_roots) and launch it live. Localhost-only; every action — and the modal's larger scrollback fetch — requires a per-run token so other sites can't reach it. Use --port to change the port, --no-browser to skip auto-open.
under the hood
02 How it works
A watcher process polls every tmux pane, keeps a single account-level reset clock, and sweeps a resume message into every paused session after the limit lifts.
Architecture
The 5-hour limit is account-level: every session pauses and resets together, so one watcher and one clock cover them all.
The watch loop
↺ back to running
Limit detection
The watcher scans the tail of each pane against a list of regexes. Built-in patterns cover the formats Claude Code emits:
Claude AI usage limit reached|<epoch>— headless / print mode5-hour limit reached ∙ resets 3am— interactive UIresets at 8pm/try again at 6:15pm— message variants
Clock times like 3am are read as the next local occurrence. Regexes you add to limit_patterns in the config take precedence over the built-ins — handy when the message format changes between Claude Code versions. If a pattern matches but the time can't be parsed, the watcher falls back to a conservative 1-hour retry rather than stalling forever.
Agents & GitHub Copilot
The agent key (top-level default, overridable per repo) picks a preset. claude is the default and behaves exactly as before — watched, with limit detection and auto-resume. copilot launches the GitHub Copilot CLI and shows it in the dashboard, but the watcher skips it: a Copilot session is never scanned for limits and never auto-resumed, so handle its rate limits yourself. You can still send it prompts from wind up and the dashboard, and a manual wind resume nudges it with its own message.
Config reference
wind reads ./second-wind.json, then ~/.wind/config.json, then ~/.config/second-wind/config.json (legacy).
<prefix>-<repo name>claude (watched + auto-resumed) or copilot (launched + shown, never auto-resumed); overridable per repoauto preset (--permission-mode bypassPermissions, accepts everything) is the shipped default for a fresh config — same risk class as --dangerously-skip-permissionswind watch runs (caffeinate -dims)wind init wizard scanned, persisted so wind add and the dashboard's + add repo can offer more repos later without re-running initwind up (convention: ~/.wind/prompts/<repo>.md; author with wind prompt)prompt_fileThe config file is trusted input: claude_cmd, claude_args, limit_patterns, and prompt files are executed, compiled, or typed exactly as written — never point wind at a config you didn't write yourself. As of v2.1 the shipped default is full-auto (--permission-mode bypassPermissions, the auto preset): an unattended run accepts everything, not just edits — the same risk class as --dangerously-skip-permissions, so only point wind at repos you trust to run agent actions without prompts (pick acceptEdits/plan/default in wind init to dial it back). And resuming blindly types resume_message into panes; if a session was actually waiting on a permission prompt or a question, "continue" is still a reasonable nudge — but review your sessions in the morning.
The dashboard binds 127.0.0.1 only. /api/status and /api/scan (the + add repo candidate list) serve tokenless, but the modal's full-scrollback endpoint /api/pane — which can carry secrets — and every write action (send/kill/resume/add) require the per-run token. wind add and /api/add write {name, path} only (inheriting the global preset, never accepting claude_args/agent/prompt from the caller), and /api/add only accepts a path already under a persisted scan_root — so a localhost request can't add an arbitrary filesystem path. Pane text reaches the page via textContent with an allowlisted ANSI renderer, never innerHTML. wind prompt never invokes a shell — $EDITOR is split with shlex and exec'd as a list, and the repo→filename mapping is validated as a single path component. Config and state writes are atomic (os.replace), so a crash or a concurrent watcher/dashboard read never sees a truncated file.