Linear templates

Configure issue formats, destinations and defaults from the dashboard, MCP, API or CLI.

Use a built-in format for each brief type, or copy one into a named custom template. Templates format a brief and choose its Linear destination. They do not generate a brief, change recommendation readiness or update an existing Linear issue.

The dashboard, MCP, Developer API and CLI use the same saved revisions and defaults. Connect Linear once for the account before saving a template. Your agent needs a credential with access to the ShipFoundry project and linear:read; writes also need linear:write and an owner or admin account role. The agent never needs Linear's OAuth token.

Template CLI commands require version 0.2.0 or newer. Version 0.2.0 is prepared for publication; the currently published 0.1.0 package does not include these commands. The API and MCP controls ship with the corresponding application release.

Operations

API paths below are relative to /api/v1. Read operations have no confirmation requirement. All writes require confirmed: true through MCP/API, or --yes through the CLI. Use one idempotency key for the same write across retries and transports.

ActionMCP toolAPICLI command
Read templates, history, defaults, presets and fieldsshipfoundry.list_linear_templatesGET /linear/templates?projectId=PROJECT_IDlinear templates --project PROJECT_ID
Read teams, projects, statuses and labelsshipfoundry.linear_template_optionsGET /linear/templates/options?projectId=PROJECT_IDlinear template-options --project PROJECT_ID
Preview an unsaved draftshipfoundry.preview_linear_templatePOST /linear/templates/previewlinear preview-template --file draft.json
Save a new template or revisionshipfoundry.save_linear_templatePOST /linear/templateslinear save-template --file template.json --yes
Select a saved revision as defaultshipfoundry.select_linear_templatePOST /linear/templates/selectlinear select-template --project PROJECT_ID --template REVISION_ID --yes
Archive, restore or reset a defaultshipfoundry.manage_linear_templatePOST /linear/templates/managelinear manage-template --file management.json --yes
Preview the export payload with a saved revisionshipfoundry.linear_previewPOST /linear/previewlinear preview --match MATCH_ID --template REVISION_ID
Create or reuse a Linear issueshipfoundry.linear_exportPOST /linear/exportlinear export --match MATCH_ID --template REVISION_ID --yes

Prefix CLI commands with shipfoundry; add --json for structured output. Set the base URL and credential as described in the CLI guide. API requests use the bearer credential and X-Idempotency-Key header described in the API guide. MCP write tools accept idempotencyKey. CLI writes accept --idempotency-key.

Agent setup procedure

  1. List templates and destination options with the ShipFoundry projectId.
  2. Choose a built-in preset matching the brief type. Copy its titleTemplate and bodyTemplate into a draft, give the draft a name, and choose its destination IDs from the options response.
  3. Preview the unsaved draft against a real recommendation using matchId. Check the rendered title, body and emptyVariables. Draft preview checks formatting and brief identity/type. It does not validate the destination against live Linear metadata or guarantee export readiness.
  4. Save the draft. Saving validates the destination and appends a revision. Select its returned id as the default only when that is intended.
  5. Preview the saved export payload. Export only after approval, then keep the returned Linear issue identity. An already-exported brief normally reuses its existing issue.

The list response contains:

FieldMeaning
templatesAll saved revisions, including archived and built-in revisions. Each has id, templateId, version, name, outputKind, templates, destination and lifecycle flags.
defaultsPinned revisionId for each configured brief type.
fallbackRevisionIdPinned generic fallback, or null.
presetsSix named built-in formats, with their type and title/body text.
variablesPlaceholder names and descriptions.
variableCatalogEvery field's placeholder, description, common, group, availability, includedInBrief and emptyBehavior.

To show one library entry per custom template, take its greatest version, omit isBuiltIn, and separate active from isArchived. Older rows are history, not separate templates. A default pins a specific revision's content. The named template's latest archive state controls whether that pinned revision is usable.

Save and preview input

This file creates a new custom template. Replace placeholder IDs with the IDs returned by the server. For MCP/API saving, add confirmed: true; the CLI adds it after --yes.

{
  "projectId": "SHIPFOUNDRY_PROJECT_UUID",
  "expectedVersion": 0,
  "name": "Team handoff",
  "titleTemplate": "{{title}}",
  "bodyTemplate": "{{brief}}\n\n## Report back\n{{outcomeInstructions}}",
  "outputKind": "engineering_handoff",
  "destination": {
    "teamId": "LINEAR_TEAM_UUID",
    "projectId": null,
    "stateId": null,
    "labelIds": []
  }
}

For draft preview, use the same file and add matchId, the ShipFoundry recommendation UUID. Do not add confirmed. Preview writes no template revision and creates no Linear issue.

InputMeaning
projectIdShipFoundry project being configured. Required.
templateIdNamed template identity. Omit for a new template or a copy. Supply it when appending to an existing template.
expectedVersion0 for a new template; latest version for an existing template. A stale version returns template_conflict (409).
nameLibrary name, 1 to 120 characters.
titleTemplatePlain title with literal placeholders, up to 500 characters. Defaults to {{title}}.
bodyTemplateMarkdown with literal placeholders, up to 40,000 characters. Defaults to {{brief}}.
outputKindOne brief type below, or null for a generic fallback. A type-specific template cannot export another brief type.
destination.teamIdRequired Linear team UUID.
destination.projectIdOptional Linear project UUID belonging to that team. This is a different identity from the top-level ShipFoundry projectId.
destination.stateIdOptional workflow status UUID belonging to that team. null uses the team's default.
destination.labelIdsUp to 50 available label UUIDs. Group IDs cannot be applied, and at most one child from each actual label group is allowed.

Destination options include teams, projects with teamIds, states with teamId, and labels with teamId, isGroup and parent. A label name such as area:briefs is ordinary text unless parent identifies a real group. Independent labels can be combined.

Brief types and built-in defaults

Display nameoutputKindBuilt-in focus
Configuration Packetconfiguration_packetConfiguration steps, acceptance and tests
Engineering Handoffengineering_handoffImplementation steps, acceptance and tests
Engineering Spikeengineering_spikeInvestigation steps, evidence and validation
Research Briefhuman_analysis_packetResearch steps, evidence and validation
Strategy Briefstrategy_briefStrategy review, evidence and validation
Workflow Briefworkflow_briefWorkflow review, evidence and validation

Each preset also includes context, why the work matters, packet information, risks, non-goals, reporting instructions and references. The generic built-in fallback is {{title}} and {{brief}}. Read presets for the exact current text instead of reproducing it in an agent prompt.

Default precedence is: explicitly requested revision, matching brief-type default, compatible generic fallback, then built-in format. Selecting one type preserves other type defaults. Saving or loading history does not select a default.

Select, archive, restore and revert

Select a saved revision with:

{
  "projectId": "SHIPFOUNDRY_PROJECT_UUID",
  "revisionId": "SAVED_REVISION_UUID",
  "confirmed": true
}

Archive or restore a named template with the latest version from the list response:

{
  "action": "archive",
  "projectId": "SHIPFOUNDRY_PROJECT_UUID",
  "templateId": "NAMED_TEMPLATE_UUID",
  "expectedVersion": 3,
  "confirmed": true
}

For restore, change action to restore and reload the latest version first. Both actions append history. There is no permanent-delete endpoint. An archived default uses the built-in format with its pinned destination; restoring makes its pinned custom content available again. Explicit selection or export of an archived template is rejected.

To revert content, copy the earlier revision's name, title/body, type and destination into a save request. Keep its templateId but use the latest expectedVersion. The returned row is a new revision. Select its id if it should become active. Existing revisions and Linear issues remain unchanged.

To reset one type to built-in, use the existing pinned destination or a destination chosen from options:

{
  "action": "reset_default",
  "projectId": "SHIPFOUNDRY_PROJECT_UUID",
  "outputKind": "engineering_spike",
  "destination": {
    "teamId": "LINEAR_TEAM_UUID",
    "projectId": null,
    "stateId": null,
    "labelIds": []
  },
  "confirmed": true
}

Use outputKind: null for the generic fallback. Reset creates and selects an immutable built-in revision in one transaction. Built-in revisions cannot be edited; copy a preset to create a custom template instead.

Placeholder reference

Use {{brief}} for the full handoff, or individual sections for your own layout. Substitution does not remove repeated sections automatically. includedInBrief identifies direct sections already included by the complete handoff. Packet subfields can also duplicate parts of {{taskPacket}}.

The field guide shows 13 common fields initially. Advanced exposes all 39; search includes advanced fields. Optional missing values render as empty strings, and preview reports explicitly referenced empty values. {{taskPacket}} explicitly explains when no executable packet exists. Helpers, conditionals, nested expressions and unknown variables are rejected. Braces in brief or repository content remain literal.

PlaceholderMeaningAvailabilityCommon
{{title}}Brief titleAll brief types.Yes
{{brief}}Complete default handoff, including its packet when availableAll brief types.Yes
{{context}}Relevant project contextAll brief types.Yes
{{whyThisMatters}}Why this matters to this repositoryAll brief types.Yes
{{suggestedSteps}}Ordered investigation and implementation stepsAll brief types.Yes
{{acceptanceCriteria}}Expected output or evidence to returnAll brief types.Yes
{{testPlan}}Validation instructionsAll brief types.Yes
{{risks}}Risks and open questionsAll brief types.Yes
{{nonGoals}}Constraints and non-goalsAll brief types.Yes
{{taskPacket}}Execution packet, when this brief has oneAll brief types. Explicitly reports when no packet is available.Yes
{{briefId}}Immutable brief identifierAll brief types.Advanced
{{briefUrl}}ShipFoundry recommendation linkAll brief types.Yes
{{sourceUrl}}Original update link, when availableAll brief types, when recorded on the original update.Yes
{{outputKind}}Brief typeAll brief types.Advanced
{{projectName}}ShipFoundry project nameAll brief types.Advanced
{{projectId}}ShipFoundry project identifierAll brief types.Advanced
{{projectUrl}}ShipFoundry project linkAll brief types.Advanced
{{updateTitle}}Original update titleAll brief types.Advanced
{{updateSummary}}Original update summary, when availableAll brief types, when recorded on the original update.Advanced
{{updatePublishedAt}}Original publication date, when availableAll brief types, when recorded on the original update.Advanced
{{sourceName}}Update source name, when availableAll brief types, when recorded on the original update.Advanced
{{matchId}}Recommendation identifier used to report outcomesAll brief types.Advanced
{{briefTitle}}Brief title without the Linear issue prefixAll brief types.Advanced
{{briefVersion}}Version of this briefAll brief types.Advanced
{{objective}}Execution objectiveRequires an execution packet. Availability depends on this brief, not just its type.Advanced
{{expectedResult}}Expected execution resultRequires an execution packet. Availability depends on this brief, not just its type.Advanced
{{executionType}}Type of executable workRequires an execution packet. Availability depends on this brief, not just its type.Advanced
{{whyNow}}Why to do this work nowRequires an execution packet. Availability depends on this brief, not just its type.Advanced
{{prerequisites}}Prerequisites before executionRequires an execution packet. Availability depends on this brief, not just its type.Advanced
{{currentState}}Known repository stateRequires an execution packet. Availability depends on this brief, not just its type.Advanced
{{unknowns}}Unknown facts and how to resolve themRequires an execution packet. Availability depends on this brief, not just its type.Advanced
{{executionSteps}}Packet steps, including authorization requirementsRequires an execution packet. Availability depends on this brief, not just its type.Advanced
{{validation}}Checks with success and failure signalsRequires an execution packet. Availability depends on this brief, not just its type.Advanced
{{completionChecklist}}Completion checklistRequires an execution packet. Availability depends on this brief, not just its type.Advanced
{{constraints}}Execution constraintsRequires an execution packet. Availability depends on this brief, not just its type.Advanced
{{evidence}}Repository and analysis evidenceRequires packet evidence. May be absent for this brief.Advanced
{{sourceEvidence}}Source evidence and linksRequires packet evidence. May be absent for this brief.Advanced
{{outcomeInstructions}}How the agent reports its result to ShipFoundryAll brief types.Yes
{{packetId}}Execution packet identityRequires an execution packet. Availability depends on this brief, not just its type.Advanced

Was This Page Useful?

On this page