Skip to main content
Glama

Worklog

A FirstMate Plugin that keeps what you work on from one Meeting to the next, and the free Notes that belong to no Meeting.

Read CONTEXT.md for the words this project uses — Entry, Note, Status, Meeting, Cycle — and docs/adr/ for why a Cycle starts when Scheduler says so and why the data is in SQLite.

Install it

One command, from its git URL. The files land in FirstMate's Shelf, the Plugin is registered in the same step, and nothing it ships is run:

firstmate install https://github.com/luanAfons0/worklog.git worklog
systemctl --user restart firstmate

Then open the Index Page, find worklog, and open its Plugin Page.

To let Scheduler start a Cycle at every Meeting, record a Grant from Scheduler to Worklog and restart again. A Grant is one way and covers one pair:

firstmate grant scheduler worklog
systemctl --user restart firstmate

Developing it instead? Register the directory where it already lives:

node src/cli.ts add worklog /absolute/path/to/worklog   # in FirstMate

See CONTRIBUTING.md for the rest.

The Plugin Page has three tabs: Cycle, Earlier Cycles and Notes. The keys 1, 2 and 3 choose one, and N starts a new Entry. Drag an Entry to another column to give it that Status, or up and down to set its place in the column; the Meeting lists each section in that order. In a Note, Shift+Enter saves it.

It needs Node 24 or newer, for TypeScript with no build step and for node:sqlite. The Host's service PATH often has only an older Node, so mcp looks for one in this order: WORKLOG_NODE, node on PATH, then every Node under nvm. With none, it says so in one sentence and the Plugin is Stopped.

Related MCP server: MCP Backlog Server

What it keeps

  • An Entry is one thing you work on: a title, an optional Markdown body, and a Status — Todo, In Progress, In Review or Done.

  • A Cycle is the time from one Meeting to the next, named by the moment it started. A new Entry goes into the current Cycle. The first Cycle starts by itself the first time Worklog needs one.

  • When a Cycle starts, every Entry that is not Done moves into it with its Status unchanged. It is the same Entry, not a copy. Done Entries stay in the Cycle they were done in.

  • An Entry that is not Done is always in the current Cycle. Set a Done Entry in an earlier Cycle back to any other Status, and it moves into the current Cycle in the same write.

  • Every Cycle is kept. The Page lists the earlier ones, newest first, each named by the moment it started; open one to see what was Done in it.

  • A Note is free Markdown text. It has no Status and belongs to no Cycle, so it never moves. Notes are listed newest first.

Everything lives in one file, worklog.db, in the Plugin directory. Git ignores it. Worklog starts empty. A Plugin directory from before the rename to Worklog holds daily.db instead; the first start renames it to worklog.db, with every Cycle, Entry and Note in it.

The Popup form

web/new.html is a small second page: choose Entry or Note, type, press Enter. An Entry has a title, a body and a Status that starts at Todo; a Note has only a body. Shift+Enter is a new line in the body. After a save the page goes to the main Plugin Page, ./.

It is the page a FirstMate Shortcut opens in a Popup. Going to ./ leaves the Popup's address, so the Popup hides by itself. In a normal browser, at /p/worklog/new.html, it lands on the main page instead. Once the Shortcut work lands in FirstMate, bind it with:

node src/cli.ts bind <keys> worklog new.html   # in FirstMate

Tools

Every tool answers its data twice: as JSON text, and as structuredContent. A tool given bad input answers a JSON-RPC error with one sentence.

Tool

Arguments

Answers

start_cycle

none

one sentence, and { cycle, moved, said }

get_cycle

optional id

that Cycle, or the current one, and its Entries

list_cycles

none

{ cycles }, newest first, each with counts by Status

create_entry

title, status, optional body

the new Entry

update_entry

id, and any of title, body, status

the Entry as it now is

move_entry

id, and status, before (optional)

the Entry in its new place

delete_entry

id

the Entry that is gone

meeting_markdown

none

the Markdown, and { markdown, done, inReview, workingOn }

list_notes

none

{ notes }, newest first

create_note

body, title (optional)

the new Note

update_note

id, body, title (optional)

the Note as it now is

delete_note

id

the Note that is gone

start_cycle is the tool a Scheduler Job calls at every Meeting, under a Grant from Scheduler to Worklog. Every call starts exactly one Cycle (ADR-0001), and its text is one sentence, because a Scheduler Run keeps one: Started the Cycle of Tue 23 Sep 10:00 and moved 4 Entries into it. The moment is on the clock of the machine Worklog runs on. The Page's Start a new Cycle button calls the same tool, after one question, for the day Scheduler did not.

meeting_markdown decides what the Page's Start presentation shows: one Entry at a time, full window, for the Statuses chosen at the top. It has a "Done" section — the Entries Done in the Cycle before the current one, then those already Done in the current one — an "In review" section, when anything is In Review — and a "Working on" section — the current Cycle's In Progress Entries, then its Todo ones, each in the order of its column. It lists titles only. Present after the Meeting's start_cycle has run; before, "Done" also holds what was reported last time.

Any Status may go to any other. A body of null or "" takes the body away. Bodies are Markdown; the Page shows them formatted with web/markdown.js, a small renderer written for this Plugin, so the Page loads nothing from a CDN.

Running it

./mcp is the Plugin Server, as the Host runs it: MCP over stdio. npm test runs every test; npm run typecheck checks the types.

Licence

MIT. See LICENSE.md.

Maintenance

ActivityMaintained
ResponsivenessResponsive

Related MCP Connectors

Related MCP Servers