Technology
Gadgets, tools, and the small obsessions of a life lived through good hardware. Enthusiasm, applied responsibly.
Stock Ticker
Add a ticker once, find it there forever.
Your tickers
Your ticker list is empty. Type a ticker above, or start with a few:
The watchlist
The page opens on five defaults: Meta, Apple, Nvidia, Google, Microsoft. Make it yours. The field above the list searches about 9,500 US-listed stocks, funds, FX pairs and crypto by ticker or company name; pick a match and it lands in the list. Each symbol gets its own cell: price, day change, a sparkline. The row of ranges above the cells, 1D through ALL, redraws every sparkline at that span. The header checkbox turns the scrolling strip off.
Tap a cell and it pushes a detail screen: the day's numbers, market cap, P/E, EPS, dividend yield, and a bigger chart with its own range tabs from one day to everything. The address bar carries #s=NASDAQ:AAPL while the screen is open, and that link reopens the same screen, on any symbol, listed or not.
Housekeeping lives behind Edit. It reveals Γ to remove and β‘ to reorder: drag with a pointer, or on the keyboard, where space lifts a row, arrows move it, and space drops it. Edit is also where watchlists are managed. Up to eight named lists, one showing at a time; the switcher stays out of the way until a second list exists.
The lists live in localStorage. They survive reloads and restarts in this browser, on this device, and go no further: no account, no sync, no database on my end. Clearing site data clears them. There is no export either, so a list built on a laptop stays on that laptop.
None of which makes it private from TradingView. Every symbol you add is passed to them to draw, so they see the list, your address, and the page you came from. The honest version of the claim is that nothing reaches a server of mine, because I don't have one.
Symbol formats
Search covers the US listings, cap-ranked so the match you meant comes up first. The same field still takes anything TradingView can resolve, typed raw: exchange-prefixed forms like NYSE:BRK.B and AMEX:VOO, FX pairs (EURUSD), crypto (BTCUSD, COINBASE:ETHUSD). A bare ticker the directory knows is upgraded to its listed form on the way in: aapl becomes NASDAQ:AAPL.
Outside the directory, bare tickers are first match, not canonical, and the first match is not always the famous one. SPX gets you SpaceX, not the S&P 500. Index and futures symbols mostly don't resolve at all on the free tier: ask for SP:SPX or CME_MINI:ES1! and the cell says the symbol is only available on TradingView, which is their way of saying that data costs money. TradingView's search gives the canonical form.
The cap is 25 symbols a list. That is a rendering budget, not a philosophy: each one is its own frame.
Where the numbers come from
TradingView, through its free embeddable widgets. No key, no account. That is also the constraint. US equity prices run about fifteen minutes behind, more on some exchanges, and TradingView decides what happens inside the frames. This is a glance, not a trading desk, and not advice.
Every free quote API I checked, Alpha Vantage and Finnhub and Polygon and Twelve Data, either restricts redisplaying quotes on a public page or charges for the right. An embed is the honest way to do this for nothing.
If the quotes don't load
A short note takes the place of the quotes. Usually that means a privacy extension or a network filter is blocking TradingView. It can also mean this site's content-security-policy hasn't been told to allow them, which is my fault rather than yours. Either way your saved symbols are untouched, and they come back when the quotes do.
devfetch
neofetch is for machines. devfetch is for developers.
Most GitHub profiles open with a wave: a README that says hello, a short bio, a row of pinned repositories. Mine boots a terminal. There's an ASCII portrait of my face on the left and a column of key: value rows on the right, and it repaints itself every night in whichever TokyoNight my reader is wearing.
This is the whole build, and it's small enough to steal in an afternoon. Every block of source below is pulled live from the repository, so nothing here can drift from what actually runs on my profile. Take it, change the parts marked TODO, and point it at yourself.
That card is live, straight from my profile: two self-contained SVGs that swap by prefers-color-scheme (flip your system theme and watch). The idea isn't mine. I first saw it on Andrew6rant's profile and rebuilt it from scratch, since that project carries no license. The whole thing is about 600 lines across three Python scripts and a workflow.
One File, Two Faces
GitHub has no setting for "show a different image in dark mode," so the entire README is one <picture> element:
Loading README.mdβ¦
The tempting approach, one SVG with a @media (prefers-color-scheme) block inside it, works in a browser and fails on GitHub, because README images render through an <img> tag and GitHub's camo proxy, and the mobile apps ignore the query outright. <picture> moves the decision up a layer, into HTML that GitHub controls: dark is the <source>, light is the fallback <img>.
That same camo proxy blocks every external fetch, which is why the two SVGs have to be fully self-contained: the font is a Fira Code subset embedded as a base64 data-URI, with no network calls and no working links anywhere in the card.
Drawing a Terminal
The card is drawn by hand, not templated. A single Python script places text on an exact monospace grid (every run pinned to its own x-coordinate so nothing shears if the embedded font falls back), with dotted-leader key: value rows, three macOS traffic-light dots, a title bar, and a TokyoNight palette. It emits both themed SVGs.
Loading src/generate_svg.pyβ¦
The rows in build_info() are the only personal part: your name, editor, keyboards, contact. That's the first thing you'll change.
A Face You Draw by Hand
The portrait is the part people ask about, and it's the one step that can't be fully automated: you pick your own photo and tune it by eye. Start with a head-and-shoulders shot, cut the background out, and matte it onto black so the subject reads against the dark card:
uvx --python 3.11 --from "rembg[cpu,cli]" rembg i you.jpg you_nobg.png
magick you_nobg.png -background black -flatten you_black.png
Then luminance becomes glyphs (each pixel's brightness picks a character from a 70-glyph ramp), and a second pass walks the same photo cell by cell, converts each to HSV, and snaps it to a theme color. Two rules carry the whole look: pastel blues are forced to stay blue (the shirt), and warm skin-and-hair tones are pushed to silver so the shirt is the only real color in the frame.
Loading src/ascii_portrait.pyβ¦
Re-render with different --contrast / --gamma / --sharpen until the face reads. This is hand-work; every photo is different, and there's no recipe that fits them all.
Counting Yourself
A card that brags should at least be honest, so the stats are real, pulled from GitHub's GraphQL API every night. Repos, stars, and followers are one query. The other two fight back: all-time commits need a year-by-year walk of contributionsCollection (it only spans a year at a time, and you have to fold in restrictedContributionsCount for private work), and honest lines-of-code means walking each repo's history yourself, since the REST stats endpoint is stale, 202s while it computes, and approximates on big repos. Each repo's result is cached against its branch-head SHA, so an unchanged repo costs zero API calls the next night.
Loading src/fetch_stats.pyβ¦
The Nightly Heartbeat
None of this is worth doing by hand twice, so a GitHub Action runs it on a cron, redraws the SVGs, and commits them back as a bot only when something changed. The token you give it decides what it can see: the default GITHUB_TOKEN counts public data; a personal access token with private scope (README_TOKEN) counts everything.
Loading the workflowβ¦
The last step is the one I'd urge you to keep. The card that inspired mine had its update cron die quietly in 2025, and by the time anyone noticed it had been frozen for the better part of a year. A heartbeat you can't hear isn't a heartbeat, so mine files an issue against its own repo the moment a run fails. The card is allowed to go stale for a day; it is not allowed to go stale for a year without telling me.
Make It Yours
Everything you'd change is marked TODO in the source above. Clone the repo and grep for it:
grep -rn TODO src/
- Your GitHub username:
fetch_stats.py, theUSERline. - Every card row:
build_info()ingenerate_svg.py(labels and values both). - The
user@hosttitle and theme colors: alsogenerate_svg.py. - The portrait: your own photo, per the section above.
Then run python3 src/fetch_stats.py and python3 src/generate_svg.py, commit the two SVGs, and drop the <picture> from the root README onto your profile. src/README.md has the full setup, dependencies, and run order.
Credit
The concept belongs to Andrew6rant, whose profile card I admired for a while before building my own. Every line here is an original re-implementation rather than a fork, but the idea, a profile that reads like a terminal and keeps itself current, is his. Mine just adds the thing his was missing: a pulse that screams when it stops.
The full source is at github.com/IllyaStarikov/IllyaStarikov. A profile README is the one page on GitHub that's entirely yours; I'd rather it say something than wave.
The Vanishing Keystrokes Bug
How a faceless background agent ate my typing, and the script that caught it.
A few days into an uptime, deep in something, my Mac would stop listening. Not a crash, not a freeze. The cursor still moved, windows still highlighted under it, I could click anything. But the keyboard went dead: I'd type a whole sentence into a window that looked focused and watch zero characters land. Clicking didn't help. Sometimes it cleared after a few seconds; sometimes I rebooted and bought another day or two of quiet.
A bug that only shows up after hours of uptime, never on a cold boot, and clears on reboot is the worst kind. You can't reproduce it on demand, so you can't poke at it. I finally cornered it, and the culprit wasn't what I assumed.
The Symptoms
If your Mac does this too, start here. The shape of the failure tells you where to look.
- The mouse works. The keyboard doesn't. Pointer moves, clicks land, but no window accepts text.
- It's system-wide, not one app. Every window is dead, whichever one you click into.
- It builds up over uptime. Fine on a fresh boot, more frequent the longer the machine stays awake.
- A reboot fixes it. Temporarily. It always comes back.
- The focused window looks slightly de-focused, title bar greyed out, as if nothing is frontmost.
That combination rules a lot out. It isn't a hardware keyboard fault: the mouse and keyboard share enough of the input stack that a real HID failure takes both. It isn't one misbehaving app. It points at the part of the OS that decides where keystrokes go, and at something that corrupts that decision the longer you stay logged in.
Two Kinds of "Front"
macOS tracks "in front" in two places that are supposed to agree.
- The active application (LaunchServices and
NSWorkspace). Apple definesfrontmostApplicationbluntly: the app that receives key events.lsappinforeports it. - The key window (WindowServer). Within the active app, keys flow to the key window, then to its first responder, the text field your cursor sits in. No window that can become key means no key window, and nowhere for text to land.
A third notion, Accessibility's AXFrontmost (what AppleScript's System Events reports), tracks the app whose UI is actually up front.
On a healthy Mac all three agree and you never think about it. The bug lives in the gap: if LaunchServices says one app is active while Accessibility says another, the OS routes your keystrokes to an app you aren't looking at. If that app has no window, they evaporate.
Bug Catcher
Check both notions from the terminal, especially while the bug is happening:
# LaunchServices: who owns key events?
lsappinfo info -only name "$(lsappinfo front)"
# Accessibility: who's actually up front?
osascript <<'EOF'
tell application "System Events"
name of first application process whose frontmost is true
end tell
EOF
Healthy, these match. Mine didn't:
LaunchServices : "Logitech G HUB Agent"
Accessibility : wezterm-gui
LaunchServices thought a faceless agent, the Logitech G HUB Agent, was the active app receiving key events, while the app I was clicking into was my terminal. My keystrokes were routing to an agent with no window.
Two commands catch it if your timing is lucky. The bug is intermittent, so I wrote a monitor that shouts the moment the two disagree.
focus-spy
It polls both notions once a second, logs every change, and flags MISMATCH when the PIDs differ. Drop it in your $PATH, chmod +x it, run it.
#!/usr/bin/env bash
# focus-spy - find out what's stealing keyboard focus on macOS.
#
# macOS tracks "the frontmost app" in two places that should agree:
# * LaunchServices / NSWorkspace - the app that RECEIVES KEY EVENTS
# (what `lsappinfo front` reports)
# * Accessibility (AXFrontmost) - the app whose UI is up front
# (what System Events reports)
# When a background agent shoves itself into the first one without a
# real window, the two disagree, and your keystrokes fall in the gap.
# This logs both once a second and shouts when their PIDs differ.
#
# Usage:
# focus-spy # watch (Ctrl-C to stop)
# focus-spy mark NOTE # mark the instant typing dies
# focus-spy report # print the timeline, sorted
set -uo pipefail
LOG="${FOCUS_SPY_LOG:-$HOME/.local/state/focus-spy.log}"
mkdir -p "$(dirname "$LOG")"
ts() { date '+%Y-%m-%d %H:%M:%S'; }
# LaunchServices' frontmost (the key-event owner) as "name#pid".
# Compare by PID, not name: the two APIs spell the same app
# differently ("WezTerm" vs "wezterm-gui"); only the PID is identity.
ls_front() {
local asn name pid
asn="$(lsappinfo front 2>/dev/null)"
name="$(lsappinfo info -only name "$asn" 2>/dev/null)"
name="${name#*=}"; name="${name//\"/}"
pid="$(lsappinfo info -only pid "$asn" 2>/dev/null)"
pid="${pid##*=}"
printf '%s\n' "${name:-?}#${pid:-?}"
}
# Accessibility's frontmost (the visible app) as "name#pid". First run
# may prompt your terminal for Automation access to System Events.
ax_front() {
osascript 2>/dev/null <<'OSA'
tell application "System Events"
set p to first application process whose frontmost is true
return (name of p) & "#" & (unix id of p)
end tell
OSA
}
watch() {
echo "focus-spy: watching (Ctrl-C to stop). Log: $LOG"
local prev="" ls ax line tag
while :; do
ls="$(ls_front)"; ax="$(ax_front)"
line="ls=[$ls] ax=[$ax]"
if [[ "$line" != "$prev" ]]; then
[[ "${ls##*#}" == "${ax##*#}" ]] && tag="ok " || tag="MISMATCH"
printf '%s\n' "$(ts) $tag $line" | tee -a "$LOG"
prev="$line"
fi
sleep 1
done
}
case "${1:-watch}" in
watch) watch ;;
mark) shift
printf '%s\n' "$(ts) MARK >>> ${*:-typing died} <<<" \
| tee -a "$LOG" ;;
report) sort "$LOG" 2>/dev/null || echo "no log yet" ;;
*) echo "usage: focus-spy [watch|mark NOTE|report]"; exit 1 ;;
esac
Leave focus-spy watch running in a spare terminal. The instant the keyboard dies, run focus-spy mark "typing died" in any shell, then focus-spy report. Look for a MISMATCH line: whatever sits on the ls= side is your thief. Every one of mine read ls=[Logitech G HUB Agent].

The two fronts diverging on demand. A faceless stand-in agent (built to reproduce the bug) seizes the LaunchServices slot while the terminal keeps Accessibility focus, so the status flips to MISMATCH, then back the instant it exits.
The Smoking Gun
A monitor tells you who; a kill test tells you whether you're right. The LaunchServices front process read Logitech G HUB Agent more than twenty samples in a row. So I killed the stack and watched it the instant it died:
killall lghub_agent lghub_system_tray lghub
lsappinfo info -only name "$(lsappinfo front)"
The active app snapped back to WezTerm and held. Both notions agreed. Typing was solid. G HUB's agent had been parking itself in the active-app slot and never letting go.
Why It Breaks
The active app receives key events, routed to its key window's first responder. An agent app (LSUIElement, no Dock icon) can still become the active app, and the old SetFrontProcess API was deprecated for NSRunningApplication.activate, which developers have long reported is easy to leave in an inconsistent state. G HUB falls into exactly that: it activates itself, probably an unbalanced activate on a device-poll loop, and becomes the active app without a window that can become key. The keyboard now points at a process with no first responder, so keystrokes are dropped, not stolen, just discarded, until you click into a real app. The mouse still works because mouse events are hit-tested by pointer location, not by which app is active. (Don't confuse it with Secure Input, where an app legitimately swallows every keystroke and forgets to stop; there both notions of "front" still agree. The mismatch is the tell.)
You're not imagining it, either. Another engineer built the same kind of monitor and clocked G Hub grabbing focus 47 times in four minutes. A MacRumors thread nails it: G Hub "keeps trying to get focus ... since it only runs in the background and has no window to receive the focus, the frontmost app of the system loses focus." Logi Options+ does the same. The trigger looks like wake and device re-enumeration, which fits why it snowballs over uptime and resets on reboot. The lesson: when you finally name a weird bug, search the name. You're rarely the first to hit a real defect.
The Fix
Right now, quit it:
killall lghub_agent lghub_system_tray lghub
Permanently: a launch agent restarts it at login (/Library/LaunchAgents/com.logi.ghub.plist, RunAtLoad). Move it aside, reversible:
sudo mv /Library/LaunchAgents/com.logi.ghub.plist \
~/Documents/backup/com.logi.ghub.plist
Then check System Settings, General, Login Items & Extensions for any Logitech entry. If you don't use Logitech G gaming gear, uninstall G HUB outright; Logi Options+ already covers a normal mouse.
My Mac types again. Now when focus feels off, I reach for focus-spy watch in a corner terminal, because the next thief trips the same wire.
Talk To Your TODOs
I talk to my TODO list. You should too.
I love TODO lists. I especially love spending days bringing one up, and promptly abandoning it.
Weeks later, I'm using it again. It's captured most of my priorities, but not all of them. Stuff falls through the cracks, I start to not trust my TODOs. Day-by-day it falls further out of sync, until I stop using it. Some time goes by, I fill the missing pieces and I'm back checking off boxes!
But a wildly new priority appeared! My system falls out of sync again, and it won't resync until I do a massive overhaul. You guessed it, I'm off working on the wild project while my original TODOs wither away.
What's wrong with me?
The Solution
What's wrong with me is I like doing stuff. Real stuff. I hate grunt work, a lot. And most of the work in maintaining a task manager is grunt work:
- Seeding. The initial high. Step 1 of using a task manager, relentlessly filling it with your current TODOs. You feel a rush of productivity, without moving one step closer to your goals.
- Maintenance. The reality of using a task manager. Adding new tasks, big or small. Removing ones that are no longer relevant, which is much harder. Keeping it in sync with your life.
- Reprioritize. The curveballs. Most change a few tasks in a project, some change entire projects, and rarely one will have you reconfigure most of your active areas of work.
So lately, instead of writing TODO lists, I've been talking to TODO lists instead.
With AI, I've been able to automate away the grunt work so I can focus on doing the work. Using natural language, I can turn prompts into projects. "Help me plan out a wedding." "Review my taxes folder and make me a template for my yearly filing." "Scan my contacts, find my relatives, and add tasks to wish them a Happy Birthday." These are actual projects Gemini has helped me with.
Here's how you can talk to your TODO list as well.

MCP: The TODO->AI Connector
MCP stands for Model Context Protocol. An MCP server is a small adapter that lets an AI client (the Gemini CLI, Cursor, ChatGPT desktop) reach into another app and use it as a set of tools: read your tasks, create new ones, retag a project, run a query. The model never swallows your database. It calls tools, and the server decides which tools exist and what each one is allowed to touch.
That fence is the point. Your tasks aren't baked into a model or shipped off to train one. The server sits between the assistant and your data, exposing a short, named list of actions and nothing else. The model picks which to call; the server enforces the rest.
My Setup
I've been using OmniFocus on-and-off for about 10 years, so it's my tool of choice. For myself, the only way I can consistently use a TODO list is if it has all my tasks.
My setup is deliberately boring. I run one of the OmniFocus MCP servers from the catalog below against my own database, and drive it from the terminal with the Gemini CLI, which is already open all day. Everything below is something I've actually asked it.
You don't need a terminal, though. The same server plugs into a GUI chat client just as well: the Gemini app, Cursor, anything that speaks MCP lets you register a server and start asking in plain English. The terminal is my preference, not a requirement. Wherever you already talk to an assistant is where this lives.
How I Actually Use It
Three chores eat most of what a task manager costs you, one for each flavor of grunt work above: clearing the inbox is maintenance, the weekly review is where you catch a reprioritization before it derails you, and starting a project from scratch is seeding without the dread. Here's how each one goes when the assistant takes the boring half.
Inbox Triage
Capture and organize are two different moods, and the switch between them is where I lose tasks. Over a day I'll dump twenty things into the inbox: "call the vet," "renew the passport," "that book Taylor mentioned," "look into the weird noise the car makes." Then I never sort them, because sorting means stopping.
So I don't sort. At the end of the day I ask it to triage: file anything it's confident about, ask me about the rest. The obvious ones land on their own: the vet call in Errands, the passport in a Travel project. It hands back the two or three it can't place, I answer those, and the inbox is empty. I never left capture mode.
Weekly Review
The weekly review is the GTD ritual I skip the most, because it's an hour of mechanical cleanup before any thinking happens. That mechanical hour is exactly what an assistant is for. I run it in the classic three passes and let the model do the grunt work in each.
Get Clear. Empty the inbox, then: "Find any project with no next action and flag it. List tasks missing a tag or a time estimate and propose values." Stalled projects are what quietly kill a system; having them surfaced instead of hunted is most of the battle. I approve or correct the proposed tags in one pass.
Get Current. "Pull my Waiting For list. Cross-reference my calendar for the last two weeks and the next two, and tell me what I've committed to that isn't in here yet." Half the time it catches a meeting that implied a task I never wrote down.
Get Creative. This is the part I actually want to do, so it's the part I keep. "Based on my active projects, give me a mind-sweep: what am I likely forgetting?" It's a trigger list tuned to my real life instead of a generic checklist. Most of it I discard. The one or two it surfaces that I'd genuinely dropped pay for the whole review.
Project Planning
A blank project is the most expensive thing in any task manager. Spelling out the dozen obvious sub-tasks of "plan a camping trip" is pure overhead, and that overhead is usually what stops me from starting at all.
So I start from a draft instead. "Set up a project for a long weekend in Tahoe: permits, gear check, food plan, the drive, who's coming. Give it sub-tasks and rough due dates working back from the 15th." Thirty seconds later there's a real project, sequenced and dated. Maybe half the tasks are right. I delete the ones that don't apply, fix the dates, add the two things it couldn't have known. Editing a wrong draft beats producing a right one from a blank page, every time.
Pick Yours
If OmniFocus isn't your task manager, almost everything else has an MCP server too. Most have several.
A few notes before the catalog:
- Official means the company that builds the tool ships the server. Prefer these unless you need self-hosted, on-prem, or a feature only the community fork has.
- Most Tier-1 tools (i.e., Atlassian, Notion, Asana) now run a hosted, OAuth-only MCP at
mcp.{vendor}.com/mcpor similar. SSE transport is being phased out; assume Streamable HTTP unless told otherwise. - Star counts last cross-checked May 2026 and drift weekly. The
registry.modelcontextprotocol.ioregistry is the canonical place to look up new entries.
Task Managers
OmniFocus
- themotionmachine/OmniFocus-MCP Query, dump, edit, batch. JXA under the hood, easiest to drop into Claude Desktop today.
- jqlts1/omnifocus-mcp-enhanced When themotionmachine hits its ceiling: custom perspectives, real hierarchical sub-tasks, Planned Dates, reparenting that doesn't break.
- vitalyrodnenko/OmnifocusMCP Pick your runtime: a Rust binary on Homebrew, Python on uv, or TypeScript on Node. 45 tools, four prompts, same surface across all three.
Things 3
- hald/things-mcp Reads everything (Inbox, Today, Upcoming, Anytime, Someday) and, as of v0.8.1, writes too: add and update todos, projects, and areas via AppleScript.
- rossshannon/Things3-MCP The fork that lets you actually create. Sub-tasks fall back to Markdown checkboxes in notes (Cultured Code's AppleScript surface won't allow native checklists).
- ebowman/mcp-server-things Defensive by default: an AI-tag-creation guard, 30-second AppleScript timeouts, env-vars for every behavior. The one to pick if you don't want surprises.
Todoist
- Official: Doist/todoist-mcp 44 tools, hosted at
ai.todoist.net/mcp, OAuth, MCP Apps support so widgets render in chat. (The older@doist/todoist-ainame still works as a thin shim; new installs usetodoist-mcp.) - greirson/mcp-todoist
DRYRUN=trueis the killer feature: rehearse bulk operations before committing them. Quick-Add natural-language parser included. - abhiz123/todoist-mcp-server ~390 stars, untouched since April 2025, still works. Light enough to keep around even after switching to the official.
TickTick / Dida365
- karbassi/mcp-ticktick Habits, focus timers, filters, calendar. The only TickTick server that feels like the actual app. Wants both a v1 token and a v2 cookie to unlock the full surface.
- jacepark12/ticktick-mcp OAuth2 with auto-refresh and a flag for Dida365 users in China. Easy on-ramp.
- liadgez/ticktick-mcp-server 100% API coverage (112 ops) plus a local cache to fix TickTick's missing "list all tasks" endpoint.
Apple Reminders
- FradSer/mcp-server-apple-events Native EventKit, not AppleScript, so it doesn't crawl on a real Reminders database. Now covers Calendar too; recurrence rules and location triggers come along for the ride.
- mggrim/apple-reminders-mcp-server 18 tools with chrono-node parsing natural-language dates ("next Tuesday at 4," "in two weeks"). List-color and emblem control if you care about the visual side.
- shadowfax92/apple-reminders-mcp AppleScript-only, basic CRUD. Smaller surface, easier to audit before letting an LLM near your reminders. (Dormant since early 2025.)
Microsoft To Do
- jordanburke/microsoft-todo-mcp-server 13 tools through Microsoft Graph with OAuth auto-refresh. Personal, work, and school tenants from one config file.
Google Tasks
- arpitbatra123/mcp-googletasks TypeScript, full CRUD, sub-tasks, due-dates. The pragmatic Google Tasks pick.
- zcaceres/gtasks-mcp TypeScript, the standard OAuth desktop-app flow. Drop in a
client_secret.jsonand you're running.
Habitica
- iBreaker/habitica-mcp-server Tasks and checklists are the productivity half; pets, mounts, shop, and skills are the rest. 8 capability domains in one server, all gamified.
TaskWarrior
- awwaiid/mcp-server-taskwarrior Wraps the local
taskbinary. Set up TaskWarrior once, get an LLM-friendly interface for free. - acebaggins/taskwarrior-mcp Real-time updates and prompt scaffolding so the model knows what to do next without you spelling it out.
- meirm/taskwarrior-ng A full web app on top of TaskWarrior, plus MCPO to expose the same MCP server as REST. Useful when you want both interfaces.
Amazing Marvin
- bgheneti/Amazing-Marvin-MCP Daily overview, time-range analytics, label/tag filters, time tracking. Smithery one-line install.
- LucaDeLeo/amazing-marvin-mcp Smithery-hosted, FastMCP, ten tools. The lowest-friction way to try Marvin's MCP at all.
Remember The Milk
No native community MCP server. RTM users currently rely on Zapier's MCP wrapper for Remember The Milk actions. Genuine gap if you want to fill it.
Time-blocking & calendars
Sunsama
- Official: api.sunsama.com/mcp Hosted, OAuth, Streamable HTTP. Tasks and workflows, no setup beyond authorize.
- robertn702/mcp-sunsama 15 task tools with GitHub and Gmail integrations baked into
create-task. Stream and group operations included; HTTP-Basic-Auth option for self-hosted setups.
Reclaim.ai
- johnjhughes/reclaim-mcp-server 14 task-lifecycle tools. Documents the COMPLETE-means-scheduled-block-ended trap so you don't fall in it.
- universalamateur/reclaim-mcp-server 40 tools across tasks, calendar, habits, focus time, and analytics. The biggest Reclaim surface you'll find.
Motion
- h3ro-dev/motion-mcp-server Built-in rate limiting that self-throttles to a conservative 12 requests every 3 minutes (well under Motion's 12-per-minute cap) so you don't get throttled mid-loop. SQLite persistence across restarts.
Routine
- Official First-party local server (
npx routine-mcp-server; needs the Routine desktop app running and Node 18+). Calendars, tasks, and notes from the daily-planner app.
Project Management
Asana
- Official:
mcp.asana.com/v2/mcpStreamable HTTP, OAuth 2.1, GA in early 2026. The V1 SSE endpoint died May 11, 2026; if you're still pointing there, you're broken. - roychri/mcp-server-asana
READ_ONLY_MODEif you don't trust the LLM yet, custom-field operations if you do. ~137 stars and still active. - n0zer0d4y/asana-project-ops Enterprise fork of roychri with batch operations, direct section assignment, and selective tool activation.
ClickUp
- Official:
mcp.clickup.com/mcp~50 tools across 14 categories, OAuth 2.1 with PKCE. No delete tools, intentionally. Rate limits depend on plan and the Everything-AI add-on. - taazkareem/clickup-mcp-server Multi-account, hybrid OAuth/API-key, fuzzy global search, persona-based tool filtering. The community option people stayed on after ClickUp went official.
- hauptsacheNet/clickup-mcp Three modes (read-minimal, read, write) and append-only descriptions, so the LLM can't blow away your notes by accident. Image support with size budgeting for token-conscious agents.
Linear
- Official:
mcp.linear.app/mcpIssues, projects, milestones, comments, teams, cycles, initiatives, roadmaps, documents. Full surface, OAuth 2.1. - tacticlaunch/mcp-linear Goes deeper than the official: cycles, milestones, roadmaps, saved views, templates, custom fields, webhooks, audits, rate-limit health checks.
- dvcrn/mcp-server-linear Multi-workspace via tool prefixing. The right pick if you run Linear across several agencies or clients. (Lightly maintained; last updated April 2025.)
Jira / Confluence (Atlassian)
- Official:
mcp.atlassian.com/v1/mcp(Rovo) Cloud-only but covers Jira, Confluence, Compass, and Bitbucket Cloud in one server. SSE endpoint deprecates June 30, 2026. - sooperset/mcp-atlassian 5,000 stars and 72+ tools across Jira (Cloud + Server / Data Center) and Confluence. The only good answer for self-hosted Jira. Patch to v0.17.0+ for the Feb 2026 RCE/SSRF fix.
- aashari/mcp-server-atlassian-jira Five generic HTTP tools that hit any Jira API endpoint, with TOON responses for 30β60% token savings on big issues.
Monday.com
- Official: mondaycom/mcp Hosted at
mcp.monday.com/mcp, OAuth 2.1. Boards, items, columns, groups, plus Dynamic API Tools that give you full GraphQL access on the fly. - Prat011/mcp-server-monday Python via uvx, Smithery-installable, Docker option. Pragmatic and quick. (Formerly
sakce/mcp-server-monday; the repo was transferred, not forked.)
Notion
- Official: makenotion/notion-mcp-server 4,257 stars. v2.0 uses the data-sources abstraction from API 2025-09-03. Notion is steering toward the hosted
mcp.notion.com/mcp. Heads-up: there's an open prompt-injection-via-page-content advisory (#238 at last check). - suekou/mcp-notion-server Markdown conversion to cut tokens, tool allowlist via
--enabledTools. The community server that makes Notion responses LLM-readable. - awkoy/notion-mcp-server Production-positioned: Zod-validated, batch operations, comments, search, archive/restore.
Trello
- GabrielRamirez/trello-mcp 73 tools across nine categories, Docker-ready, remote HTTP support. The most thorough Trello server in the catalog.
- delorenj/mcp-server-trello Built-in token-bucket rate limiting (300/10s per key, 100/10s per token) and persistent board switching. Actively maintained (SSRF protection and due-reminders landed mid-2026).
- adriangrahldev/advanced-trello-mcp-server Production-hardened HTTP layer: keep-alive, exponential-backoff retries with jitter, batch tools, attachment downloads.
Shortcut
- Official: useshortcut/mcp-server-shortcut Hosted at
mcp.shortcut.com/mcp(OAuth) or local stdio (PAT). Stories, epics, iterations, objectives, docs, custom fields. Ship-safe withSHORTCUT_READONLY=trueand aSHORTCUT_TOOLSallowlist.
Wrike
- Official:
mcp.wrike.comHosted. Task queries, folder/project navigation, prioritization, and meeting-to-task conversion.
Smartsheet
- Official Hosted. Sheet read/summarize, row CRUD, attachments. Requires a Business / Enterprise / Advanced Work Management plan.
- josh-cornett/smartsheetmcp TypeScript, Streamable HTTP and SSE, broad endpoint coverage with documented pagination so the LLM doesn't silently truncate your sheets.
- terilios/smartsheet-server Healthcare-analytics flavor: clinical-note summarization, sentiment, batch analysis on top of Smartsheet.
Plane
- Official: makeplane/plane-mcp-server 100+ tools across ~19 modules. OAuth at
mcp.plane.so/http/mcp, PAT atmcp.plane.so/http/api-key/mcp.
Basecamp
- georgeantonopoulos/Basecamp-MCP-Server 79 tools, OAuth 2.0 with auto-refresh, chmod-protected secrets. The most complete Basecamp 3 option.
- BusyBee3333/basecamp-mcp-2026-complete 50+ tools targeting Basecamp 4 specifically. (New and lightly proven.)
- No official Basecamp MCP; the company hasn't shipped one.
Backlog (Nulab)
- Official: nulab/backlog-mcp-server First-party. Project, issue, wiki, attachment management.
- katsuhirohonda/mcp-backlog-server Adds prompts and analytical templates so the LLM has a starting posture. (Low adoption, quiet since early 2025.)
Dart
- Official: its-dart/dart-mcp-server Native MCP for Dart's AI-first PM platform. Tasks, docs, projects. (The local server is now deprecated in favor of Dart's hosted MCP.)
Fibery
- Official: Fibery-inc/fibery-mcp-server Natural-language interaction with Fibery workspaces. Python. (This local server is deprecated; Fibery now hosts one at
mcp.fibery.io/mcp.)
Taskade
- Official: taskade/mcp Projects, tasks, workspaces, OAuth.
Notes
Notion
See Project management above.
Obsidian
- MarkusPfundstein/mcp-obsidian ~3,472 stars. Connects through the Local REST API plugin. Where almost everyone starts.
- bitbonsai/mcpvault ~1,133 stars and lightweight. Picks up speed when MarkusPfundstein's gets too heavy.
- StevenStavrakis/obsidian-mcp ~693 stars with a broad tool surface. Fits well alongside Templater-driven vaults.
For the Obsidian Tasks plugin specifically, jfim/obsidian-tasks-mcp parses both emoji and Dataview syntax directly from markdown, no REST API needed.
Logseq
- ergut/mcp-logseq Hooks into Logseq's Local HTTP API, with optional vector search via local Ollama. DB-mode supported, tag-based privacy excludes work fine.
- eugeneyvt/logseq-mcp-server Search/Get/Edit/Delete unified-tool architecture, template enforcement, soft-delete safety. Fewer tools, fewer ways to misfire.
- joelhooks/logseq-mcp-tools TypeScript. Journal summaries, graph analysis, DataScript natural-language queries. Closest thing to a research assistant for your Logseq graph.
Roam Research
- 2b3pro/roam-research-mcp Comprehensive API access to Roam graphs. Block references, queries, page CRUD.
Apple Notes
- sirmews/apple-notes-mcp Read-only: lists and searches by reading the Apple Notes SQLite database directly (needs Full Disk Access). No creating or editing. (Archived since late 2024.)
- RafalWilinski/mcp-apple-notes Semantic search via a LanceDB vector store. The one to pick if you've been hoarding Notes for years and want to query them like a brain.
Bear
- netologist/mcp-bear-notes Reads Bear's SQLite directly: search by title, tag, or content. K8s/code/YAML helpers built in.
- akseyh/bear-mcp-server Plain text search over your Bear library, straight from the SQLite. No embeddings.
Airtable
- domdomegg/airtable-mcp-server PAT-scoped, schema discovery, read/write, search, comments. Distributed via .mcpb (Claude Desktop extension), pre-listed in Anthropic's MCP Registry.
- rashidazarang/airtable-mcp v4 with 42 tools: full CRUD, comments, schema, webhooks, batch ops, AI-prompt templates.
- jordan-huffman/airtable-mcp-server Fixes the "everything is a string" gap of the popular forks: proper handling of single-select, date, formula, and checkbox fields.
Dev
GitHub Issues + Projects
- Official: github/github-mcp-server ~29,200 stars; one of the most-starred MCP servers anywhere. Local binary, Docker, hosted remote variant. Watch out: the
projectstoolset is off by default. FlipGITHUB_TOOLSETSor--dynamic-toolsets. - taylor-lindores-reeves/mcp-github-projects Pre-dated official Projects support. Auto-generated GraphQL types and an
ALLOWED_REPOSwrite-restriction list make it good for sprint workflows. - idosal/git-mcp Turns any GitHub repo into a doc/code source for retrieval. Not for issue management; the right tool for "what does library X actually do."
GitLab
- Official: GitLab Duo's built-in MCP server Issue + MR creation and code search since GitLab 18.5; assignees, reviewers, labels, and milestones added in 18.8. Works on Cloud and self-managed.
- zereight/gitlab-mcp The community wrapper to reach for when Duo isn't an option.
- nguyenvanduocit/gitlab-mcp A lighter, more selective alternative; zereight's is the one with the broader API surface.
Bitbucket
- Official (via Atlassian Rovo) PR lifecycle, pipelines, deployments, all in the same Atlassian server. API-token only; no Bitbucket OAuth.
- b1ff/atlassian-dc-mcp Purpose-built for Atlassian Data Center, with OS-keychain secret storage. Separate
@atlassian-dc-mcp/{jira,confluence,bitbucket}packages. - aashari/mcp-server-atlassian-bitbucket Generic-tool design: a few HTTP-method tools that hit any endpoint. Sister project to aashari's Jira server.
YouTrack
- tonyzorin/youtrack-mcp ARM64 + AMD64 Docker images on ghcr.io and Docker Hub. The path of least resistance for self-hosted YouTrack.
- GaijinEntertainment/youtrack-rocket-mcp Async Python FastMCP with smart field caching. Faster than the alternatives on big projects.
Redmine
- runekaagaard/mcp-redmine Closest to 100% Redmine API coverage. ~172 stars, quiet since January 2026.
- jztan/redmine-mcp-server 45 tools, every auth mode (API-key, Basic, OAuth2), prompt-injection protection, Docker. OAuth2 wants Redmine 6.1+.
Taiga
- talhaorak/pytaiga-mcp Epics, user stories, tasks, issues, sprint tracking, verbosity controls. The Taiga server you'll actually keep installed.
OpenProject
- AndyEverything/openproject-mcp-server Python async with a 23-parameter work-package filter. Made for the people who actually use OpenProject's filter UI.
Vikunja
- 0xK3vin/vikunja-mcp 11 capability domains: kanban, relations, views, notifications, teams. The polished pick.
- democratize-technology/vikunja-mcp API-token + JWT auth, smart hybrid filtering that falls back to client-side when the server can't help. Cleaner architecture than most.
- aimbitgmbh/vikunja-mcp Safety controls (
ENABLE_PROJECT_DELETEetc., default false because Vikunja has no trash). Tested withgpt-oss:20bif you're going local.
Generic / Self-Hosted
These don't wrap an external SaaS. They are the task system, designed for AI workflows from the start.
- cjo4m06/mcp-shrimp-task-manager ~2,087 stars. Chain-of-thought, reflection, style consistency, all wired into a task store the agent can plan against.
- eyaltoledano/claude-task-master (TaskMaster) The one most coding agents reach for in IDE workflows.
- eyalzh/kanban-mcp Kanban for multi-session AI workflows. Useful when several agents are working in parallel and you need a board to mediate.
Back to Checking Boxes
I still abandon my TODO list. I'll ignore it for a week, miss a project, let it drift. The difference now is that catching up isn't a weekend of grunt work, it's a sentence: "here's what changed, sort it out." The list rebuilds itself, and I get back to doing the stuff I actually wanted to do.
You Should Host a Website
Not have one. Host one.
Everyone tells you the same thing: you should have a website. A place the algorithm can't touch. A URL that's yours. Words that outlive the platform.
They're right. But this isn't a post about having a website; it's about hosting one.
Decade of Hosting
I've been running websites since 2014. From WordPress onward, through a handful of CMSes, none of them have made me money. None have been wildly successful. All of them taught me more about running a real service on the internet than any job ever did.
Hosting forces you to see the full stack. Before you see a working page, you need three things:
- A domain
- A server
- A CMS
After that, the web opens up with endless possibilities to tinker. To name three:
Web development. I started because the theme didn't have a contact form. Then I wanted a landing page. Then I wanted the whole layout rewritten. Within a few months I could scaffold a component, wire up a build, and deploy without thinking. None of it was "job" work.
Web design. I'm not a designer. But running my own site meant the stakes were zero, so I designed anyway. I picked fonts. I argued with myself about spacing. I redesigned the nav three times in a weekend.
Something odd happened along the way: I became opinionated. I'd see a well-designed site and think can I do something like that? I started noticing other people's patterns, their hierarchy, their whitespace. I shifted from user to contributor, an active participant in the ecosystem.
Ops. The frontend was the fun part. Then came everything underneath, roughly ranked by how much each will ruin your day when it breaks:
- Reliability. Is the site actually up? Does it stay up when you push? Do you know when it's not?
- Security. Any open ports? TLS 1.3? Are your admin panels behind a login that a bot can't guess in an afternoon?
- Performance. Is anything cached? How long is first paint? Are your images doing work they don't need to?
- Observability. When things break, do you hear about it from your logs, or from a friend texting you "hey, your site's down"?
- Accessibility. Alt text. Contrast. Semantic HTML. The baseline is cheap; skipping it is rude.
Every one of these is a specialization; every one is yours to obsess over or ignore. It's a gift and a curse.





Or Not!
Self-hosting isn't for everyone. Reasons to skip:
- Money. Self-hosting is often more expensive than a managed blog once you value your own time. If you're counting hours, the math rarely works in your favor.
- Time. Other side projects fail quietly in staging. A self-hosted site fails loudly, in production, at the worst moment. It asks for attention even when you have none to give.
- Data responsibility. You own the data, which means you also own the backups, updates, abuse reports, and the incident when something goes wrong.
If any of those rings true, self-hosting isn't right for you. But I still think you should have a corner of the internet. Any of these will give you one without the operations tax:
Getting Started
If you're still curious, here's a rundown of hosting options.
If you haven't used AI for development, start here. A chatbot is the closest thing you'll get to pair programming with a patient senior web developer. Tell it your vision, let it walk you through the tradeoffs, have it vibe-code you through the parts that feel over your head.
Pick a Domain
Registrars that don't upsell you into a funnel:
Pick a .com if you can get one; a .co or .dev if you can't. Don't overthink it, you can always move a domain.
Pick a Host
For a real server: DigitalOcean, Linode, or Hetzner will rent you a VPS for a few dollars a month. If your site is static, Cloudflare Pages, Netlify, and Vercel have generous free tiers.
Pick a CMS
Pick one and commit:
- Ghost for a modern blog with a good admin
- WordPress if you want every plugin ever made
- Jekyll, Hugo, or Eleventy if you want static output and don't mind the build step
- Whatever you vibe-code yourself if you want to learn the most
You can (and probably will) migrate later, so pick one to get started.
Your Corner
The best reason to host your own site isn't cost, control, or credibility. It's that the web stops being something that happens to you and starts being something you make. You stop reading the internet and start writing it.
That's worth more than any plan.