+40
.gitignore
+40
.gitignore
···
+28
CRUSH.md
+28
CRUSH.md
···+- Runtime: Bun (see CLAUDE.md). Prefer Bun APIs (Bun.serve, Bun.file, Bun.$) over Node shims. Bun auto-loads .env.+- Formatting: Prettier/biome if present; otherwise 2-space indent, trailing commas where valid, semicolons optional but consistent.+- Types: Strict TypeScript. Prefer explicit types on public APIs; infer locals via const. Use unknown over any. Narrow with guards.+- Imports: Group std/bun, third-party, then local. Use named imports; avoid default exports for libs.+- Naming: camelCase for vars/functions, PascalCase for types/classes, UPPER_SNAKE for env constants.+- Errors: Throw Error (or subclasses) with actionable messages; never swallow. Use Result-like returns only if established.+- Async: Prefer async/await. Always handle rejections. Avoid top-level await outside Bun entrypoints.+- Tests: bun:test (import { test, expect } from "bun:test"). Keep tests deterministic, no network without mocking.
+15
README.md
+15
README.md
+531
anthropic.sh
+531
anthropic.sh
···+local challenge=$(printf '%s' "$verifier" | openssl dgst -sha256 -binary | openssl base64 | tr -d "=" | tr "/" "_" | tr "+" "-" | tr -d "\n")+-d "{\"grant_type\":\"refresh_token\",\"refresh_token\":\"${refresh_token}\",\"client_id\":\"${CLIENT_ID}\"}")+access_token=$(echo "$bearer_response" | sed -n 's/.*"access_token"[[:space:]]*:[[:space:]]*"\([^"]*\)".*/\1/p')+new_refresh_token=$(echo "$bearer_response" | sed -n 's/.*"refresh_token"[[:space:]]*:[[:space:]]*"\([^"]*\)".*/\1/p')+expires_in=$(echo "$bearer_response" | sed -n 's/.*"expires_in"[[:space:]]*:[[:space:]]*\([0-9]*\).*/\1/p')+-d "{\"code\":\"${code}\",\"state\":\"${state}\",\"grant_type\":\"authorization_code\",\"client_id\":\"${CLIENT_ID}\",\"redirect_uri\":\"https://console.anthropic.com/oauth/code/callback\",\"code_verifier\":\"${verifier}\"}")+access_token=$(echo "$bearer_response" | sed -n 's/.*"access_token"[[:space:]]*:[[:space:]]*"\([^"]*\)".*/\1/p')+refresh_token=$(echo "$bearer_response" | sed -n 's/.*"refresh_token"[[:space:]]*:[[:space:]]*"\([^"]*\)".*/\1/p')+expires_in=$(echo "$bearer_response" | sed -n 's/.*"expires_in"[[:space:]]*:[[:space:]]*\([0-9]*\).*/\1/p')
+314
bin/anthropic.ts
+314
bin/anthropic.ts
···+Bun.write(Bun.stdout, `\nTokens are cached at ~/.config/crush/anthropic and reused on later runs.\n`);
+23
bin/open.ts
+23
bin/open.ts
···
+29
bun.lock
+29
bun.lock
···+"@types/bun": ["@types/bun@1.2.19", "", { "dependencies": { "bun-types": "1.2.19" } }, "sha512-d9ZCmrH3CJ2uYKXQIUuZ/pUnTqIvLDS0SK7pFmbx8ma+ziH/FRMoAq5bYpRG7y+w1gl+HgyNZbtqgMq4W4e2Lg=="],+"@types/node": ["@types/node@24.1.0", "", { "dependencies": { "undici-types": "~7.8.0" } }, "sha512-ut5FthK5moxFKH2T1CUOC6ctR67rQRvvHdFLCD2Ql6KXmMuCrjsSsRI9UsLCm9M18BMwClv4pn327UvB7eeO1w=="],+"@types/react": ["@types/react@19.1.9", "", { "dependencies": { "csstype": "^3.0.2" } }, "sha512-WmdoynAX8Stew/36uTSVMcLJJ1KRh6L3IZRx1PZ7qJtBqT3dYTgyDTx8H1qoRghErydW7xw9mSJ3wS//tCRpFA=="],+"bun-types": ["bun-types@1.2.19", "", { "dependencies": { "@types/node": "*" }, "peerDependencies": { "@types/react": "^19" } }, "sha512-uAOTaZSPuYsWIXRpj7o56Let0g/wjihKCkeRqUBhlLVM/Bt+Fj9xTo+LhC1OV1XDaGkz4hNC80et5xgy+9KTHQ=="],+"csstype": ["csstype@3.1.3", "", {}, "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw=="],+"typescript": ["typescript@5.9.2", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-CWBzXQrc/qOkhidw1OzBTQuYRbfyxDXJMVJ1XNwUHGROVmuaeiEm3OslpZ1RV96d7SKKjZKrSJu3+t/xlw3R9A=="],+"undici-types": ["undici-types@7.8.0", "", {}, "sha512-9UJ2xGDvQ43tYyVMpuHlsgApydB8ZKfVYTsLDhXkFL/6gfkp+U8xTGdh8pMJv1SpZna0zxG1DwsKZsreLbXBxw=="],
+12
crush.json
+12
crush.json
+35
package.json
+35
package.json
···
+181
public/index.html
+181
public/index.html
···+placeholder="Paste the exact code shown by Anthropic (not a URL). If it includes a #, keep the part after it too."
+1
src/server.ts
+1
src/server.ts
···
+29
tsconfig.json
+29
tsconfig.json
···