Changelog
What has shipped
Junkt is deliberately small, so this list stays short. Everything here is live.
-
Feature
Controls — your half of the store
Everything in Junkt has flowed one way: your agent writes a key, and reads it back later. You could watch it and delete things, and that was the extent of your say. Controls go the other way. A control is a typed setting you write in the dashboard and your agent may only read — the way to tell a running agent something without editing its prompt or its schedule.
- A new Controls page. Booleans flip in one click, so pausing a scheduled job is a switch rather than a form.
- Four types: boolean, string, number, and enum with a fixed set of options. Each carries a description, which is the part that matters — a flag named "paused" says nothing to an agent until you say what to do about it.
- One new tool, list_controls, returning every control with its value cast to its type and the description alongside. Values come back with the list rather than a call apiece, because a control nothing checks does nothing.
- Read-only is enforced, not conventional: set_value, increment and delete_key all refuse the control: namespace, so an agent cannot clear a flag that stops it. The refusal message points it at list_controls instead.
- The reserved namespace was special:, which described nothing. It is now control:, where it means something — the prefix an agent reads a control under is the same one it is told it cannot write.
- Ten controls per account, on their own allowance. Setting one never costs you a key.
- list_keys names your controls alongside your keys, so an agent that only ever calls that one still finds out they exist.
- Junkt still cannot stop an agent by force. A control is somewhere it will reliably look, which only works if you have told it to look — there is a page about that, and about what else controls are good for.
-
Feature
A clock, and a dice roll
Reading the clock used to mean one read-only key, special:current_time_utc, which answered the narrowest version of the question — knowing the current UTC time still leaves the model doing date arithmetic, and that is exactly where it slips. That key is gone, and four tools have taken its place.
- time covers now, since, add, seconds_until and same_day. Hand same_day a stored updated_at and it tells you whether that falls on today's date in whatever timezone you name — the "has this already run?" check, in one call.
- seconds_until midnight returns a number you can pass straight to set_value as a ttl, for a key that clears itself at the end of the day.
- random_number, random_token and random_choice cover integers, probability gates and jitter; UUIDs, ULIDs, nanoids, hex, PINs and passphrases; and picking, shuffling, sampling or weighting a list.
- A seed makes any draw reproducible, so the same input always buckets the same way, and times returns a batch from one call instead of one request each. Nothing generated is stored, and none of it counts against your key limit.
- special: is now simply reserved — writes are refused and nothing is readable there. list_keys totals count only the keys you actually store, so the number reads straight against your limit.
-
Site
Docs, and a site that says what the product does
The landing page had been describing a product three releases behind. It now covers counters, expiry, the activity log and the special namespace, and there is finally somewhere to read the details.
- Public documentation: the model and limits, connecting a client, and a full tool reference.
- Privacy, terms and support pages.
- This changelog, and a blog.
-
Feature
Activity log
Handing an autonomous agent persistent memory is easier when you can check what it did with it. Every successful write, increment and delete is now recorded.
- Recent activity on the dashboard: the action, the key, the time, and whether it came from MCP or the web UI.
- Reads are deliberately not logged — every get_value would drown the entries that matter.
- Rejected operations leave no trace, so the log only shows things that actually happened.
- Entries are pruned after 30 days.
-
Feature
Keys can expire
set_value takes an optional ttl in seconds. When it elapses the key disappears. This is what turns Junkt from a place to leave notes into something you can build a cooldown out of.
- Expired keys vanish from get_value and list_keys, and stop counting toward your key limit, before they are physically removed.
- Re-setting a key rewrites its TTL. Setting it without one clears any previous expiry.
- expires_at is reported by set_value, get_value and list_keys.
- The Keys page gained an Expires column.
-
Feature
Atomic counters
Counting used to mean read, parse, add one, write back — which loses counts the moment two runs overlap. The new increment tool does it in one atomic operation.
- increment creates a counter from zero on first use. A negative amount decrements.
- Counters are a distinct kind of key: set_value will not overwrite one, and a plain value cannot be incremented. Both directions fail loudly rather than corrupting anything.
- Type is reported by get_value and list_keys, and shown as a badge on the Keys page.
-
Launch
Junkt is live
A tiny key/value store your agents reach over MCP, built because a scheduled Cowork task kept sending the same digest twice.
- Four MCP tools: list_keys, get_value, set_value and delete_key.
- OAuth 2.1 with PKCE and Dynamic Client Registration, so connectors register themselves.
- A dashboard with your server URL, your connectors, and your keys.
- 25 keys and 2KB values on the free tier.