Work / Agents and botsopen brief

Stackline: a team task board run from Claude and ChatGPT

What it was

Dodil wanted a Trello replacement on its own cloud: a board for a small team, run from Claude and ChatGPT over MCP, with roles, a change log and a structure anyone copies with one command. Judged by working code in a public repository; the score sheet gave 30 for the core and roles, 25 for MCP, 20 for code, 15 for extras, 10 for polish.

What we did

Built Stackline on FastAPI over the Dodil cloud: boards, lists, numbered cards, drag and drop, owner, member and viewer roles, a "was and is" change log. One MCP endpoint with 28 tools and three commands, OAuth with PKCE. The set_up_board tool makes a board from one sentence. Two versions in two days, 47 tests, deploy through Dodil CI on every push.

What the client got

A live site with three demo sign-ins and no registration, open code under MIT, a live check of 11 of 11 on the real database and Dodil models. The first version got 3 stars from the owner, and by the data we gathered that is the most he gave anyone. The cloud cost $0: the Free plan with a hard ceiling.

ClientDodil, open brief on Freelancer
My roleBrief analysis, architecture, code, tests, design, submission texts. Dodil sign-up, CLI login and every go-ahead to publish by Dmytro
StatusTwo entries submitted, the first got 3 stars from the owner, results after 19 November 2026
Result47 tests in the second version, live check 11 of 11 on the real DataK3 database · Open
Rejected: the first version in a newspaper style. Pretty, but the judge hit a sign-up wall, there were no demo logins, and Claude connected only after manual approval. 3 stars
Rejected: the first version in a newspaper style. Pretty, but the judge hit a sign-up wall, there were no demo logins, and Claude connected only after manual approval. 3 stars
Accepted: the second version's front page. "Tell Claude the goal. Get the board.", three demo sign-ins and a hint on connecting Claude. Touchable within a minute
Accepted: the second version's front page. "Tell Claude the goal. Get the board.", three demo sign-ins and a hint on connecting Claude. Touchable within a minute

The task

Dodil, a cloud for applications with its own database, sign-in, models and CI, opened a brief for a Trello replacement: a board for a team of three to five people, run from Claude and ChatGPT over MCP. The terms: roles, a change log, no external OpenAI or Anthropic keys, and a structure anyone copies with one “remix” command. One link to a public repository is submitted, and the judging is by working code.

A team wants a simple board, and questions like “what is on me this week” and “what is holding the launch” are better asked in words than clicked through filters. For Dodil the task is different: show that a full application comes together on their cloud in an evening.

Why, and what the idea was

The first version followed the score sheet from the brief. The starter repository covered about a third of the core, and the main risk sat in the remix “gate”. So the core first, then MCP, then the extras: an AI checklist from a card, similar cards by meaning, a daily summary, “what is blocking the launch” along the chain, automatic overdue flags.

The second version was set by an independent review. It agreed that the three stars were not about the code: the judge could not touch anything within two minutes. The live link hit a sign-up wall, there were no demo logins, and Claude connected only after a client was approved by hand in our pool. The newspaper with the blackletter masthead read as an art project, not a platform template. And we turned out to be one of six similar entries with the same tables and 24-26 tools, so “26 tools” stopped being an argument.

Hence the plan: access first, then one end-to-end scenario, “a board from a sentence”, then the face. We deliberately dropped comments, schema migrations and the race for test counts.

How it went

When What happened
Day 1, morning Brief and rules analysed, a plan. The core locally on stubs: boards, lists, cards, roles, log, 26 MCP actions, web with drag and drop, extras. 24 tests. A security self-check found 2 holes, closed, 26 tests
Day 1, afternoon Dmytro signed up on Dodil and logged into the CLI. The starter remixed, its tables replaced with ours, CI deployed. Live check on the real database and models 9 of 9
Day 1, afternoon MCP checked the way Claude connects: OAuth through the pool, Dmytro’s login, 4 phrases from the brief, someone else’s board invisible. The “Index cards” design rejected, a newspaper with a night edition made instead
Day 1, evening Repository public, the first entry submitted. The same day the owner gave 3 stars with no comment
Day 2, morning A review by five independent advisers in the role of the owner and Dodil’s judges: each read the brief, our code and 10 public competing entries
Day 2, afternoon The second version: set_up_board, a sample board, a public demo for three roles with a reset, MCP prompts and tool annotations. Three design options, Dmytro picked A. 47 tests, live check 11 of 11
Day 2, evening Code pushed, CI green, demo users created by Dmytro. The second entry submitted. The per-entrant limit of two reached

Tools and method

Python and FastAPI, light DDD: a domain layer with the role rules, application with the shared scenarios, infrastructure with DataK3, sign-in and models, and two “doors”, web and mcp, that call the same scenarios. About 1,900 lines in app/ and 800 lines of tests.

Data in DataK3, Dodil’s cloud database over DuckDB: 7 tables from schema.sql, a change log with “was” and “is” fields. Sign-in through the appid user pool behind a gateway: a forged header around the gateway gets 401. Claude connects over OAuth with DCR and PKCE; Claude and ChatGPT have their own registered clients with no manual approval step. AI only from Dodil Models: the kimi-k2.7-code chat and jina-embeddings-v4 embeddings cached per card, no external keys in the project.

MCP: one /mcp endpoint, 28 action tools and three slash commands: /standup, /plan_my_week, /unblock. Every tool is marked “read only” or “changes or deletes”, so Claude asks before deleting. set_up_board assembles a board from a sentence: dates counted back from the launch date, “blocked by” links in place.

Runs on Ignite, deployed through Dodil Git CI on every push: test, build, deploy, remix check. An empty remix is not empty: a new copy opens a sample board with an overdue card, a blocker chain and history, and the demo has a reset button so the next judge does not see the previous one’s mess.

Result

A live site: the front page “Tell Claude the goal. Get the board.”, three demo sign-ins, owner, member and viewer, and a hint on connecting Claude. A board with drag and drop, card numbers, overdue cards with a red edge and “waits on #4”, search, “My plate”, “Overdue”, a daily summary and an activity log. Someone else’s board is invisible by number, by name and through search, the same on the page and in Claude.

Numbers: 24 tests in the first build, 27 in the first submitted entry, 47 in the second. The live check on the real DataK3 bucket and Dodil models 9 of 9, then 11 of 11. CI: test, build, deploy, remix passed. The first entry got 3 stars, and by the data we gathered the owner gave no one more: 3 stars on 7 entries out of 43.

Weak spots, plainly. A full remix into another organisation was not run: on Free one organisation has only one user pool, and the test copy failed on that limit. The connection in the Claude web app specifically is untested; the same protocol was checked with our own client and Claude Code. ChatGPT is registered as a client but was not tried live in ChatGPT.

What we do not know yet: the results. The owner chooses after the brief closes and has up to 30 days to judge. We will add it when it comes.

Mistakes and what we took from them

A judge rates what they managed to touch in two minutes.The first version's three stars were not about the code. Demo sign-ins, a sample board and a first line of the entry saying "what we fixed after your 3 stars" matter more than another ten features.
A deleted card's number went to a new card together with its history.And a stale board save brought back a removed member. The security self-check found it before publication. Numbers are never reused now, and members, lists and boards are written separately.
The kimi-k2.6 model took 28-40 seconds for a short summary against Ignite's 60-second request limit. We moved to kimi-k2.7-code, usually 2-7 seconds, but Free returns 429 after several calls in a row. So the board plan in Claude is made by Claude itself, and Dodil Models is called only by the web page.
Remixing the starter brings the starter's tables, and `schema.sql` runs only when the bucket is created. The empty tables had to be dropped and ours created by hand.
DataK3 runs on DuckDB: DATE comes back as a timestamp and `at` turned out to be a reserved word. Dodil's documentation does not say so.
`dodil data connect` prints the session token right in the connection string.Easy to paste into a log or a chat by accident. We worked so that the token went nowhere, and checked the commit history for secrets before publishing.

Tools

PythonFastAPIDodil DataK3Dodil appidDodil IgniteDodil ModelsMCP (OAuth, DCR, PKCE)pytestClaude Code