Tower · macOS menu bar + terminal

همه Agentهای Claude Code روی یک رادار.برج مراقبت دست شماست.

وقتی چندین Agent در Claude Code هم‌زمان کار می‌کنند، پیگیری‌شان سخت می‌شود: کدام منتظر شماست، کدام بی‌سروصدا fail شده، و کدام دو تا دارند یک فایل را تغییر می‌دهند. Tower یک app برای menu bar مک و یک داشبورد terminal است که Agentها را زیر نظر می‌گیرد، مصرف واقعی پلن را نشان می‌دهد، Claude را روی کشور هدف قفل می‌کند — که یعنی درخواست‌ها فقط وقتی بیرون می‌روند که واقعا داخل همان کشور باشید — و وضعیت اتصال را هم بی‌تعارف می‌گوید.

$ curl -fsSL https://ghhrmnzdh.github.io/tower/install.sh | sh
بعد از نصب: در هر terminal فقط بنویسید tower — داشبورد همان‌جا باز می‌شود
یک daemonstdlib Python دو front-endmenu bar + curses صفرthird-party deps
Guard radar
Guardمجاز
دلیلداخل کشور هدف · مسیر Anthropic باز است
پاسخ به Claude→ api.anthropic.com · مجاز
مسئله

شش Agent. یکی بیست دقیقه پیش fail شده، یکی منتظر approval است که ندیده‌اید، و دو تای دیگر دارند به هم برخورد می‌کنند. از بیرون، همه شبیه هم‌اند.

claude — payments-api
claude — auth-service
claude — web-ui
claude — tower
claude — docs
claude — infra
سیگنال ندارید

نمی‌بینید کدام Agent به شما نیاز دارد.

هیچ چیز بالا نمی‌آید. بین terminalها جابه‌جا می‌شوید تا مورد متوقف‌شده را پیدا کنید؛ اگر هم پیدا شود، دیر پیدا می‌شود.وضعیت امروز · سکوت

علت روشن نیست

خطا می‌بینید، اما منبعش معلوم نیست.

Claude وسط کار می‌ایستد. مشکل Wi‑Fi است؟ شبکه کند هتل است؟ Anthropic مشکل دارد؟ سراغ speed test می‌روید و حدس می‌زنید.وضعیت امروز · API Error (500)

مرز ندارید

VPN جابه‌جا می‌شود و کار می‌میرد.

موقعیت شما وسط session عوض می‌شود. درخواست به‌جای اینکه فقط منتظر برگشتن به کشور هدف بماند، شبیه auth خراب برمی‌گردد.وضعیت امروز · Please run /login

متر ندارید

نمی‌دانید چقدر مانده است.

چقدر از پلن مصرف شده؟ محاسبه local token فقط تخمین است. مقدار واقعی را وقتی می‌فهمید که وسط کار به سقف خورده‌اید.وضعیت امروز · یک حدس

کار Tower

چهار کار، یک daemon.

همه منطق و state در یک process پس‌زمینه نگه داشته می‌شود. چیزی که در menu bar یا terminal می‌بینید فقط یک نمای سبک و مستقیم از همان state است.

Traffic

همه Agentها، مرتب‌شده.

هر Agent فعال در Claude Code به‌صورت زنده دیده می‌شود: model، effort، کاری که همین حالا انجام می‌دهد و سرعت پیشرفتش. صف بر اساس نیاز به توجه شما مرتب می‌شود: failed، بعد blocked، بعد asking، بعد done. notification هم دارد و با click-to-focus مستقیم به terminal همان Agent می‌روید.

auth-servicefailed
⛔︎ apiمنتظر approval
? web-uiاز شما سوال دارد
docsdone · نوبت شما
Weather

اینترنت شما، یا Anthropic.

وقتی Claude وسط session خطا می‌دهد، Tower از قبل سوال اصلی را جواب داده است. لینک شما و TLS handshake تا edgeهای Anthropic را پیوسته و بی‌سروصدا بررسی می‌کند تا به‌جای حدس، منبع خطا را نام ببرد. speed test دستی هم با یک کلیک در دسترس است.

Onlinenet 8 ms · api 214 ms
↓ 412 Mbps · tested 2m ago
Fence

Claude را روی یک کشور قفل کنید.

قفل بودن یعنی: درخواست Claude فقط وقتی بیرون می‌رود که تایید شده باشد داخل کشور هدف هستید. یک proxy محلی کوچک، هر درخواست را وقتی قطعا بیرون از آن کشور باشید نگه می‌دارد. رفتار آن fail-closed است، یعنی هر وضعیت نامطمئن منتظر می‌ماند. درخواست نگه‌داشته‌شده با 503 و Retry-After جواب می‌گیرد، نه 403: Claude خودش retry می‌کند و وقتی برگشتید ادامه می‌دهد. pending است، failed نیست.

inside 🇨🇦 CApass
VPN → 🇳🇱 NLheld
503 · Retry-After 5 — Claude waits, then resumes
Usage

عدد واقعی، نه تخمین.

حد واقعی پلن از خروجی خود Claude Code یعنی claude -p /usage می‌آید. احراز هویت را خود Claude انجام می‌دهد و Tower هیچ tokenای را نمی‌خواند. تخمین local token و cost کنار آن هست، اما واضح برچسب خورده که تخمین است.

Session3%reset in 4h
Weekly33%reset in 2d
Fable31%reset in 2d
source · claude -p /usage · 60s
Menu bar

همه Agentها در یک نگاه.

یک app native برای menu bar، نوشته‌شده با Swift، AppKit و SwiftUI. روی رادار در bar کلیک می‌کنید و نمای Tower باز می‌شود: اول چیزهایی که به توجه شما نیاز دارند، بعد کارهایی که در حال اجرا هستند.

نشان همان state است.رادار داخل bar خود guard است. رنگ کامل فقط برای hold یا خطر استفاده می‌شود؛ وقتی محافظت برقرار است، آرام و سفید می‌ماند.
Model و effort برای هر Agent.Opus، Sonnet، Haiku، Fable با MAX، HIGH، MEDIUM یا LOW. نشان هر Agent فقط وقتی زنده می‌شود که همان Agent مشغول کار باشد.
برخوردها قبل از خراب‌کاری.دو Agent در یک repo هشدار است. دو Agent روی یک فایل هشدار قرمز است.
پایان کار واضح دیده می‌شود.checkmark کشیده می‌شود، row یک‌بار روشن می‌شود و counter بالا می‌رود. failure حرکت نمایشی ندارد؛ ساده و خشک ظاهر می‌شود.
Tower
Protected
Internet · API8 ms · 214 ms
Agents3 at work · 41 jobs done today · 1 needs you
payments-apiOpus 4.8MAX
done — your turn · 214 tests pass, ready to merge
1m
2 agents editing towerd.py in tower
🇨🇦Toronto, CA — inside 🇨🇦 CA
Staying awake · lid open
Long agents keep running while the lid is open.
Plan usageupdated 2m ago
Session3%resets 4h
Weekly33%resets 2d
Fable31%resets 2d
Usage paused — connection unstable Can't reach Anthropic right now. Usage returns on its own once the link is stable.
Open Dashboard… Terminal Dashboard… Settings… Quit & Stop Guard…
این نمونه‌ها زنده‌اند — همان هندسه و همان حرکتی که خود اپ می‌سازد، نه اسکرین‌شات.
بالا یک وضعیت را انتخاب کنید: آیکون menu bar، popover، Claude Code و داشبورد terminal همه با هم دنبالش می‌کنند.
داخل Claude Code

Hold هیچ‌وقت Agent شما را قطع نمی‌کند.

Claude Code را دقیقا مثل قبل اجرا می‌کنید — نه wrapper، نه flag، نه دستور اضافه. وقتی guard درخواستی را نگه می‌دارد، Claude فقط یک 503 قابل‌retry می‌بیند و در spinner خودش صبر می‌کند. همین که اتصال یا موقعیت شما برگردد، همان turn از همان‌جا ادامه پیدا می‌کند.

503 + Retry-After، هرگز 403.Claude Code خطای 403 را auth خراب می‌فهمد — «Please run /login» — و turn را می‌کشد. اما 503 وارد چرخه retry خودش می‌شود: pending، نه failed.
دلیل، داخل خود پیام است.پیام hold علتش را می‌گوید — no stable connection to Anthropic، outside target country، location not confirmed — پس حتی قبل از باز کردن Tower می‌دانید چرا منتظر است.
بودجه retry که از قطعی‌ها بلندتر است.Tower سقف retry کلود را بالا می‌برد — attempt 7/300 — تا چرت VPN یا اختلال سمت Anthropic هم بی‌دردسر رد شود. Agentهای شما هرگز قطع یا terminate نمی‌شوند.
چیزی برای restart وجود ندارد.شبکه را درست کنید یا به کشور هدف برگردید: spinner خودش پاک می‌شود و Agent به کار ادامه می‌دهد. نه context از دست می‌رود، نه turn می‌میرد.
tower — caffeinate ◂ claude — 125×32
> tighten the retry logic in towerd.py and run the tests
⏺ Read(src/towerd.py) · Update(src/towerd.py) · Bash(./build.sh)…
متن hold همان پاسخ واقعی daemon است، بایت به بایت: tower: blocked (reason) - holding for a usable path, retry shortly. به «مجاز» برگردید — همان turn خودش ادامه می‌دهد.
Terminal

همان Tower، داخل shell.

یک داشبورد curses بدون dependency؛ فقط Python stdlib، با همان state file که app می‌خواند. تنظیمی را در یکی تغییر دهید، حدود یک ثانیه بعد در دیگری هم دیده می‌شود.

با یک کلمه باز می‌شود.بنویسید tower. installer آن را روی PATH می‌گذارد؛ لازم نیست path حفظ کنید یا چیزی را double-click کنید. از popover داخل menu bar هم می‌توانید Terminal Dashboard… را باز کنید.
عمدا به کلیدهای پراکنده واکنش نمی‌دهد، اما clickپذیر است.یک keypress اشتباهی کاری نمی‌کند، پس guard ناخواسته خاموش نمی‌شود. اما روی یک row کلیک کنید تا عمل کند: routing را toggle کند، کشور را انتخاب کند، speed test بگیرد یا terminal یک Agent را focus کند.
پاسخ را همان لحظه نشان می‌دهد.header قرمز مثل INTERNET DOWN، WI-FI LOGIN REQUIRED یا ANTHROPIC API ISSUE یعنی اول همین‌جا را ببینید. خطای شبکه همیشه از guard مهم‌تر است.
فقط وقتی چیزی تغییر کند repaint می‌شود.حدود 80 ms برای input، حدود 60 ms تا تایید action در daemon، و بدون هزینه idle.
tower
TOWERProtected · target: Canada
NETWORK LOCATION
✔ inside target
IP 142.114.9.2
Country Canada (CA)
Location Toronto, ON
ISP Bell Canada
GUARD
Route Claude on
Enforce on
Scope Claude only
Allowed 1284
Blocked 3
Proxy :53937 up
● on · lid open Mac stays awake while the lid is open[w] change
● online · net 8 ms · api 214 ms
api ▂▃▂▅▃▂▄▆▃▂▅▃ ↓ 412 Mbps (2m ago)click → speed test
3 at work · 41 done today · 1 need you
payments-api — done · 214 tests pass · Opus 4.8 · MAX · 1m
khamzadeh_flow — thinking… · Fable 5 · 1M · MAX · 17 ✓ · 2m
tower — editing towerd.py · Opus 4.8 · HIGH · 56 ✓ · 2m
web-ui — running tests · Sonnet 5 · MED · 12 ✓ · 5m
⚠ 2 agents in tower — both touching towerd.py
PLAN LIMITSupdated 2m ago
Session ░░░░░░░░░░░░░░░░░░░ 3% used resets in 4h
Week all ██████▌░░░░░░░░░░░░░ 33% used resets in 2d
Fable ██████▏░░░░░░░░░░░░░ 31% used resets in 2d
last 24h · 312 requests · 9 sessions
local estimate · measured on this machine, not your plan %
Session 1.2M tokens $4.80 86 msgs 2h
Week 18.4M tokens $61.22 ~29.1M projected
LIVE TRAFFIC1284 allowed · 3 blocked
09:41:22 ✔ allowed Claude api.anthropic.com
09:41:08 ✔ allowed Claude api.anthropic.com
روی خطِ پایین کلیک کنید تا منوی واقعی ACTIONS باز شود. «Route Claude through the guard» در همین دمو واقعا guard را خاموش و روشن می‌کند و «Re-check location now» یک بررسی موقعیت اجرا می‌کند.
نشان‌ها

برای هر model یک glyph زنده.

عمدا تک‌رنگ و کمینه. در حالت عادی ثابت می‌ماند؛ وقتی Agent مربوطه کار می‌کند، هر نشان به شکل خودش زنده می‌شود. رنگ tier فقط روی label کوچک کنار آن دیده می‌شود، نه روی خود نشان.

فایده‌اش کاملا عملی است: با یک نگاه به فهرست می‌بینید کدام model دارد کدام کار را انجام می‌دهد — تا مارپیچ سنگین Fable که سرِ یک اصلاح ساده مستندات نشسته، یا Haiku که وسط یک refactor بزرگ افتاده، قبل از اینکه token (یا سهم هفتگی Fable) بی‌دلیل بسوزد، به چشم بیاید.

منطق طراحی

اگر چیزی اشتباه به نظر می‌رسد، یعنی app دارد کارش را انجام می‌دهد؛ نه اینکه خراب شده باشد.

Fail-closed، نه گیج‌کننده.Claude فقط وقتی مجاز است که Tower تایید کرده باشد داخل کشور هدف هستید و مسیر قابل استفاده‌ای تا Anthropic وجود دارد. هر چیز نامطمئن hold می‌شود و به‌محض درست شدن location یا connection آزاد می‌شود. لازم نیست چیزی را kill کنید.
موقع خاموش شدن همیشه route را برمی‌گرداند.قبل از خروج، proxy از settings.json حذف می‌شود تا Claude Code دوباره مستقیم وصل شود. crash کردن front-end باعث خراب شدن Claude نمی‌شود.
نه از طریق shell، نه داخل ترافیک شما.routing فقط settings.json را تغییر می‌دهد؛ passive، قابل برگشت، و با backup قبل از اولین تغییر. proxy ترافیک HTTPS را با CONNECT تونل می‌کند: hostnameها را می‌بیند و هیچ byteای را decrypt نمی‌کند.
نسبت به sessionهای شما read-only است.Tower داخل ~/.claude چیزی نمی‌نویسد و در session تایپ نمی‌کند. process table و network table را می‌خواند و transcriptها را tail می‌کند. همین.

Flight rule · block یعنی pending، نه failed

1
403 کار را می‌کشد.Claude Code آن را auth خراب می‌خواند؛ «run /login»؛ و کار از دست می‌رود.
2
پس Tower با 503 + Retry-After جواب می‌دهد.درخواست اول چند ثانیه نگه داشته و دوباره بررسی می‌شود؛ بنابراین اختلال خیلی کوتاه اصلا retry قابل مشاهده نمی‌سازد.
3
Claude spinner خودش را نشان می‌دهد.«Retrying · attempt 2/10»؛ همان حالت pending بومی و پایدار خودش. چیزی از دست نمی‌رود.
4
خودش ادامه می‌دهد.به‌محض clear شدن guard، turn از همان‌جا ادامه پیدا می‌کند.
در راه

روی رادار.

Tower متن‌باز است: استفاده کنید، fork کنید، port کنید. یک daemon قابل حمل با front-endهای سبک باعث می‌شود هرکدام از این مسیرها قابل انجام باشد.

برنامه

Linux front-end

یک tray از طریق AppIndicator؛ curses dashboard از همین حالا باید اجرا شود. daemon با stdlib قابل حمل است.

ایده

برخوردهای دقیق‌تر

فراتر از same-repo و same-file: خط‌های دقیقی که دو Agent ممکن است روی آن‌ها به هم بخورند، با یک tap برای pause کردن دیگری.

ایده

تاریخچه مصرف

حافظه طولانی‌تر برای plan usage: burn-down هفتگی و هشدار قبل از رسیدن به سقف، نه بعد از آن.

ایده

Fenceهای بیشتر

فراتر از کشور: بازه‌های زمانی، ruleهای per-project و allowlist. همان proxy به شکل fail-closed، با راه‌های بیشتر برای مرزبندی.

سوال‌ها

قبل از نصب.

macOS می‌گوید Tower از یک “unidentified developer” است. چه کار کنم؟

اگر نصب تک‌خطی را استفاده کنید معمولا این پیام را نمی‌بینید. Tower فعلا توسط Apple notarize نشده و macOS فایل‌هایی را که از browser دانلود می‌شوند quarantine می‌کند؛ بعد signature را چک می‌کند، آن را نمی‌شناسد و اجازه باز کردن app را نمی‌دهد. فایلی که با curl گرفته شود quarantine نمی‌شود، پس macOS آن check را اجرا نمی‌کند و Tower معمولی باز می‌شود. اگر zip را دستی دانلود می‌کنید، flag را با xattr -rd com.apple.quarantine /Applications/Tower.app پاک کنید، یا یک‌بار app را باز کنید و در System Settings → Privacy & Security گزینه Open Anyway را بزنید. روش Right-click → Open در macOS 15 حذف شده است.

اجرای script اینترنتی با pipe به sh خطرناک نیست؟

سوال درستی است. اول script را بخوانید؛ کوتاه است و همان فایلی است که command اجرا می‌کند. release را از GitHub می‌گیرد، داخل /Applications باز می‌کند، command به نام tower را link می‌کند و app را باز می‌کند. password نمی‌خواهد و از sudo استفاده نمی‌کند. اگر باز هم نمی‌خواهید، zip را از Releases بگیرید و دستی نصب کنید.

آیا Tower کلید API یا tokenهای Anthropic را می‌خواند؟

نه. مصرف واقعی پلن از خروجی خود Claude Code یعنی claude -p /usage می‌آید. احراز هویت را خود Claude انجام می‌دهد و Tower هیچ tokenای را نمی‌خواند. proxy ترافیک HTTPS را با CONNECT تونل می‌کند؛ فقط hostnameها را می‌بیند و ترافیک شما را decrypt نمی‌کند.

Tower چطور Claude Code را روی یک کشور قفل می‌کند؟

Tower یک proxy محلی کوچک اجرا می‌کند و Claude Code را از طریق کلید HTTPS_PROXY در ~/.claude/settings.json به آن وصل می‌کند، نه از طریق shell شما. وقتی قطعا بیرون از کشور هدف باشید، درخواست Claude نگه داشته می‌شود و با 503 و Retry-After جواب می‌گیرد؛ بنابراین Claude آن را در spinner خودش retry می‌کند. درخواست pending می‌ماند، failed نمی‌شود، و وقتی دوباره داخل کشور هدف باشید ادامه پیدا می‌کند.

اگر Tower بسته شود یا crash کند چه می‌شود؟

قبل از خروج، proxy از settings.json حذف می‌شود تا Claude Code دوباره مستقیم وصل شود. guard در هر خروج سالم و از طریق atexit مسیر را برمی‌گرداند و daemon تک‌نمونه‌ای است. crash کردن front-end باعث خراب شدن Claude نمی‌شود.

از کجا بفهمم قطعی از اینترنت من است یا از Anthropic؟

Tower هر دو را پیوسته و بی‌سروصدا بررسی می‌کند: لینک شما و یک TLS handshake زمان‌گیری‌شده با api.anthropic.com. نتیجه را به شکل online، degraded، offline، captive portal یا مشکل سمت Anthropic نشان می‌دهد و یک speed test دستی هم دارد. حدس لازم نیست و برای فهمیدن وضعیت، هیچ درخواست Claude مصرف نمی‌شود.

Tower رایگان است؟ روی Windows یا Linux اجرا می‌شود؟

Tower رایگان و متن‌باز است. تجربه کامل، یعنی menubar app به‌همراه terminal dashboard، روی macOS 14 یا جدیدتر و Apple Silicon اجرا می‌شود.

روی Windows 10/11، daemon و terminal dashboard همین حالا اجرا می‌شوند: همان guard، همان proxy fail-closed و بدون dependency. فعلا experimental است؛ نوشته و review شده، اما هنوز روی سخت‌افزار واقعی Windows تست نشده است. native tray app برای Windows مرحله بعدی است. front-end لینوکس هم برنامه‌ریزی شده و curses dashboard باید از حالا روی Linux اجرا شود.

Get Tower

برای Agentها یک Tower داشته باشید.

فقط یک خط: app را نصب می‌کند، دستور tower را روی PATH می‌گذارد و guard را روشن می‌کند — بدون password، بدون Gatekeeper warning و بدون drag کردن.

$ curl -fsSL https://ghhrmnzdh.github.io/tower/install.sh | sh
بعد از نصب: در هر terminal فقط بنویسید tower — داشبورد همان‌جا باز می‌شود · برای upgrade همین خط را دوباره اجرا کنید
این خط دقیقا چه کار می‌کند؟

اول خود اسکریپت را بخوانید — کوتاه است و دقیقا همان فایلی است که این دستور دانلود می‌کند. آخرین release را از GitHub می‌گیرد، در /Applications باز می‌کند، دستور tower را لینک می‌کند و app را اجرا می‌کند. هیچ‌وقت password نمی‌خواهد و از sudo استفاده نمی‌کند.

نصب دستی، یا build از source

Tower.app.zip را از Releases بگیرید — نه “Source code (zip)” که app ساخته‌شده ندارد. macOS دانلودهای browser را quarantine می‌کند و app را unidentified می‌خواند؛ با xattr -rd com.apple.quarantine /Applications/Tower.app پاکش کنید یا در System Settings → Privacy & Security گزینه Open Anyway را بزنید. خط نصب بالا اصلا به این مسئله نمی‌خورد.

ساختن از source به Xcode Command Line Tools نیاز دارد:

$ git clone https://github.com/ghhrmnzdh/tower && cd tower && ./build.sh
پیش‌نیازها

macOS 14+ روی Apple Silicon · Claude Code نصب‌شده · Python 3.8+ در runtime (خود macOS دارد). روی Windows 10/11، daemon و داشبورد terminal همین حالا اجرا می‌شوند — experimental؛ tray app مرحله بعد است. Linux هم در برنامه است.