A Pointman extension that opens a Linear team's or project's board in the apps. Pointman draws it with its own project board: the same columns, cards, filters and drag. Linear stays the source of truth, and the board has full control of it. A move, a rank, an edit of any field, a new card or a comment goes to Linear, and the card settles where Linear puts it. If Linear says no, the card snaps back with Linear's reason.
Linear is asked from the node, with the vault's API key, so the apps never hold it.
pointman add linear
-
Add a key:
/linear addin any thread opens a form for a personal API key from linear.app (Settings › Security & access › New API key). It's sealed into the vault aslinear.<label>for every node, and never posted. Pointman asks Linear as the key's owner. Add one per Linear workspace: each board is asked with the key that sees its team or project. -
Connect a board: in a project's pane, Add a project board lists the Linear teams and open
projects every key sees (
/linear boardslists them in a thread). Pick one, and the project opens its board.
A board opens by a team, {team: "ALA"}, or by a Linear project, {project: "<id>"}. A project's issues
can be in several teams: its columns are each team's states by name (the first team's order first), and a
move sets the issue's own team's state of that name.
-
Columns: the team's workflow states in Linear's order. Each falls in one of Pointman's seven
categories (triage, backlog, todo, active, review, done, dropped): In Review is
review, say, and a started state named for a hold isactive, held. - Cards: the team's or project's open issues, and those closed in the last 14 days. Each card has its identifier, epic or task (the EPIC label or an "[EPIC] …" title), kind (by the Bug and Feature labels), state, owner (the assignee), parent, cycle, due date, priority, labels, estimate, Linear's order, and a link to the issue.
- An opened card also has its description, its comments (oldest first) and its sub-issues.
- Sprints and milestones: the teams' recent cycles are its sprints, and the issues' project milestones its milestones. Its people are who a card can be given to, and its labels the teams' and the workspace's.
- Size: a board too big to send at once leaves out the longest-closed issues first, then the least recently changed, and the board says how many.
-
Keeping current: every 30 seconds (
refresh_seconds), an open board asks Linear what changed since its last look, and everything (teams' people, labels and sprints too) every ten minutes. Only what changed goes to the apps.
| Gesture | What goes to Linear |
|---|---|
move {item, to} |
the issue's state |
rank {item, before | after} |
its order (sortOrder) between its neighbours in that column |
edit {item, fields} |
title, body, state, owner (a handle, or null), priority (urgent, high, normal or medium, low, none), target (YYYY-MM-DD, or null), estimate, labels (names), sprint (an id or name, or null) and parent (a ref, or null), each checked against the board first |
open {item} |
nothing: it adds the card's description, comments and sub-issues |
comment {item, body} |
a comment |
create {fields} |
a new issue with title and any of edit's fields, on team (a key) or the board's first team, and in the Linear project when the board is one |
| Kind | Slash | What |
|---|---|---|
linear.add |
/linear add |
Add a Linear API key for every node |
linear.boards |
/linear boards |
The Linear teams and open projects whose boards can be connected |
linear.team |
A team's states, people, labels and sprints: what an issue on it can be set to. team
|
|
linear.projects |
The open Linear projects the keys see | |
linear.search |
Issues by query (words in the title or description), team, state, owner (a display name, or none) or project; open ones unless all; at most limit (25) |
|
linear.issue |
One issue by its ref (ALA-12), with its description, comments and sub-issues |
|
linear.create |
A new issue: team, title, and any of body, state, owner, priority, target, estimate, labels, sprint, parent, project
|
|
linear.update |
Change an issue by its ref: the same fields; only those given change, and null clears one | |
linear.comment |
A comment on an issue: issue, body
|
The last seven are for agents and scripts (create_job): each asks with the vault's keys in turn, or the one
account names (work, for linear.work), so an issue or team is found with whichever key sees it. A state, owner,
label, sprint or parent that the team doesn't have is refused with what it does have, as on the board.
linear.boards answers with each one's target, name, suggested project key and kind:
{targets: [{target: {team: "ALA"}, name: "Spark", key: "ALA", kind: "team"},
{target: {project: "<id>"}, name: "Spark Voice", key: "SV", kind: "project"}],
text: "1 Linear team: Spark (ALA). 1 Linear project: Spark Voice."}
The key is a team's own, or a project name's initials (a one-word name's first three letters); none when the name gives no key.
| Setting | Default | |
|---|---|---|
refresh_seconds |
30 | How often an open board asks Linear what changed |
api_url |
https://api.linear.app/graphql |
Linear's GraphQL endpoint |
cargo test
The tests run it against a stand-in node and a stand-in Linear: a GraphQL server on a free local port that
answers as Linear's API would. To release, bump version in extension.toml and Cargo.toml and push a tag
for it (git tag v0.4.3 && git push origin v0.4.3). The release workflow builds each platform (macOS arm64
and x86_64, Linux x86_64 and arm64) and attaches it, and the marketplace lists it within 30 minutes.
MIT. See LICENSE.