Agentero
에이전트를 연결해 로컬 Vault에 연구 컨텍스트를 보관·Zotero에서 무결점 이동·읽고 이해·재활용
오픈소스 GTD 앱: 텔레그램 봇, 인박스, 프로젝트, 컨텍스트, 주간 검토 제공, 웹 및 텔레그램 지원
Бесплатное GTD-приложение с открытым кодом: задачи через Telegram-бот, Inbox, проекты, @контексты и Weekly Review. На сайте и в Telegram.
생산성Python · HTMLGitHub @alxndr-bnd온라인운영자 미확인
써 보셨어요? 한 번만 눌러 주세요. 로그인은 필요 없어요.
Free GTD (Getting Things Done) task manager: web app + Telegram bot. Capture in one tap, clarify later. FastAPI + Postgres, MIT.
저장소 README에서 가져옴
README 전체를 불러오는 중입니다.
README 전문 보기 ↗Serbito GTD is a free task manager built around David Allen's GTD method: capture everything in a second, clarify it later, do the next action. On the web and in Telegram, one account for both. Hosted at gtd.serbito.rs · bot @gtdsrbot.
FastAPI + PostgreSQL, one container. English and Russian.
call mom tomorrow at 10am #Family @phone → task, reminder, project, context.@context on any task to open it. Recent in the menu keeps the last 5 projects and contexts one click
away, on every device.Details for contributors: docs/internals.md. What changed in each version: CHANGELOG.md (also on the site: What's new).
Claude and other MCP clients can work with your tasks: capture to the Inbox, list and search tasks, projects and
contexts, complete and edit a task, move it to another list, project or context, and run the Weekly Review.
The server address is https://gtd.serbito.rs/mcp (on your own server — BASE_URL/mcp).
You need only the address. No token.
Serbito GTD) and the URL https://gtd.serbito.rs/mcp. Leave the OAuth fields empty.
Press Add, then Connect.claude.ai), then press Allow.Any MCP client with OAuth sign-in works the same way: give it the address, sign in to Serbito GTD, and press Allow.
https://gtd.serbito.rs/mcp and OAuth authentication.~/.cursor/mcp.json, then press Connect next to it in Cursor Settings → MCP:
{ "mcpServers": { "gtd": { "url": "https://gtd.serbito.rs/mcp" } } }
.vscode/mcp.json:
{ "servers": { "gtd": { "type": "http", "url": "https://gtd.serbito.rs/mcp" } } }
claude mcp add --transport http gtd https://gtd.serbito.rs/mcp, then run /mcp and choose
Authenticate.Check the consent screen. The app sends its own name, and Serbito GTD does not check it. The screen also shows where the
access goes: a site (chatgpt.com), an app on this computer (localhost), or a desktop app (cursor://…). If you
did not start the connection yourself, or you do not know that address, press Deny.
Serbito GTD accepts these return addresses: any https:// site, http://localhost, 127.0.0.1 or [::1] on any port,
and the app links cursor://, vscode:// and vscode-insiders://.
To disconnect, open 👤 Account → 🤖 AI assistants → Connected apps and press Disconnect. Access stops at once. Removing the connector in the client may leave access open in Serbito GTD; disconnect it in Serbito GTD too.
claude mcp add --transport http gtd https://gtd.serbito.rs/mcp --header "Authorization: Bearer gtd_…"
Authorization: Bearer gtd_….mcp-remote bridge — command npx, arguments
["mcp-remote", "https://gtd.serbito.rs/mcp", "--header", "Authorization: Bearer gtd_…"].Ask, for example: “add ‘call the bank tomorrow 10am’ to my inbox”, “what are my next actions @phone?”, “complete #42”, “move #17 to the Renovation project”, “#12 is waiting for Anna”, “let's do the weekly review”.
| Tool | What it does |
|---|---|
capture | Captures a task, like the app and the bot: dates, #Project and one or more @contexts in the text work |
list_tasks | Lists a list (Inbox, Next, Waiting, Scheduled, Someday, Reference, Done, all); filters by project, context, text |
list_projects | Active projects with counts; marks projects without a next action; include_archived adds archived ones |
list_contexts | Contexts with counts of open tasks (a task with two contexts counts in both) |
complete_task | Marks task #N done |
move_task | Moves task #N to a list, a project (created if missing) and/or sets its contexts (one or several) |
update_task | Changes the title, notes or due date of task #N, or sets who it waits for (moves it to Waiting) |
archive_project | Archives a project: with its open tasks (tasks="archive") or only the project (tasks="keep") |
restore_project | Brings an archived project back with its archived tasks; past reminders are dropped |
weekly_review | Read-only summary: Inbox count, projects without a next action, empty projects, overdue, Waiting, next 7 days, Someday count |
The prompt process_inbox tells the assistant to clear the Inbox in the same order as the app: one task at a time,
oldest first, the five GTD questions.
https://claude.ai/api/mcp/auth_callback, the same on claude.com) or
to a program on your computer (http://localhost, 127.0.0.1, [::1]), exact match.Once: python3 -m venv .venv && .venv/bin/pip install -r requirements-dev.txt, cp .env.example .env,
createdb gtd. Then — local database, auto-reload on every change:
.venv/bin/uvicorn app:app --reload --reload-exclude .venv --env-file .env
.env points to the local database by default. The server applies the schema on startup, and
unreleased code must not change production. Connecting to production is explicit only — see
docs/deploy-gcp.md.--reload-exclude .venv is required: without it the watcher sees .venv and restarts the server in a loop.DEV=1 the sign-in screen has a Dev login button (first user), and without SMTP_PASSWORD the email
sign-in code goes to the server log instead of an email.DEV=1 live reload works: editing .py restarts the server, editing static/ doesn't, but either way
the open page refreshes itself within ~1 s (it polls /api/dev/version). Text typed in the capture field is
kept; an open task card postpones the refresh.BASE_URL) the bot uses long polling and won't start if the bot has a production webhook.Or with Docker: DEV=1 docker compose up --build — see self-hosting.
.venv/bin/playwright install chromium # once: the browser for the SPA smoke test
.venv/bin/python -m pytest -n auto --dist worksteal # in parallel, as the release gate and CI; without -n: one process
A temporary database in the local Postgres (brew services start postgresql@17, or TEST_PG_URL) is created
and dropped automatically, one per pytest-xdist worker. It is also dropped on Ctrl-C and SIGTERM; a test run
drops gtd_test_* databases that are older than 1 hour and have no connections (left by kill -9).
Telegram, Google and email are stubbed. tests/test_browser_smoke.py opens every
section of the app and the public pages in headless Chromium and fails on any JS error or CSP violation. The release
script runs the tests before tagging.
The CSP is report-only until CSP_ENFORCE = True in app.py. To run the smoke with the enforced policy before
that, set GTD_CSP_ENFORCE_IN_TESTS=1. In smoke tests, give wait_for_function a function ("() => window.x"),
not an expression: Playwright polls an expression through eval, and the enforced CSP blocks it.
CI (.github/workflows/ci.yml) runs on every pull request and every push to main:
the full pytest with the browser smoke, a lock check and an image build.
Versions are locked with hashes. You edit requirements*.in; requirements*.txt are generated, do not edit them.
| File | What | Installed by |
|---|---|---|
requirements.in → requirements.txt | app dependencies | the Docker image (pip install --require-hashes) |
requirements-dev.in → requirements-dev.txt | the same versions plus pytest and Playwright | developers and CI |
Update the lock with uv (brew install uv), then reinstall and commit .in and .txt together:
scripts/lock.sh # after an edit in requirements*.in
scripts/lock.sh --upgrade-package fastapi # one package to its latest version
scripts/lock.sh --upgrade # all packages
.venv/bin/pip install -r requirements-dev.txt
requirements*.in.uv), the base image digest and the actions.python:3.14-slim@sha256:…. Dependabot bumps the digest. The deploy still runs
apt-get upgrade once a day, so Debian security fixes do not wait for a new digest. A new Python minor version
is a manual change: the FROM tag and --python-version in scripts/lock.sh.## [Unreleased] in CHANGELOG.md:
### Added / Changed / Fixed / Security, one line - English text and right under it
- RU: Русский текст. Write what users can now do or what got fixed — not commit messages.main: scripts/release_minor.sh "Commit message" [new_file …]. First the CI gate (SERBITO-613,
scripts/ci_gate.sh): HEAD must be origin/main and every GitHub run on main for it must be green; it waits
up to 20 min for a running CI and refuses to release on red, cancelled or missing CI. A red run on main or
on a tag also opens a Highest ci-red bug in Jira (.github/workflows/ci-red.yml). Then it picks the next
tag vX.Y.0 and refuses to release if [Unreleased] has no entries. Otherwise it renames [Unreleased] to
## [X.Y.0] - <today> (with a fresh empty [Unreleased] on top), runs the tests, commits everything
in one release commit, tags, pushes, and creates the GitHub Release with that version's English entries.APP_VERSION from the tag: the footer,
the app menu and /changes show it (dev when unset, e.g. locally).## [X.Y.Z] section in CHANGELOG.md, so a tag pushed by hand
cannot ship without notes.vX.Y.Z tag with fresh Debian packages and redeploys it: same version, image <sha>-r<YYYYMMDD>. Trivy gates it
like a release; if the main page is not 200 after the switch, traffic goes back to the previous revision.scripts/indexnow.py sends every URL in
/sitemap.xml to api.indexnow.org (Bing, Yandex and other IndexNow engines; Google does not use it). The key
is the file static/<key>.txt, served at /<key>.txt; IndexNow keys are public by design. A network error or
a non-2xx answer prints a warning and does not fail the deploy. The weekly refresh does not ping. To ping by hand:
( prints the request and does not send it)./changes and /en/changes render CHANGELOG.md, parsed once at startup by changelog.py;
tests/test_changelog.py checks the format, both languages and that every tag has an entry.
MIT © 2026 Alexander Bondarchuk — free to use, modify and distribute, including commercially, as long as the copyright and license text are kept.
GTD® and Getting Things Done® are trademarks of the David Allen Company. This project is independent and not affiliated with the author of the method.
Also by No Handoff:
Made by No Handoff
python3 scripts/indexnow.py--dry-run