Skip to content
tylamb1Public

About

task management system that integrates them with Clyde

Resources

Stars

0 stars

Watchers

0 watching

Forks

Repository files navigation

Task

A small, self-hosted task board that Claude can read and write.

Projects are columns, tasks are cards. Each card has a subject, a body, who it's assigned to, who created it, a due date, a priority, and a running list of notes. People add tasks on the site or straight from a Claude conversation, and everyone on a project sees the same board.

Node 22 · Express · EJS · PostgreSQL · Docker. One container plus Postgres; no build step.

What it does

  • Board - one column per project you belong to, cards sorted by due date then priority. Overdue and due-today cards are flagged; "Assigned to me" and "Show done" toggles. Quick-add box at the bottom of every column.
  • Cards - subject, body, assignee, creator, due date, priority, notes. Every reassignment, due-date change, done/reopen and move is recorded on the card with who did it and when.
  • Projects - whoever creates a project owns it and adds people by email. Adding someone who has never signed in creates their account, so an invite is all a new person needs. Members see only their projects; site admins see all. Owners can transfer ownership, remove members, and delete the project.
  • Claude - the site is also an MCP server with its own OAuth 2.1 authorization server. Each person adds it once as a custom connector in Claude (web, desktop, mobile, or Claude Code), approves it, and from then on Claude can list, add, assign, note, complete and move tasks as that person. The /connect page in the app has the exact steps.
  • Sign-in - no passwords. Email one-time codes, passkeys (Windows Hello, Face ID, security keys), Google, and Microsoft (personal and work/school accounts). Only people on the allowlist (users) can get in; project owners add to it when they add members, admins can edit it at /admin/users.

Run it

git clone https://github.com/tylamb1/task && cd task
cp .env.example .env        # set SITE_URL, BOOTSTRAP_ADMIN_EMAIL, and (for real email) RESEND_API_KEY
docker compose up -d

Open SITE_URL (default http://localhost:3000). The first sign-in as BOOTSTRAP_ADMIN_EMAIL becomes the admin: use "Email me a code" - without RESEND_API_KEY the code is printed to the container log (docker compose logs web).

For anything public put a TLS proxy (Caddy, Traefik, nginx, Dokploy...) in front of port 3000. Passkeys, Google and Microsoft sign-in, and Claude's connector all require https, and SITE_URL must be the public https address.

Local development

npm install
cp .env.example .env
docker compose up db -d            # Postgres on localhost:5432
set -a; . ./.env; set +a           # or use a .env loader of your choice
npm run dev                        # http://localhost:3000, restarts on file changes

Migrations in migrations/*.sql run automatically at startup, once each, in filename order.

Tests

npm test                                                               # pages that need no database
DATABASE_URL=postgres://task:task@localhost:5432/task npm test         # plus the database, OAuth and MCP tests

The database tests truncate the tables they use; point them at a throwaway database.

Configuration

Everything is an environment variable; .env.example documents each one.

Variable Purpose
DATABASE_URL Postgres connection string
SITE_URL Public origin, e.g. https://task.example.com. Drives cookies, passkeys, OAuth redirect URIs and the MCP URL
APP_NAME Name shown in the header, emails and to Claude (default Task)
TZ Time zone for "today" and "overdue"
BOOTSTRAP_ADMIN_EMAIL Becomes the first admin when the users table is empty
RESEND_API_KEY, MAIL_FROM Outbound email via Resend. Blank = print to console
GOOGLE_CLIENT_ID/SECRET Enables "Continue with Google". Redirect URI: SITE_URL/auth/google/callback
MICROSOFT_CLIENT_ID/SECRET Enables "Continue with Microsoft". Redirect URI: SITE_URL/auth/microsoft/callback. Register the app for "any organizational directory and personal Microsoft accounts"; set MICROSOFT_TENANT to a tenant id to restrict it

Running two copies (say one for home and one for work) is two deployments of the same image with different .env files and databases.

Connecting Claude

Signed-in people get the steps at /connect. In short: Settings → Connectors → Add custom connector, paste SITE_URL/mcp, leave the client id/secret blank, click Connect, sign in, click Allow. For Claude Code: claude mcp add --transport http task SITE_URL/mcp then /mcp.

How it works: /.well-known/oauth-protected-resource/mcp points Claude at this site's authorization server (/.well-known/oauth-authorization-server). Claude registers itself (/register, RFC 7591), sends the person to /authorize (PKCE, S256), the person signs in and approves, Claude exchanges the code at /token, and calls /mcp with the bearer token. Access tokens last an hour, refresh tokens 90 days (sliding). Tokens are stored hashed. People can see and disconnect their connections on /connect.

Tools: list_projects, list_tasks, get_task, add_task, update_task, complete_task, reopen_task, add_note, delete_task, create_project, add_project_member. Projects are referred to by name, tasks by #id, people by name or email, and "me" is the signed-in person.

A useful line in a Claude Project's instructions: "Tasks for this project go in the Task project called Condo."

Layout

server.js            starts the app (runs migrations first, creates the bootstrap admin)
src/app.js           Express setup and route order (sessions → OAuth/MCP → same-origin check → browser routes)
src/db.js            shared pg pool  ->  db.query(sql, params)
src/migrate.js       applies migrations/*.sql once each, in order
src/render.js        res.page(view, locals) renders a view inside views/layout.ejs
src/auth/            sign-in: email codes, passkeys, Google/Microsoft, sessions, CSRF guard
src/data/            users, projects (membership), tasks (cards and notes) - all SQL lives here
src/routes/          board, projects, tasks, connect pages
src/oauth/           the authorization server (provider.js) and the consent page
src/mcp/             the MCP endpoint and its tools
src/admin.js         /admin/users
migrations/          001 auth tables, 002 projects/tasks/notes, 003 OAuth clients/codes/tokens
views/, public/      EJS templates and static files (one stylesheet, no front-end build)
test/                node --test; database tests skip unless DATABASE_URL is set

Deploy with Dokploy (example)

  1. Create a Postgres service; copy its internal connection string.
  2. Create an Application from this repo, build type Dockerfile, env from .env.example with DATABASE_URL from step 1 and SITE_URL=https://your.domain.
  3. Add the domain with HTTPS on, container port 3000. Deploy. Check https://your.domain/healthz.

Every push to main then redeploys.

License

MIT

About

task management system that integrates them with Clyde

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages