Added
-
Adopted JSON-RPC 2.0 as the wire protocol, framed as NDJSON over a local socket or over TCP.
The specification defines the payload and leaves the transport alone, so a client is implementable in any language. Failures come back as standard error codes.
-
Added timer notifications, the capability the protocol change was for.
A connection calling
timer.subscribereceivestimer.started,timer.began,timer.running,timer.durationSet,timer.paused,timer.resumed,timer.endedandtimer.stopped. -
Added the
watchcommand, which subscribes and prints the timer on every change until interrupted, so a status bar no longer has to poll. -
Added the
setcommand, exposing thetimer.setmethod that was previously reachable on the wire but not from the CLI. -
Added the
configurecommand, which generates an account from one of the documented cycle presets.It asks for the preset, names the account after it, then appends it to the configuration file, or prints it on stdout when declined, redirected or in JSON mode.
The append is plain text, so comments and formatting survive. A taken name is suffixed, and
defaultis claimed only when no other account holds it.A bare
comodoroand any command needing an account open with a welcome naming the missing file, then offer the wizard. Declining is a hook, not a gate: the command carries on.The generated account holds its cycles alone, since every other field has a default. Custom cycles, addresses, precision and hooks stay hand-written.
-
Added the
json-schema <DIR>command, writing one JSON Schema file per command emitting structured output, so a script consuming--jsoncan validate what it reads.Three land today,
comodoro-get,comodoro-watchandcomodoro-configure. The commands driving the timer report a confirmation rather than data, so they carry none. -
Turned Comodoro into a library as well as a binary, by merging the io-time crate into this repository.
Three layers: the timer and protocol types (the only no_std one, always compiled), a blocking client and server (
clientandserverfeatures), and the CLI (cli, default).
Changed
-
BREAKING Renamed the
unix-socketconfiguration table tosocket, and gave every transport field a default, so a table adjusts an address rather than enabling a transport.socket.pathdefaults to comodoro.sock inside$XDG_RUNTIME_DIRor the temporary directory,tcp.hostto 127.0.0.1 andtcp.portto 9999.An account therefore requires nothing but its
cycles, andunix-socketstays an accepted alias so a 1.x file still loads.Which transport runs is no longer configured:
server startbinds what it is given, the default one when given none. A client still followssocket.defaultandtcp.default. -
BREAKING Renamed the
[PROTOCOL]argument to[TRANSPORT], since a protocol is now what the two peers speak rather than what carries it.It takes
socket, aliasedunix-socket, ortcp.server starttakes a list, so serving both at once iscomodoro server start socket tcp.Only
setreorders its arguments, ascomodoro set <SECONDS> [TRANSPORT], since an optional argument cannot stand before a required one. -
BREAKING Replaced the
--debugand--traceflags with--log-level <LEVEL>and--log-file <PATH>, which the pimalaya-cli toolkit now provides.--log-levelacceptsoff,error,warn,info,debugandtrace, and overridesRUST_LOGwhen given. -
BREAKING Reworked the cargo features, dropping
std,timerandcommand.stdpulled no crate of its own, every layer above the timer required it, and shell hooks pull no extra crate.vendorednow forwards to notify-rust.A build without
notifyrefuses an account carrying notify hooks as it loads, naming the missing feature rather than failing the build. -
BREAKING Rewrote the library API, so nothing published before this release still resolves.
The I/O-free coroutine layer is gone, the remaining items are domain-prefixed per the Pimalaya naming guidelines, and everything the CLI needs sits under one
clisubtree.What this release keeps stable is the TOML and the wire shapes. The Rust API is documented on docs.rs and counts as new.
-
Re-licensed the project from AGPL-3.0-or-later to dual MIT OR Apache-2.0.
-
Moved to edition 2024 with a 1.89 minimum supported Rust version.
Fixed
-
Fixed the configuration paths ignoring what the documentation describes.
-cnow reads theCOMODORO_CONFIGenvironment variable when given no path, and splits:-delimited paths into the base and the ones deep-merged on top. -
Fixed the errors raised when no account can be resolved saying nothing actionable.
A missing configuration names the path it looked for and offers the wizard, or points at
comodoro configurewhen no one is there to answer.A missing named account lists the ones the configuration does hold, and a missing default account names the two ways to pick one.
-
Fixed a client connection blocking every other one.
The server ran each connection to completion before accepting the next, so a long-lived client held it to itself. Each connection now gets its own thread.
-
Fixed a panic in one request killing the daemon.
A panic while holding the timer poisoned its lock, so every later request exited. The lock is now recovered, since a panic can leave the timer stale but never torn.
-
Fixed shell hooks not going through a shell.
A command given as a string was split on whitespace and executed directly, so a hook redirecting its output passed
>>to echo as an argument.String commands now run through
/bin/sh -c(cmd /Con Windows), and an array still executes directly. -
Fixed a duration set through
timer.setlasting less than a second.It was written onto the current cycle, which the tick recomputes from the elapsed time, so the write was discarded within a second while the call reported success.
A set now moves the timeline to the point leaving the requested duration remaining. Longer than the cycle is clamped to it, and setting a stopped timer does nothing.
-
Fixed a paused timer being impossible to stop.
timer.stopacted only on a running timer, so it reported success on a paused one and left it paused. -
Fixed a configuration of zero-length cycles panicking the server, by way of a modulo by zero.
Such a timer now ticks and sets without effect, since no elapsed time can name a cycle in it.
-
Fixed a timer completing its last loop in silence.
timer.ended,timer.stoppedand theon-timer-stophook never fired on the one moment acycles-counttimer exists for, and the timer reported itself stopped mid-cycle.The completing tick now emits both events and resets, exactly as
timer.stopdoes. -
Fixed a cycle boundary going unannounced between two cycles sharing a name.
Boundaries were detected by comparing names, so a single cycle looping forever never announced a round. A boundary is now also recognised by the remaining duration going back up.
-
Fixed the per-second tick reporting the previous second.
Every
timer.runningnotification lagged one tick, and a duration written bytimer.setwas announced again by the next one, twice within the same wall-clock second.A tick now reports what it just computed:
timer.runninginside a cycle,timer.endedthentimer.beganwhen crossing into another, nothing when nothing changed.