Skip to main content

Aegis

A macOS background focus tool. Start a focus session with a topic and duration; the Chrome extension reports pages you visit to a local daemon, which uses an LLM (any OpenAI-compatible endpoint) to judge whether the page supports your study topic. Off-task pages are redirected to a local "keep focus" page.

  • No browsing latency. Pages load normally; the check happens in the background and a caught distraction is redirected within ~1s of being judged.
  • Locked sessions. While a session is active it cannot be stopped, reset, or quit through the app — the daemon runs as a launchd KeepAlive agent and session state persists atomically across restarts (crash/restart/corruption cannot silently void the lock). Be honest with yourself: this is a self-imposed commitment aid, not tamper-proof confinement — anyone who owns the machine can still unload the agent, disable the extension, use another browser, or edit the session file. It guarantees the lock is not lost accidentally; it does not prevent leaving intentionally.

Architecture

Chrome (extension: background.js)
  │  tabs.onUpdated / onActivated
  ▼  POST /evaluate  (async, non-blocking)
macOS daemon (aegis/)  ──►  SQLite cache ──► LLM (Groq/NIM/Zen/…)
  │  whitelist  →  cache  →  LLM verdict
  ▼  {allowed: false, confidence >= 0.8}
redirect tab ──►  http://127.0.0.1:8123/blocked  ("Aegis" page)

Install

Aegis is a Python package installed with pipx; the daemon runs as a launchd LaunchAgent managed by the aegis CLI.

brew install pipx
pipx install aegis-focus         # from PyPI
aegis install                    # render the LaunchAgent plist and start the daemon

The package is published on PyPI as aegis-focus (the plain aegis name was already taken by another project); the installed commands are still aegis and aegis-daemon.

The plist points at the pipx venv's python, so the daemon always runs exactly the code the CLI manages. After a new release, upgrade and reload:

pipx upgrade aegis-focus
aegis restart                    # refuses while a focus session is active (--force overrides)

To install from this repository instead (development builds):

pipx install .                   # from the repo (or pipx install /path/to/aegis)

The Chrome extension is not part of the Python package: load it from the extension/ folder of the repository (that folder is also bundled in the PyPI source download).

CLI reference

aegis install     install/repair the daemon agent (re-renders the plist, reloads)
aegis restart     reload the agent; refuses during an active session unless --force
aegis status      agent loaded? daemon healthy? session state?
aegis cleanup     remove logs and the verdict cache (keeps config and the session lock)
aegis uninstall   stop the daemon, remove the agent + logs + ALL state (confirms unless -y)

There is deliberately no aegis stop: the daemon is a KeepAlive agent — you cannot stop it without removing it. aegis uninstall is the removal path. A deliberate user can always escape (see "Locked sessions" above); the commands are honest about it.

Configure the LLM

Create ~/Library/Application Support/Aegis/config.json:

{
  "LLM_BASE_URL": "https://api.groq.com/openai/v1",
  "LLM_API_KEY": "gsk_...",
  "LLM_MODEL": "llama-3.3-70b-versatile",
  "LLM_TIMEOUT": "60",
  "BLOCK_CONFIDENCE": "0.8"
}

or export the same names as environment variables in the terminal you run the daemon from (a launchd agent does not inherit your shell env; the rendered plist only sets the PATH captured at aegis install time). After a pipx ensurepath or a shell change, run aegis restart so the plist is re-rendered with the new PATH (an unchanged plist is hot-restarted with kickstart; a changed one is booted out and re-bootstrapped so launchd reads the new program path). config.json is the reliable route for secrets under launchd. If no key is set the daemon still runs and blocks nothing (every verdict falls back to allow). Invalid values (e.g. a bad AEGIS_PORT) fall back to defaults instead of crashing.

Note: the Chrome extension hardcodes 127.0.0.1:8123 (see extension/background.js), so AEGIS_PORT/AEGIS_HOST should be left at their defaults for the extension to work.

Extra always-allowed domains can be added without touching code:

{ "EXTRA_WHITELIST": "khanacademy.org, brilliant.org" }

Whitelisted entries match subdomains too (e.g. en.wikipedia.org) and are IDNA-normalized, so Unicode domains work. Public-suffix entries (e.g. co.uk, com.au — domains that are really TLDs) are rejected with a warning: you cannot whitelist an entire country's domains, and the rejection keeps a typo from silently widening the allowlist.

Then load the extension:

  1. Open Chrome → chrome://extensions
  2. Enable Developer mode → Load unpacked
  3. Select the extension/ folder

Usage

  • Click the A menu bar icon → Start Focus Session… → enter topic and duration (1–600 min). The session cannot be stopped early through the app (a deliberate user can always remove it — see "Locked sessions" above).
  • When you finish (or the daemon restarts mid-session), the lock is restored automatically from ~/Library/Application Support/Aegis/session.json (a backup copy .bak is kept and used if the lock file is ever corrupt).

Verdict pipeline

  1. No active session → allow.
  2. Whitelisted domains (github.com, wikipedia.org, …) and browser-internal pages (chrome://, about:, edge://, Chrome Web Store, the Aegis daemon itself, …) → allow, no LLM call.
  3. SQLite verdict cache (per URL per session) → instant repeat answers. LLM failures (timeout, transport error, unparseable reply) are never cached — an outage cannot seal a page open (or lock one shut).
  4. LLM call with page title, URL, meta description, and top/middle/bottom text samples (or YouTube title/channel/description for videos) → JSON verdict {"allowed": bool, "confidence": 0-1, "reason": str}. Verdicts are rate-limited per session (up to 30 per 5 s) so a tab-storm cannot burn the LLM budget; a burst of navigations simply waits its turn and gets slower answers, it never makes more calls.
  5. Any LLM failure → allow (never block browsing due to API issues) — meaning a slow or stalled evaluator intentionally lets an off-task page through. The API is loopback-only and rejects every non-extension Origin, so no website can read your session or burn your LLM quota.

The "Aegis" page

Off-task pages are redirected to http://127.0.0.1:8123/blocked, which:

  • Shows the block reason, session topic, and a live countdown.
  • Auto-returns to the original page 5 seconds after the session ends (no input needed).
  • Appeals: a text box + "Appeal" button. The appeal is sent to the LLM, which decides whether your justification warrants access to that page during this session. The page's link is attached automatically — nothing to copy.
    • Granted → the page opens immediately and the allow verdict is cached for the session, so it is not instantly re-blocked.
    • Denied → the reason is shown; you may appeal again (rate-limited to 1 per 5 s to protect the LLM budget).
    • LLM outage → denied (fail-closed — an appeal is not an unlock bypass). Appeals are retried up to 6 times before giving up.
    • Grants are per-session: a new session judges the page fresh.
    • The page also shows an "Aegis daemon unreachable" hint after several failed /status polls, so a dead daemon is visible instead of a silently frozen countdown.

Uninstall

aegis uninstall

Removes the LaunchAgent, ~/Library/Logs/Aegis/, and the entire ~/Library/Application Support/Aegis/ state directory (session lock, cache, config). The pipx package itself is left installed (pipx uninstall aegis removes that too). The project directory is left in place.

Development

python3 -m venv venv
./venv/bin/pip install -e .
python -m aegis.main          # run daemon in foreground (menu bar app)
python3 -m tests.test_evaluator   # offline daemon+CLI unit tests (no LLM needed)
node aegis/static/test_blocked.mjs      # blocked-page UI harness
node extension/test_background.mjs      # extension harness

Logs: ~/Library/Logs/Aegis/ — daemon.log (auto-rotating, capped at ~1.5 MB total) plus unbounded daemon.out.log / daemon.err.log (launchd's stdout/stderr redirects). The daemon is crash-proof by design: corrupt lock files fall back to the backup copy, a corrupt SQLite cache degrades to an in-memory cache, and any LLM/cache error always degrades to allow.

License

GNU General Public License v3.0 or later — see LICENSE.

Metadata

Release files for aegis-focus 1.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for aegis-focus 1.1.0
File Size Uploaded
aegis_focus-1.1.0.tar.gz 90.7 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for aegis-focus 1.1.0
File Interpreter ABI Platform
aegis_focus-1.1.0-py3-none-any.whl Python 3 none any Details

Total release size: 151.3 kB

Release files / aegis_focus-1.1.0.tar.gz

Download URL aegis_focus-1.1.0.tar.gz
Size 90.7 kB
Tags Source
SHA-256 checksum
How to use checksums
790015f98ea4474793cc832afd0848b33b8b26f63ae70e459a59efee55b3e33d
BLAKE2b-256 checksum
How to use checksums
0c7b5ffa8423590d5986b5358ca7229fe09d9aa0f8a0f821e3f803b2379e022a
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.14.6

Release files / aegis_focus-1.1.0-py3-none-any.whl

Download URL aegis_focus-1.1.0-py3-none-any.whl
Size 60.6 kB
Tags Python 3
SHA-256 checksum
How to use checksums
bfb31b45d1d5ad194c2a7d473d8ca10c6235fd3ac124f3c796ce16500b57c016
BLAKE2b-256 checksum
How to use checksums
ba8f99a8cd18acab8e9f330fcae47fa13b8d022efd955e120d7df1d82b27ca38
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.14.6

Release history Release notifications | RSS feed

This release

1.1.0 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page