Keep Linear and Todoist in sync for a clean task list
Your task list lies to you. Issues get renamed in Linear, priorities shift, due dates move, and your Todoist “plan for the day” quietly becomes a museum of old intentions.
Project managers feel it during standups. Agency owners feel it when a client asks for status “right now”. And if you’re a marketing lead juggling launch tickets, a solid Linear Todoist sync is the difference between focus and constant tab-hopping.
This workflow keeps Todoist aligned with what’s actually happening in Linear. You’ll see what it does, what you need, and how the logic avoids the usual “duplicate task” mess.
How This Automation Works
See how this solves the problem:
n8n Workflow Template: Keep Linear and Todoist in sync for a clean task list
flowchart LR
subgraph sg0["New issue or updated issue Flow"]
direction LR
n0["<div style='background:#f5f5f5;padding:10px;border-radius:8px;display:inline-block;border:1px solid #e0e0e0'><img src='https://flowpast.com/wp-content/uploads/n8n-workflow-icons/todoist.svg' width='40' height='40' /></div><br/>Update task"]
n1["<div style='background:#f5f5f5;padding:10px;border-radius:8px;display:inline-block;border:1px solid #e0e0e0'><img src='https://flowpast.com/wp-content/uploads/n8n-workflow-icons/linear.svg' width='40' height='40' /></div><br/>New issue or updated issue"]
n2["<div style='background:#f5f5f5;padding:10px;border-radius:8px;display:inline-block;border:1px solid #e0e0e0'><img src='https://flowpast.com/wp-content/uploads/n8n-workflow-icons/todoist.svg' width='40' height='40' /></div><br/>Check if task already exists1"]
n3@{ icon: "mdi:swap-horizontal", form: "rounded", label: "if task already exists1", pos: "b", h: 48 }
n4["<div style='background:#f5f5f5;padding:10px;border-radius:8px;display:inline-block;border:1px solid #e0e0e0'><img src='https://flowpast.com/wp-content/uploads/n8n-workflow-icons/todoist.svg' width='40' height='40' /></div><br/>Remove task"]
n5@{ icon: "mdi:cog", form: "rounded", label: "Do nothing1", pos: "b", h: 48 }
n6@{ icon: "mdi:swap-horizontal", form: "rounded", label: "Switch based on action", pos: "b", h: 48 }
n7@{ icon: "mdi:swap-horizontal", form: "rounded", label: "If action's due date is not ..", pos: "b", h: 48 }
n8@{ icon: "mdi:swap-horizontal", form: "rounded", label: "Task finished ?", pos: "b", h: 48 }
n9["<div style='background:#f5f5f5;padding:10px;border-radius:8px;display:inline-block;border:1px solid #e0e0e0'><img src='https://flowpast.com/wp-content/uploads/n8n-workflow-icons/todoist.svg' width='40' height='40' /></div><br/>Close task"]
n10@{ icon: "mdi:swap-horizontal", form: "rounded", label: "If it's a sub-issue", pos: "b", h: 48 }
n11["<div style='background:#f5f5f5;padding:10px;border-radius:8px;display:inline-block;border:1px solid #e0e0e0'><img src='https://flowpast.com/wp-content/uploads/n8n-workflow-icons/linear.svg' width='40' height='40' /></div><br/>Get parent issue"]
n12@{ icon: "mdi:swap-vertical", form: "rounded", label: "Set title with parent and su..", pos: "b", h: 48 }
n13["<div style='background:#f5f5f5;padding:10px;border-radius:8px;display:inline-block;border:1px solid #e0e0e0'><img src='https://flowpast.com/wp-content/uploads/n8n-workflow-icons/todoist.svg' width='40' height='40' /></div><br/>Update task1"]
n14@{ icon: "mdi:swap-horizontal", form: "rounded", label: "Task finished ?1", pos: "b", h: 48 }
n15["<div style='background:#f5f5f5;padding:10px;border-radius:8px;display:inline-block;border:1px solid #e0e0e0'><img src='https://flowpast.com/wp-content/uploads/n8n-workflow-icons/todoist.svg' width='40' height='40' /></div><br/>Close task1"]
n16["<div style='background:#f5f5f5;padding:10px;border-radius:8px;display:inline-block;border:1px solid #e0e0e0'><img src='https://flowpast.com/wp-content/uploads/n8n-workflow-icons/todoist.svg' width='40' height='40' /></div><br/>Check if task already exists3"]
n17@{ icon: "mdi:swap-horizontal", form: "rounded", label: "if task already exists3", pos: "b", h: 48 }
n18@{ icon: "mdi:cog", form: "rounded", label: "Do nothing2", pos: "b", h: 48 }
n19@{ icon: "mdi:swap-horizontal", form: "rounded", label: "If action's due date is not ..", pos: "b", h: 48 }
n20@{ icon: "mdi:swap-horizontal", form: "rounded", label: "If it's a sub-issue1", pos: "b", h: 48 }
n21["<div style='background:#f5f5f5;padding:10px;border-radius:8px;display:inline-block;border:1px solid #e0e0e0'><img src='https://flowpast.com/wp-content/uploads/n8n-workflow-icons/todoist.svg' width='40' height='40' /></div><br/>Remove task1"]
n22["<div style='background:#f5f5f5;padding:10px;border-radius:8px;display:inline-block;border:1px solid #e0e0e0'><img src='https://flowpast.com/wp-content/uploads/n8n-workflow-icons/linear.svg' width='40' height='40' /></div><br/>Get parent issue1"]
n23@{ icon: "mdi:swap-vertical", form: "rounded", label: "Set title with parent and su..", pos: "b", h: 48 }
n24["<div style='background:#f5f5f5;padding:10px;border-radius:8px;display:inline-block;border:1px solid #e0e0e0'><img src='https://flowpast.com/wp-content/uploads/n8n-workflow-icons/todoist.svg' width='40' height='40' /></div><br/>Create task2"]
n25["<div style='background:#f5f5f5;padding:10px;border-radius:8px;display:inline-block;border:1px solid #e0e0e0'><img src='https://flowpast.com/wp-content/uploads/n8n-workflow-icons/todoist.svg' width='40' height='40' /></div><br/>Create task3"]
n8 --> n9
n8 --> n0
n11 --> n12
n14 --> n15
n14 --> n13
n22 --> n23
n10 --> n11
n10 --> n14
n20 --> n22
n20 --> n24
n6 --> n2
n6 --> n16
n3 --> n4
n3 --> n5
n17 --> n7
n17 --> n19
n1 --> n6
n2 --> n3
n16 --> n17
n12 --> n8
n23 --> n25
n7 --> n10
n7 --> n21
n19 --> n20
n19 --> n18
end
%% Styling
classDef trigger fill:#e8f5e9,stroke:#388e3c,stroke-width:2px
classDef ai fill:#e3f2fd,stroke:#1976d2,stroke-width:2px
classDef aiModel fill:#e8eaf6,stroke:#3f51b5,stroke-width:2px
classDef decision fill:#fff8e1,stroke:#f9a825,stroke-width:2px
classDef database fill:#fce4ec,stroke:#c2185b,stroke-width:2px
classDef api fill:#fff3e0,stroke:#e65100,stroke-width:2px
classDef code fill:#f3e5f5,stroke:#7b1fa2,stroke-width:2px
classDef disabled stroke-dasharray: 5 5,opacity: 0.5
class n1 trigger
class n3,n6,n7,n8,n10,n14,n17,n19,n20 decision
classDef customIcon fill:none,stroke:none
class n0,n1,n2,n4,n9,n11,n13,n15,n16,n21,n22,n24,n25 customIcon
The Challenge: Linear changes don’t reach your daily task list
Linear is where work gets defined, debated, and finalized. Todoist is where you decide what to do next. The trouble starts when those two drift. An issue gets moved to Done, but the Todoist task stays open, so you keep “planning” to do something that’s already finished. Titles change, sub-issues get split, and suddenly your list has vague tasks like “Fix bug” with no context. Even worse, you lose trust in your own system, which means you stop using it.
It adds up fast. Here’s where it breaks down in real teams.
- You end up re-copying issue titles, links, and due dates into Todoist, which burns about 10 minutes every day.
- Closed work stays open in Todoist, so your “today” list looks heavier than it really is.
- Sub-issues are hard to understand out of context, and you waste time hunting for the parent issue name.
- Filtering by “assigned to me” becomes manual policing, because Todoist doesn’t know who owns the Linear issue.
The Fix: One-way Linear → Todoist task syncing
This n8n workflow listens for issue events in Linear and mirrors them into Todoist as clean, current tasks. When an issue is created, it checks if a matching Todoist task already exists by looking up the Linear issue ID. If it finds one, it updates the task instead of creating a duplicate. If it doesn’t, it creates a new task in your chosen Todoist project (Inbox by default). When the Linear issue is marked Done, the workflow closes the Todoist task. And if the issue is deleted, the related Todoist task is removed too, so you don’t keep ghosts in your list.
The workflow starts with a Linear issue change trigger. Then it routes the event (create, update, remove), verifies a matching Todoist task, and applies the right action. If the issue is a sub-issue, it can fetch the parent issue and build a clearer “Parent → Child” style task title.
What Changes: Before vs. After
| What This Eliminates | Impact You’ll See |
|---|---|
|
|
Real-World Impact
Say you handle 15 Linear issues a week that actually need to land on your personal list. Manually, you might spend about 5 minutes per issue creating a task, updating the title later, and closing it when it’s done. That’s roughly an hour of maintenance, plus the extra time when you miss a change and have to reconcile. With this workflow, you spend about 20 minutes once setting your email filter and Todoist project, then the rest runs in the background.
Requirements
- n8n instance (try n8n Cloud free)
- Self-hosting option if you prefer (Hostinger works well)
- Linear to trigger on issue changes.
- Todoist to create, update, and close tasks.
- Linear account email (use it in the IF filters).
Skill level: Beginner. You’ll connect accounts, then swap in your email and preferred Todoist project.
Need help implementing this? Talk to an automation expert (free 15-minute consultation).
The Workflow Flow
A Linear issue changes. The workflow is triggered when an issue is created, updated, completed, or removed in Linear.
The event gets routed. A simple switch routes the job to the right path (create, update, remove), so you don’t have one giant tangle of logic.
Todoist is searched and validated. It looks for an existing task tied to that Linear issue ID, then decides whether to create a new task, modify the existing one, close it, or delete it.
Titles get cleaned up when needed. If the issue is a sub-issue, the workflow can fetch the parent issue and compose a clearer combined title before writing it into Todoist.
You can easily modify which issue states sync and where tasks land in Todoist based on your needs. See the full implementation guide below for customization options.
Step-by-Step Implementation Guide
Step 1: Configure the Linear Issue Event Trigger
Set up the Linear webhook trigger so the workflow starts whenever an issue event occurs in your Linear team.
- Add and open Linear Issue Event Trigger.
- Set Team ID to
[YOUR_ID]. - Set Authentication to
oAuth2. - Credential Required: Connect your linearOAuth2Api credentials.
Step 2: Connect Linear and Todoist
This workflow uses multiple Todoist and Linear actions; ensure all nodes share the correct credentials.
- Credential Required: Connect your linearOAuth2Api credentials for Fetch Parent Issue and Fetch Parent Issue B.
- Credential Required: Connect your todoistApi credentials to all Todoist nodes (10+ nodes handle search, create, update, close, and delete actions).
- Confirm that Search Existing Task A and Search Existing Task B use Operation
getAlland Return All set totrue.
Step 3: Set Up Routing and Task Presence Checks
Route by Linear action type and confirm whether a Todoist task already exists before taking action.
- Open Route by Action Type and confirm the three rules match
{{ $json.action }}forremove,create, andupdate. - In Search Existing Task A and Search Existing Task B, set Filters → Filter to
=rechercher : {{ $json.data.id }}so tasks are matched by Linear issue ID. - In Verify Task Presence A and Verify Task Presence B, keep the notEmpty check on
{{ $json }}to only act on existing tasks.
Step 4: Configure Parent Issue Checks and Title Composition
When a Linear issue has a parent, fetch the parent and build a combined title for Todoist tasks.
- In Check Due Date & Assignee A and Check Due Date & Assignee B, verify the conditions use
{{ $('Route by Action Type').item.json.data.dueDate }}and assignee email equals[YOUR_EMAIL]. - In Check For Parent Issue and Check For Parent Issue B, ensure the parent ID check uses
{{ $('Route by Action Type').item.json.data.parentId }}. - In Fetch Parent Issue and Fetch Parent Issue B, set Issue ID to
{{ $('Route by Action Type').item.json.data.parentId }}and Operation toget. - In Compose Parent-Child Title and Compose Parent-Child Title B, set the title value to
{{ '[' + $json.title + ']' + ' -> ' + $('Route by Action Type').item.json.data.title }}and enable Include Other Fields.
Step 5: Configure Todoist Actions (Create, Update, Close, Delete)
These nodes create or update Todoist tasks and close or delete tasks based on Linear status and action type.
- In Create Todoist Task A, set Content to
{{ $('Route by Action Type').item.json.data.title }}, add labellinear, and set Project to[YOUR_ID]. - In Create Todoist Task B, set Content to
{{ $json.title }}, add labellinear, and set Project to[YOUR_ID]. - In Modify Todoist Task, set Task ID to
{{ $('Verify Task Presence B').item.json.id }}and confirm update fields use{{ $json.title }},{{ $('Route by Action Type').item.json.data.url }}, and{{ $('Route by Action Type').item.json.data.dueDate }}. - In Modify Todoist Task B, set Task ID to
{{ $json.id }}and map fields to{{ $('Linear Issue Event Trigger').item.json.data.title }}and related Linear data. - In Close Todoist Item and Close Todoist Item B, set Operation to
closeand confirm the Task ID expressions ({{ $('Verify Task Presence B').item.json.id }}or{{ $json.id }}). - In Delete Todoist Task and Delete Todoist Task B, set Operation to
deletewith Task ID{{ $json.id }}.
Done vs. ["Todo","In Progress","Backlog","In Review"] to decide whether to close or update tasks.Step 6: Test and Activate Your Workflow
Run a controlled test to verify tasks are created, updated, or closed correctly in Todoist based on Linear issue events.
- Click Execute Workflow and trigger a Linear issue event (create, update, remove) in your team.
- Confirm that Route by Action Type routes to the correct branch and that Search Existing Task A or Search Existing Task B returns data.
- Verify that the resulting Todoist task is created, updated, closed, or deleted with the expected content and description.
- Once validated, toggle the workflow Active to enable production syncing.
Watch Out For
- Linear credentials can expire or need specific permissions. If things break, check your n8n credential connection status first.
- If you’re using Wait nodes or external rendering, processing times vary. Bump up the wait duration if downstream nodes fail on empty responses.
- Default prompts in AI nodes are generic. Add your brand voice early or you’ll be editing outputs forever.
Common Questions
About 30 minutes if your Linear and Todoist accounts are ready.
Yes. No coding required, but you do need to follow the setup steps carefully. Most of the work is just connecting accounts and pasting in your Linear email for the assignee filter.
Yes. n8n has a free self-hosted option and a free trial on n8n Cloud. Cloud plans start at $20/month for higher volume. You’ll also need to factor in Linear and Todoist costs (usually $0 for the APIs in normal use).
Two options: n8n Cloud (managed, easiest setup) or self-hosting on a VPS. For self-hosting, Hostinger VPS is affordable and handles n8n well. Self-hosting gives you unlimited executions but requires basic server management.
You can change the “assigned to me” behavior by editing the IF checks that look for your Linear email, which is the main filter deciding what becomes a Todoist task. Common tweaks include syncing additional Linear states (not just Done), switching the target Todoist project from Inbox to a dedicated project, and adjusting the task title formatting so it includes team name, priority, or a short prefix. If you don’t want deletions to remove tasks, route the “remove” action to a no-op instead of the delete node.
Usually it’s expired OAuth credentials in n8n. Reconnect Linear in your n8n credentials, then re-run a test event from Linear. If it still fails, check that the Linear workspace permissions allow issue read access, and confirm you’re listening to the right team or project in the trigger.
On n8n Cloud Starter, you can run a few thousand executions per month, which is plenty for most personal and small-team syncing.
Often, yes, because this automation needs branching logic (create vs update vs remove, plus completion handling, plus parent-title enrichment) and n8n handles that cleanly without turning it into five separate zaps or scenarios. The “search then update or create” pattern is also easier to control in n8n, so duplicates are less likely. Zapier or Make can still work if your use case is simpler, but you may spend more time stitching together edge cases. If you’re unsure, run the numbers on how many steps you’d need and what happens when an issue is renamed or deleted. Talk to an automation expert and we’ll sanity-check your setup.
Once Linear and Todoist stop drifting, planning your day becomes simple again. Set it up once, then let the workflow keep your list honest.
Need Help Setting This Up?
Our automation experts can build and customize this workflow for your specific needs. Free 15-minute consultation—no commitment required.