There’s a moment in every project where you open your main file, scroll for what feels like 30 seconds, and think: this has to stop. Today was that day.
The 5,000-Line Diet 🏋️
Let’s address the elephant in the repo: main.py was 15,900 lines. One file. Fifteen thousand nine hundred lines of FastAPI endpoints, SQL queries, SSE streams, and business logic all living together like a college dorm room.
Today it went on a diet. A serious one.
main.py: 15,900 → 11,500 lines (-28%)
The extracted modules:
| New File | What It Does |
|---|---|
routers/dashboard.py |
Dashboard summary API |
routers/groups.py |
Group CRUD, dynamic groups, tags |
app/core/rules.py |
Dynamic group rule evaluation engine |
app/db/nodes.py |
Node upsert, auto-onboard, group membership |
dependencies.py |
Shared auth, DB pool, error helpers |
app/core/config.py |
Centralized env-based settings |
Is 11.5k still too much? Absolutely. But Rome wasn’t burned in a day. Or however that saying goes.
The tricky part wasn’t the extraction itself — it was making sure dependencies.py properly shares the database pool and auth verification across all routers without circular imports. FastAPI’s Depends() injection pattern makes this surprisingly clean once you get the wiring right.
Command Palette: Ctrl+K 🔍
Every tool I love has a command palette. VS Code, Slack, Notion, Linear — they all let you hit Ctrl+K and just go somewhere. Octofleet now does too.
Hit Ctrl+K (or ⌘+K on Mac) from anywhere and you get:
- Live node search — type a hostname, see online/offline status in real-time
- Page navigation — jump to any page without touching the sidebar
- Keyboard-first — arrow keys, Enter to navigate, Escape to close
It’s one of those features that takes 329 lines to build but saves you thousands of clicks over time. The search hits the /api/v1/nodes endpoint and shows results with colored status dots — green for online, gray for offline. Simple, but it feels right.
The implementation lives in a single CommandPalette.tsx component that gets mounted in the root layout. It listens for the keyboard shortcut globally and renders a dialog overlay with a filtered list. Nothing revolutionary, but the kind of polish that makes a tool feel like a product instead of a prototype.
Agent Activity Monitor: The Eye of Sauron 👁️
Here’s the new toy I’m most excited about.
Go to Admin → Agent Monitor and you see every single thing your agents are doing. Right now. In real-time.
The left side shows all your agents as clickable cards — hostname, version, status (active/idle/stale/offline), running jobs, pending remediation. Click one and the activity feed on the right filters to show only that agent’s traffic.
The feed itself is a live stream of events:
- Job polls — agent checking for new work
- Terminal/Shell/Screen polls — remote access heartbeats
- Health reports — periodic system stats
- Remediation results — patch job outcomes
- Job results — command execution completions
Under the hood, it works like this:
- An HTTP middleware intercepts every request matching agent-known URL patterns (
/jobs/pending/,/terminal/pending/,/agents/*/health, etc.) - Events go into an in-memory ring buffer (capped at 500 — no DB overhead)
- A Server-Sent Events endpoint streams new events + periodic node status to connected browsers
- The frontend also polls every 10s as a fallback because SSE reconnection isn’t always instant
The middleware approach means zero changes to existing endpoints. It just watches the traffic and records what it sees. Completely non-invasive.
The summary cards at the top give you the instant overview: how many agents are active, total count, running jobs, pending remediation. It’s the kind of dashboard you leave open on a second monitor.
The Merge That Almost Wasn’t 🔀
Here’s the real story of today. I had a feature branch (testdevelop) with the refactoring and command palette work, but it was based on a commit from before nine important bugfixes and the entire Agent Monitor feature had landed on main.
The rebase went clean (git gods were smiling), but testing revealed five issues:
- Missing
Searchicon import in Navbar — TypeScript caught it, but only during the Docker build. 30 seconds of build time to find a missing import. Classic. - Phantom
trigger_alertimport in the extractedjobs.py— referenced a function that doesn’t exist inalerting.py. Imported but never called. Dead code that only explodes when you move it. API_KEYvsINVENTORY_API_KEY— the newconfig.pylooked forINVENTORY_API_KEY, but Docker Compose setsAPI_KEY. Every single endpoint returned 401. Took longer to find than I’d like to admit.- UUID vs TEXT column mismatch —
job_instances.node_idis TEXT,nodes.idis UUID. Postgres does not silently cast these. It will, however, silently ruin your evening. - Duplicate router registration —
groups_routerwas included twice. FastAPI doesn’t complain, but you get duplicate routes in the OpenAPI schema.
All fixed, all tested, all green. The merge commit is clean and every endpoint responds with 200.
What’s Next
The backend still needs more slimming — 11.5k lines is better but not great. The security endpoints alone account for a huge chunk and should probably move to their own router module.
There’s also the lingering current_state_version column error on service assignments, and /repo/files has a missing download_count column. Neither is from today’s changes, but they’re on the list.
For now though, I’m going to enjoy the fact that I can hit Ctrl+K, type “BALT”, and instantly jump to my BALTASA node’s detail page. It’s the little things.
Octofleet is open source. Check it out on GitHub if you’re into endpoint management, or just want to see a 11,500-line main.py and feel better about your own codebase.