Releases: justinstimatze/linear-strict
Releases · justinstimatze/linear-strict
Release list
linear-strict 0.1.1
- The Claude Code hooks installer (
examples/claude-code-hooks/install.sh) works in a project outside git instead of refusing it. In a git repo where.claude/settings.local.jsonisn't ignored, it says which line to add to.gitignore, and a refusal or--statusno longer leaves an empty settings file behind. Its README gives the path under a global install of the release.tgz, since the package is not on npm. - Requires Node 22 or later. Node 20 reached end of life on 2026-04-30; CI tests 22 and 24.
- No change to the tools or what they return.
Development:
npm testalso checks Prettier formatting and runs knip for unused files, exports and dependencies; CI runs shellcheck on the hook scripts.- TypeScript 6.0, ESLint 10 and Jest 30. Errors rethrown with a new message keep the original as
cause. src/strict-linear.tsis split into modules (queries, Done when checks, descope, reconciling, comment rules, get_issue and list_issues shaping), andStrictLinear.setStatetakes its optional arguments as one object.- An optional pre-commit hook (
git config core.hooksPath hooks) runs a non-blocking CodeScene delta check.
Install: npm install -g https://github.com/justinstimatze/linear-strict/releases/download/v0.1.1/linear-strict-0.1.1.tgz, then linear-strict install. See the README for setup.
linear-strict 0.1.0
First release as a standalone package.
- Tools:
get_issue,description_history,list_issues,claim,check_claim,set_state,comment,set_status,set_fields,create_issue,list_teams,list_cycles,list_projects,list_initiatives,notifications,mark_notifications_read,whoami. - A description patch names the description it was written against:
get_issuereturnsdescription_sha, andset_state, or acommentwith a patch, passes it asbase. A patch built from an older read is refused with what changed since. - The sign-off prompt for dropping a
Done whenitem shows each check as it stands, what replaces it, why the agent wants it and what approving gives up, as rows with short labels and the full text beneath, and approves on Accept. It had asked for a ticked box per item, and Accept with the boxes left unticked, as they started, was scored as a decline. A descope now needsdescope_riskbesidedescope_reason, each at most 100 characters, since the form shows each on one line. The form opens with the ticket's title, and text longer than a row continues on the rows below it. The form waits 30 minutes, up from 10. A refusal says what the person wrote and what the client returned. - In Claude Code, sign-off goes through
AskUserQuestionwith the change in its preview box, oncelinear-strict installhas added the sign-off hooks to~/.claude/settings.json.set_stateissues the question with a token, a PreToolUse hook refuses it if its text was changed, a PostToolUse hook records the answer, and the retry passes the token assign_off.LINEAR_STRICT_SIGN_OFF=judgehands the decision to a model instead (claude-opus-5-5by default), for sessions nobody is watching; the descope comment names the model and its reason.linear-strict auth judge-key setstores its API key in the config directory, mode 600. list_issuesreturns every matching ticket in one call: the server pages through Linear to the end and answers withtotal,by_stateand one row per ticket, so there is no cursor for an agent to stop following. A failed page, or more than 2,000 matches, is refused rather than answered with part of the set.open: trueleaves out completed and canceled tickets.firstandafterare gone. An agent had stopped after 4 pages of a 955-ticket cycle.linear-strict installunder npx writes hooks that run the same pinned version through npx, since npm prunes the cache npx runs from and hooks pointing into it would stop recording answers without a word.install --statussays whether the installed hooks can still run, and the server asks through the elicitation form instead ofAskUserQuestionwhen they can't.- A server replaced by Claude Code's
/mcpreconnect exits once the newer one has served for a minute with it idle, instead of running for as long as the client does. It also exits when its parent does or its input closes.LINEAR_STRICT_SINGLE_INSTANCE=0turns this off. npm testruns every sign-off route end to end through the built server over stdio:AskUserQuestionwith the installed hooks, the form when the hooks can't run, and the judge (--live-judgefor the real API).- The npm package includes
examples/and aserver.jsonfor the MCP registry (mcpNameio.github.justinstimatze/linear-strict). description_historyreads the snapshots Linear keeps of a description: each version's time, author and diff, and withblamethe version behind every current line.- A comment edited after the description accounted for it shows up in
drift.edited_after_reconcile, and moving the marker needs it accounted for again. The marker records when it was checked (checked). - The reconciled marker is kept in an attachment on the ticket instead of a
<!-- strict:reconciled … -->line in the description. Linear stores descriptions as rich text with no place for an HTML comment, so the line showed to everyone as literal text they could edit or delete. The attachment also records the hash of the description it was checked against, anddrift.description_changed_elsewherereports a description edited outside this server since. A marker line from an earlier version is still read, and the next description write through this server moves it to the attachment. - Tickets labelled
no-agents(LINEAR_STRICT_HANDS_OFF_LABELS) refuse every write through this server. - GraphQL over
fetch. A rate-limited call waits for Linear's reset time and retries twice, then says when the limit resets. A read that meets a gateway error (502, 503, 504) is retried the same way; a write is not, since it may have gone through. claimmakes an agent (app) identity the delegate on every ticket, including an unowned one, which it had taken as assignee.- Writes to an archived or trashed ticket are refused.
- Moving a ticket to a canceled state needs
reason, posted as a comment, since canceling skips the Done checks. ask_tomentions the person by profile link when the name resolves to one member, so they are notified.- A cited PR whose merge status Linear didn't record no longer refuses Done; the result names it.
get_issuereads the latest 200 history entries rather than all of them, and a description write that changes nothing is not sent.- The README and package say plainly that this is an unofficial project, not affiliated with Linear.
- Installs from the built package attached to each GitHub release (
npm install -g <release .tgz URL>); it is not on npm. linear-strict auth login|status|logout, an OAuth login with PKCE and token refresh, fromtacticlaunch/mcp-linear.- An
Observedline may carry a time after its date. - Done needs each ticked
Done whenitem to cite what showed it:- [x] item · <evidence>, where evidence is a commit SHA, a PR, a file:line, a link, a CI run,Observed N, or a command and its result. A cited PR linked to the ticket must be merged. - A ticket written with neither
ObservednorDone whengets oneunstructuredfinding instead of two missing sections, and a closed or canceled ticket gets neither. - An unknown argument is refused with the arguments the tool does take, and a field that belongs to
set_fields(an assignee oncreate_issue, say) points there. - Claude Code hooks under
examples/claude-code-hooks.
Install: npm install -g https://github.com/justinstimatze/linear-strict/releases/download/v0.1.0/linear-strict-0.1.0.tgz, then linear-strict install. See the README for setup.