What is built, and where the rest is tracked
Planned work lives in GitHub issues, not in this file. Anything new — a bug, an idea, a change of mind — goes there, so there is one list rather than two that disagree.
A milestone is named after the release that carries it, and is closed when
that release is tagged. The names drifted once — milestones called v1…v4
against versions 0.1.0…0.6.0, which read as major versions and were not — so
they were renamed to the versions they actually shipped in. An issue blocked on
something outside this repository sits on no milestone: a schedule it cannot
meet is how the drift started.
- 0.2.0 — read and write issues, queues, projects, goals, attachments; every distribution channel; the agent skill. Shipped across 0.1.0 and 0.2.0.
- 0.3.0 — worklogs, checklists, portfolios, administration.
- 0.5.0 — what the API offered and the tool did not: the dictionaries and people that make a write guessable rather than a guess, issue history, moving an issue between queues, editing what was already written, and writes for the project-management entities. Shipped across 0.4.0 and 0.5.0.
- 0.6.0 — the endpoints a survey of the API found unused, and the query language written down against a live Tracker rather than from memory.
- 0.7.0 — the rest of the Tracker API: components, link types, queue access, and the writes a sweep found missing. 1.0.0 waits on this, because a tool that claims a version 1 for a Tracker CLI should not still make a caller guess at what a component field takes.
- Yandex Wiki — whether the other half of an organisation’s writing belongs behind this binary at all. Not a version: research first, and the answer may be no.
kind:question— open design questions, filed so they are not re-litigated from scratch.
Labels split the work by area: area:issues, area:entities,
area:attachments, area:output, area:testing, area:distribution,
area:agents.
Already built
-
Project scaffolding: toolchain, lints, hooks,
justtasks, CI on three platforms, tagged releases, docs site. -
Layered configuration and profile resolution, reporting where the choice came from (ADR 2).
-
Keychain-backed credentials, keyed by account (ADR 2).
-
HTTP client: auth and organisation headers, typed errors mapped to exit codes, retries limited to transport failures and backpressure (ADR 4).
-
Compact text renderer for issues and issue pages: fixed field order, links with their type, fenced untrusted text, pagination tally — pinned by snapshots (ADR 1, ADR 3).
-
The whole command tree, built rather than declared: exit code 64 exists for a command a future build adds, and nothing in this one returns it.
-
ytcli auth statusend to end. -
ytcli cheatsheet, compiled into the binary. -
issue changelog,issue move, editing comments and worklogs,worklog findacross issues,queue versionsandqueue tags, and create/update/delete for projects, portfolios and goals — the whole of milestone v3 apart from making the tool work inside Claude Cowork, which needs a session there to answer. -
ytcli dict listand theusergroup: the two things a write had to be guessed at without. Dictionaries print the stable key beside the localised name, because only one of the two can go in a script.user findfilters the directory here — Tracker has no user search endpoint — and says how many people it read rather than presenting a capped answer as a complete one. -
Milestone 0.6.0:
skills/ytcli/yql.md, every query on it sent to a real Tracker before it was written down — which is howStoryPointsturned out not to be a filter name while"Story Points"is.field getsays what a field accepts, naming the command that lists the values when they live elsewhere.issue remotelinksshows what an issue is attached to outside Tracker.queue automationreports macros, autoactions and triggers, and says which section it was refused rather than counting it zero.sprint listandqueue local-fieldsclose the two listings that had no way in. -
ytcli issue listas an alias ofissue find: every other group lists with that word, and the group used most was the one exception. -
Profile routing: a bare key goes to the profile that can see its queue, and every command says on stderr which profile and organisation answered.
ytcli auth useswitches the stored default without reading a token. -
Help written in markdown and rendered with termimad for a terminal; the source goes to a pipe, where an agent reads it natively and escape codes would be noise.
-
The agent surface (ADR 6):
skills/ytcli/, loaded as a plugin by Claude Code and Codex from one directory, and--helpwritten as documentation rather than as clap’s defaults. Both are checked against the binary by tests, since a stale example is acted on rather than noticed. -
Worklogs, checklists and link editing, with reads and writes under separate command prefixes so an allowlist cannot be stretched from one into the other.
-
queue get, andqueue create --like: a new queue copies its issue types, workflows, resolutions and defaults from one that already works, because workflow ids are organisation-specific strings nobody has memorised.--yesis required for one queue, since a key is claimed once. -
Organisation-wide field and template listings, read-only. The template paths are
issueTemplatesandcommentTemplates; there is no_templatescollection, and every plausible guess at one answers 400 or 404. -
Boards, read-only: listing, columns in board order, and sprints. A board that cannot have sprints is refused in Tracker’s own words rather than answered with an empty list.
-
Portfolios: listing, reading, what one contains, and moving a project or a portfolio in and out of one. Containment writes quote the version they read, so a concurrent change is refused rather than overwritten. Containment is a separate command rather than part of
get, because it is a second request and nothing should pay for an answer it did not ask for. -
Image attachments drawn in the terminals that can draw them, and a next step printed everywhere else.
-
Documentation that is executed: the README and cheatsheet examples run as
trycmdcases against the stub, and a command documented without a case has to be declared unrunnable with a reason. -
brew install ormeilu/tap/ytcli, from ormeilu/homebrew-tap. The formula is generated by the release workflow from the archives it just published and pushed with a deploy key scoped to that one repository. The step is skipped when the key is absent: a release must not fail over an optional channel.
Deliberately out of scope
Recorded here rather than as issues, so the decisions are not re-opened by someone reading the backlog:
- A second entry point named
yandex-tracker-cli. It would double the size of every release artifact to save typing. The PyPI package keeps that name; the command isytcli, and a shell alias covers the rest. - Any verb that both reads and writes. ADR 1 depends on the split being total: agent hosts allowlist read verbs permanently, and one mixed verb would silently break that for every user.
- Printing a stored token. A tool whose main consumer is an agent should not offer secret exfiltration as a feature.