A worker at a desk at night under a giant eclipse shield, glowing app windows bouncing off its gold corona

Eclipse Shield

I built Eclipse Shield for the hours when I sit down to do one thing and the open tabs argue for another. It is my focus tool: a Flask backend in secure_app.py, and a browser extension that asks that backend about each visit before the visit settles in.

I keep this page as a logbook rather than a pitch. Each entry below records one part of the tool as I have it: what it is, how a visit gets decided, what the extension does, how I run it, and where it stands when I am being plain about it.

GitHub stars for Eclipse Shield GitHub forks of Eclipse Shield Last commit to Eclipse Shield Top language in Eclipse Shield Size of the Eclipse Shield repository

Open the repoRun itWhere it stands

The eclipse shield at full span over a calm night desk, its corona turning distractions aside
themed-banner: the naming picture for this build, the shield at full span over the desk it guards.
Observation 01

What it is

Entry: the tool itself

Eclipse Shield is a focus tool I wrote for my own desk. I set a context first, in plain words: what I am working on, and what counts as serving that work. Then, when I visit a site, the tool checks that visit against the context I set, instead of against a fixed list that cannot tell study from distraction.

The moving parts are two. The backend is secure_app.py, a Python Flask service that serves on localhost:5000 and holds my lists, my category rules, and the deciding logic. The extension, in the extension folder of the repo, lives in the browser (Chrome and Opera), watches the visit, and talks to the backend about it.

That split is the whole shape of the project. The browser side sees the visit as it happens. The backend side decides, using rules I wrote and, only when I supply a key, an AI call. Entry two logs that decision order exactly as I run it.

Observation 02

How a visit gets decided

Entry: precedence, in order

I gave the decision a fixed order, and the order is the point. My explicit lists outrank everything. A category rule comes next. The AI is asked only when no rule has settled the visit and only when I have supplied my own Gemini key. When I have supplied no key, the rules decide alone, and the tool says so rather than dressing that up.

  1. Allow list. If I put a site on my allow list, it loads. My explicit word settles it.
  2. Block list. If I put a site on my block list, it is blocked. Again, my explicit word settles it.
  3. Category rules. If a category rule matches the visit and my current context, that rule applies.
  4. Gemini AI, when keyed. If no rule matches and I have supplied my own Gemini key, the backend asks the AI, with my stated context and goals as the basis.
  5. Rules only, when not keyed. If no rule matches and I have supplied no key, the rules alone decide. The /health route reports this state as local-only, in its ai field.
Observation 03

The extension

Entry: the browser side

The extension is the part that sits with me in the browser. The repo carries its files in the extension folder, including popup.html and popup.js, background scripts for Chrome and Opera, manifest files for each, and the matrix-animation folder. It reports the visit to secure_app.py and acts on the answer it gets back.

I have exactly one genuine screenshot of it in the repo, and I would rather show that one honestly than stage a set. It is the matrix animation screen, below. The drawings after it come from my Eclipse-Shield-Visuals folder, and I caption them as drawings, not as screens.

Screenshot of the Eclipse Shield extension matrix animation screen, from the repo
The extension matrix animation screen, from extension/matrix-animation/screenshot.png in the repo. This is the only screenshot the project has, so it is the only screenshot on this page.
Hand drawn architecture diagram for Eclipse Shield
architecture.png, from Eclipse-Shield-Visuals: my drawing of how the parts of the project fit together.
Hand drawn components diagram for Eclipse Shield
components.png, from Eclipse-Shield-Visuals: my drawing of the components, piece by piece.
Hand drawn flowchart for Eclipse Shield
flowchart.png, from Eclipse-Shield-Visuals: my drawing of the flow a visit takes through the tool.
Hand drawn statistics chart for Eclipse Shield
statistics.png, from Eclipse-Shield-Visuals: a chart drawing from the project folder, presented as a drawing, not as measured results.
Hand drawn product map for Eclipse Shield
product-map.png, from Eclipse-Shield-Visuals: my map of the product as I laid it out.
Hand drawn schematic sheet for Eclipse Shield
schematic.png, from Eclipse-Shield-Visuals: my schematic sheet for the project.
Observation 04

Quick Start

Entry: the documented way

For macOS, the route the README recommends: read QUICKSTART.md and run the installer, ./install-local.sh. On any platform, without Docker:

python3 -m venv venv && source venv/bin/activate pip install -r requirements.txt -r requirements-secure.txt python3 secure_app.py # serves http://localhost:5000 curl http://localhost:5000/health

The /health route returns JSON with a status, a timestamp, a version, and an ai field that reads configured when an analyzer with AI is available, and local-only when it is not. In local rules only mode it reports ai as local-only.

More in the repo: docs/INSTALLATION.md and docs/DEPLOYMENT.md.

Observation 05

Requirements

Entry: what it needs
Observation 06

Security notes

Entry: locking down

The repo's security work covers input validation, rate limiting, API key handling, and CSRF protection. Two ways to check it:

python3 security_test.py http://localhost:5000 python3 -m pytest tests/ -q
Margin slip, keeper's hand

security_test.py runs against a live server. The pytest suite needs no server and no API key.

Observation 07

Where it stands

Entry: the honest part
Pasted slip, stated plainly

I will state plainly what the extension reads, because a tool that watches my browsing should not hide what it watches. The extension reads my browser history, up to 10,000 entries, my open tabs, and my bookmarks.

When I supply my own Gemini key, the extension and backend send browsing context to Google's Gemini API so the AI step in entry two can judge a visit against my stated context and goals. That context leaves my machine on that step. I know that, and I choose when to supply a key with that in mind.

Without a key, the tool runs local-only rules: my allow list, my block list, and my category rules, with no AI call. The /health route reports that state in its ai field.

This is a personal tool I built for my own focus. I keep the repo docs folder, with its nine files, as I wrote it, and I keep this site in Eclipse-Shield-Website, separate from that documentation.