linear_custom_view
Manages a Linear custom view — a saved, filtered list of issues, projects, initiatives or feed items. The filter goes through as a JSON object rather than typed HCL. Linear's IssueFilter alone has 122 top-level fields and nests arbitrarily, and the server normalises what it stores, so a typed schema would freeze against a moving API and a plain string would report drift on every plan. The *_json attributes are compared semantically instead. Set exactly one of filter_json, project_filter_json, initiative_filter_json or feed_item_filter_json — which one decides what the view lists. resource "linear_custom_view" "in_review" { name = "In Review" team_id = linear_team.eng.id shared = true filter_json = jsonencode({ state = { type = { eq = "started" } } labels = { some = { name = { eq = "ai" } } } }) }
linear_custom_view (Resource)
Manages a Linear custom view — a saved, filtered list of issues, projects, initiatives or feed items.
The filter goes through as a JSON object rather than typed HCL. Linear's IssueFilter alone has 122 top-level fields and nests arbitrarily, and the server normalises what it stores, so a typed schema would freeze against a moving API and a plain string would report drift on every plan. The *_json attributes are compared semantically instead.
Set exactly one of filter_json, project_filter_json, initiative_filter_json or feed_item_filter_json — which one decides what the view lists.
resource "linear_custom_view" "in_review" {
name = "In Review"
team_id = linear_team.eng.id
shared = true
filter_json = jsonencode({
state = { type = { eq = "started" } }
labels = { some = { name = { eq = "ai" } } }
})
}
Example Usage
# The reason this provider exists. The filter goes through as JSON and is
# compared semantically, so Linear's server-side normalisation is not drift.
resource "linear_custom_view" "in_review" {
name = "In Review"
description = "Everything waiting on a reviewer"
team_id = linear_team.engineering.id
shared = true
color = "#0f7488"
filter_json = jsonencode({
state = { type = { eq = "started" } }
labels = { some = { name = { eq = "ai" } } }
})
}
# Set a different filter to make it a project, initiative or feed view — exactly
# one of the four may be set.
resource "linear_custom_view" "active_projects" {
name = "Active projects"
shared = true
project_filter_json = jsonencode({
status = { type = { eq = "started" } }
})
}
Schema
Required
name(String) Name of the view.
Optional
color(String) Colour of the view icon as a hex string.description(String) Description of the view.feed_item_filter_json(String) Feed item filter as a JSON object. Makes this a feed view.filter_json(String) Issue filter as a JSON object, e.g.jsonencode({ state = { type = { eq = "started" } } }). Compared semantically, so Linear's server-side normalisation is not reported as drift.icon(String) Icon of the view.initiative_filter_json(String) Initiative filter as a JSON object. Makes this an initiative view.initiative_id(String) UUID of the initiative the view is scoped to. Write-only, for the same reason asproject_id.owner_id(String) UUID of the user who owns the view. Defaults to whoever the API key belongs to.project_filter_json(String) Project filter as a JSON object. Makes this a project view.project_id(String) UUID of the project the view is scoped to. Write-only: Linear exposes a view's projects as a connection rather than as this id, so drift in this attribute cannot be detected.shared(Boolean) Whether the view is visible to the whole workspace rather than only its owner.team_id(String) UUID of the team the view is scoped to. Leave unset for a workspace-wide view.
Read-Only
id(String) UUID of the view.model_name(String) What the view lists, derived by Linear from whichever filter is set —Issue,Project,InitiativeorFeedItem.
Import
Import is supported using the following syntax:
The terraform import command can be used, for example:
# Import by UUID.
terraform import linear_custom_view.example a1b2c3d4-0000-0000-0000-000000000000