A command-line microservice that automatically synchronizes Linear issues with your Motion calendar, eliminating the manual effort of keeping your work items in sync between platforms.
The Linear-Motion Sync Tool is designed for developers who use Linear for team project management and Motion for personal task and calendar management. It provides a robust, configurable pipeline to sync assigned Linear issues to your Motion calendar, ensuring your personal to-do list accurately reflects your work commitments.
- Automated Task Creation: Automatically creates Motion tasks from assigned Linear issues
- Bidirectional Status Updates: Marks Linear issues with completion tags when tasks are finished in Motion
- Flexible Configuration: Support for multiple Linear workspaces, custom time estimates, and sync schedules
- Fault Tolerance: Resilient to API failures with comprehensive error logging
- Real-time Updates: Webhook and polling support for immediate synchronization
cargo install linear-motion
ubi --project arlyon/linear-motion
mise use -g cargo:linear-motion
mise use -g ubi:arlyon/linear-motion
Download the latest binary from the GitHub releases page.
-
Initialize configuration:
linear-motion init
-
Edit the generated
config.json
with your API keys and preferences -
Run a one-time sync:
linear-motion sync
-
Start continuous background syncing:
linear-motion sync --watch
-
Check sync status:
linear-motion status
-
(coming soon) Podman Quadlet: Run the daemon under podman + systemd with auto-updates.
To run the sync command periodically as a specific user on a modern Fedora system, the best practice is to create a systemd
user service and a corresponding timer unit. This is the modern replacement for user-level cron jobs.
This process involves creating two files in your user's configuration directory.
This file tells systemd
what command to run.
-
First, ensure the target directory exists:
mkdir -p ~/.config/systemd/user/
-
Create the service file:
nano ~/.config/systemd/user/linear-motion-sync.service
-
Add the following content:
[Unit] Description=Sync Linear Motion data [Service] Type=oneshot ExecStart=/linear-motion sync
Description
: A human-readable description of what the service doesType=oneshot
: Suitable for a script that starts, performs a single task, and then exitsExecStart
: The full, absolute path to the command you want to run
This file tells systemd
when to run the service defined above.
-
Create the timer file (must have the same name as the service file, but with a
.timer
extension):nano ~/.config/systemd/user/linear-motion-sync.timer
-
Add the following content:
[Unit] Description=Run Linear Motion sync once an hour [Timer] OnCalendar=hourly Persistent=true [Install] WantedBy=timers.target
>: Runs the job at the top of every hour (e.g., 1:00, 2:00, 3:00)
Persistent=true
: If the system was powered off when the job was supposed to run, it will run as soon as possible after the next boot/loginWantedBy=timers.target
: Tellssystemd
how to enable the timer so it starts automatically when you log in
Important: Because these are user services, you must use the --user
flag with systemctl
. Do not use sudo
.
# Reload the systemd user daemon to pick up the new files
systemctl --user daemon-reload
# Enable and start the timer
systemctl --user enable --now linear-motion-sync.timer
The tool uses a config.json
file for configuration. Here's the structure:
{
"motion_api_key": "your_motion_api_key",
"sync_sources": [
{
"name": "My Team",
"linear_api_key": "your_linear_api_key",
"projects": ["PROJECT-1", "PROJECT-2"],
"webhook_base_url": "https://your-domain.com/webhooks",
"sync_rules": {
"default_task_duration_mins": 60,
"completed_linear_tag": "motioned",
"time_estimate_strategy": {
"fibonacci": {
"1": 30,
"2": 60,
"3": 120,
"5": 240,
"8": 480
},
"default_duration_mins": 60
}
}
}
],
"global_sync_rules": {
"default_task_duration_mins": 60,
"completed_linear_tag": "motioned",
"time_estimate_strategy": {
"default_duration_mins": 60
}
},
"polling_interval_seconds": 300,
"schedule_overrides": [
{
"name": "Work Hours",
"interval_seconds": 60,
"start_time": "09:00",
"end_time": "17:00",
"days": ["mon", "tue", "wed", "thu", "fri"]
}
]
}
- motion_api_key: Your Motion API key for task management
- sync_sources: Array of Linear workspace configurations
- name: Friendly name for the sync source
- linear_api_key: Linear API key for this workspace
- projects: Optional list of specific Linear projects to sync
- webhook_base_url: Optional webhook URL for real-time updates
- sync_rules: Source-specific sync rules (overrides global rules)
- global_sync_rules: Default sync behavior
- default_task_duration_mins: Default task duration when no estimate exists
- completed_linear_tag: Tag applied to Linear issues when Motion tasks are completed
- time_estimate_strategy: Mapping of Linear estimates to Motion durations
- polling_interval_seconds: How often to check for updates (default: 300 seconds)
- schedule_overrides: Different polling intervals for specific times/days
The tool supports multiple estimation systems:
- Fibonacci: Story point values (1, 2, 3, 5, 8, 13, etc.)
- T-Shirt: Size-based estimates (XS, S, M, L, XL)
- Linear: Linear's built-in estimation
- Points: Generic point-based system
- Initial Sync: On startup, syncs all open assigned Linear issues to Motion
- Ongoing Updates: Uses webhooks or polling to detect new/updated Linear issues
- Task Creation: Creates Motion tasks with appropriate durations based on Linear estimates
- Completion Tracking: Monitors Motion for completed tasks
- Bidirectional Update: Tags completed Linear issues and removes them from sync
-
linear-motion init
- Generate configuration template -
linear-motion sync
- Run one-time sync -
linear-motion sync --watch
- Start continuous background sync -
linear-motion status
- Show current sync status and errors
Perfect for developers who:
- Use Linear for sprint planning and issue tracking
- Use Motion for personal time management and calendar blocking
- Want to automate the tedious task of keeping both systems in sync
- Need accurate time blocking based on work estimates
- Want bidirectional status updates between systems
- Database: Uses local
fjall
database for ID mappings and status tracking - API Integration: Respects rate limits for both Linear and Motion APIs
- Fault Tolerance: Handles API failures gracefully with retry logic
- Concurrency: Single daemon process with IPC for status queries
- Security: API keys stored in local configuration file
Contributions are welcome! Please see the contributing guidelines for details.
This project is dual-licensed under either of
- Apache License, Version 2.0, (LICENSE-APACHE)
- MIT license (LICENSE-MIT)
at your option. See LICENSE.md for details.