npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

mirror-tasks

v1.3.3

Published

Bidirectional sync between Leantime and Trello with status mapping, milestones, users, and HTML to Markdown conversion

Readme

Mirror Tasks - Leantime ↔ Trello Sync

A TypeScript application that provides bidirectional synchronization between Leantime and Trello, with project-based filtering, automatic backup/restore, and advanced features like status mapping, milestone labels, and user assignments.

Features

  • Project-based sync: Only syncs projects listed in projects.csv (max 10)
  • Project code suffixes: Adds #CODE-<task-id> suffix to task names (at the end)
  • Status synchronization: Maps Leantime statuses to Trello lists automatically
  • Milestone labels: Syncs Leantime milestones as Trello labels
  • User assignments: Syncs Leantime user assignments to Trello card members
  • Task relations: Syncs task dependencies and relations as comments and in descriptions
  • HTML to Markdown: Converts Leantime HTML descriptions to clean Markdown for Trello
  • Override mode: Force one-way sync from Leantime to Trello (overwrites Trello)
  • Optional Leantime prefixes: Can add suffixes to Leantime headlines (via ADD_PREFIX_TO_LEANTIME env var)
  • Automatic cleanup: Removes Trello cards for projects not in CSV list (with backup)
  • Backup & restore: Automatically backs up removed projects and supports restore
  • Bidirectional sync: Syncs changes from both Leantime and Trello
  • Dry-run mode: Test sync without making changes
  • Simulation mode: Fetch and save data without making changes
  • Continuous sync server: Run as a service with web UI for play/pause/force sync
  • Multi-instance support: Support multiple Leantime and Trello instances with separate mappings

Prerequisites

  • Node.js 18+ (for native fetch support)
  • TypeScript 5.9+
  • Leantime API token
  • Trello API key and token

Installation

  1. Clone the repository:
git clone <repository-url>
cd mirror-tasks
  1. Install dependencies:
npm install
  1. Copy the example environment file:
cp .env.example .env
  1. Edit .env with your configuration (see Configuration)

  2. Copy the example projects CSV:

cp projects.csv.example projects.csv
  1. Edit projects.csv with your project codes and names (see Project CSV Format)

Configuration

Environment Variables

Create a .env file based on .env.example:

| Variable | Required | Default | Description | |----------|----------|---------|-------------| | LEANTIME_URL | Yes* | - | Leantime server URL (or LEANTIME1_URL, LEANTIME2_URL, etc. for multi-instance) | | LEANTIME_APITOKEN | Yes* | - | Leantime API token (or LEANTIME1_APITOKEN, LEANTIME2_APITOKEN, etc.) | | TRELLO_API_KEY | Yes* | - | Trello API key (or TRELLO1_API_KEY, TRELLO2_API_KEY, etc. for multi-instance) | | TRELLO_APITOKEN | Yes* | - | Trello API token (or TRELLO1_APITOKEN, TRELLO2_APITOKEN, etc.) | | TRELLO_BOARD_ID | Conditional | - | Trello board ID (or TRELLO1_BOARD_ID, TRELLO2_BOARD_ID, etc.) | | TRELLO_LIST_ID | No | First open list | Default Trello list for new cards | | PROJECTS_CSV_PATH | No | ./projects.csv | Path to projects CSV file | | STATUS_MAPPING_PATH | No | ./status-mapping.json | Path to status mapping configuration | | USER_MAPPING_PATH | No | ./user-mapping.json | Path to user mapping configuration | | LEANTIME_RATE_LIMIT_MS | No | 5000 | Rate limit delay for Leantime API (milliseconds) | | BACKUP_DIR | No | ./backups | Directory for backups | | SYNC_STATE_FILE | No | ./.data/sync-state.json | Sync state file path | | ADD_PREFIX_TO_LEANTIME | No | false | Add suffix to Leantime headlines | | SYNC_INTERVAL_SECONDS | No | 0 | Sync interval (0 = single run) | | SYNC_INTERVAL_MINUTES | No | 10 | Sync interval for server mode (minutes) | | PORT | No | 3000 | Server port for web UI | | SYNC_DRY_RUN | No | false | Enable dry-run mode |

*Trello credentials are optional in simulation mode.

Project CSV Format

The projects.csv file should have the following columns:

  • CODE: Short project code (e.g., "CRM", "OPS", "XCR")
  • NAME: Exact Leantime project name (case-sensitive matching)
  • TRELLO_BOARD_ID (optional): Trello board ID for per-project boards
  • LEANTIME_INSTANCE (optional): Leantime instance identifier (1, 2, 3, etc.). Defaults to "1"
  • TRELLO_INSTANCE (optional): Trello instance identifier (1, 2, 3, etc.). Defaults to "1"

Example (single instance):

CODE,NAME,TRELLO_BOARD_ID
XCR,XCerdible,bUgDmx8G
CRM,CRM System Rollout,
OPS,Internal Ops Improvements,

Example (multiple instances):

CODE,NAME,TRELLO_BOARD_ID,LEANTIME_INSTANCE,TRELLO_INSTANCE
XCR,XCerdible,bUgDmx8G,1,1
PROJ2,Project 2,boardId2,2,2
PROJ3,Project 3,boardId3,1,3

Notes:

  • Only the first 10 projects are processed
  • If TRELLO_BOARD_ID is provided in CSV, each project syncs to its own board
  • If TRELLO_BOARD_ID is not in CSV, use TRELLO_BOARD_ID from .env for all projects
  • Project name matching is case-insensitive but must match exactly after trimming
  • Multi-instance support: Each instance pair (Leantime + Trello) has separate:
    • API credentials (LEANTIME1_URL, TRELLO1_API_KEY, etc.)
    • Sync state files (.data/sync-state-leantime1-trello1.json)
    • Status and user mapping configs (optional: status-mapping-1.json, user-mapping-1.json)

Usage

Build the project:

npm run build

Run a single sync (bidirectional):

npm run sync
# or
npm start
# or
npm run dev

Run in override mode (force Leantime → Trello):

npm run sync:override
# or
npm run dev -- --override

Override mode:

  • Forces all Leantime tasks to Trello cards (one-way sync)
  • Updates existing cards or creates new ones
  • Ignores timestamps and sync state
  • Useful for initial sync or when you want to overwrite Trello with Leantime data

Run in dry-run mode (test without changes):

npm run sync:dry
# or
npm run dev -- --dry-run

Run in simulation mode (fetch and save data only):

npm run simulate
# or
npm run dev -- --simulate

# With custom output directory:
npm run dev -- --simulate --simulation-output ./my-data

Simulation mode:

  • Fetches all data from Leantime (projects and tasks)
  • Fetches data from Trello (if TRELLO_BOARD_ID is provided)
  • Saves data to JSON files in ./simulation-data/ (or custom directory)
  • Does NOT make any changes to either system
  • Creates a summary file with statistics

Restore a project from backup:

npm run dev -- --restore-project CRM --restore-folder ./backups/removed-projects/CRM

Run as continuous sync server (with web UI):

# Development mode (uses ts-node, no build needed)
npm run server

# Production mode (uses compiled JS, faster, requires build first)
npm run build
npm run server:prod

# Or via CLI flag
npm run dev -- --server

Difference between server and server:prod:

  • npm run server: Runs TypeScript directly using ts-node (development mode, slower startup, no build needed)
  • npm run server:prod: Runs compiled JavaScript from dist/ (production mode, faster startup, requires npm run build first)

The server mode provides:

  • Web UI: Open http://localhost:3000 (or custom PORT env var) in your browser
  • Play/Pause: Control sync execution
  • Force Sync: Manually trigger a sync immediately
  • Status Display: Shows current status, last sync time, and errors
  • Automatic Sync: Runs sync every X minutes (configurable via SYNC_INTERVAL_MINUTES env var, default: 10 minutes)

Environment Variables for Server Mode:

  • PORT: Server port (default: 3000)
  • SYNC_INTERVAL_MINUTES: Sync interval in minutes (default: 10)

Example:

# Start server on port 3000, sync every 10 minutes
PORT=3000 SYNC_INTERVAL_MINUTES=10 npm run server

# Start server on port 8080, sync every 5 minutes
PORT=8080 SYNC_INTERVAL_MINUTES=5 npm run server

The web UI provides:

  • Real-time status updates (refreshes every 2 seconds)
  • Play button to resume paused sync
  • Pause button to pause sync
  • Force Sync button to trigger immediate sync
  • Last sync time display
  • Error messages if sync fails

CLI Commands

All commands can be run with npm run <script> or npm run dev -- <flags>:

| Command | Description | |---------|-------------| | npm run build | Compile TypeScript to JavaScript | | npm run dev | Run TypeScript directly (development) | | npm start | Run compiled JavaScript | | npm run sync | Run single bidirectional sync | | npm run sync:dry | Run sync in dry-run mode (no changes) | | npm run sync:override | Run override mode (force Leantime → Trello) | | npm run simulate | Fetch and save data without changes | | npm run server | Start continuous sync server with web UI | | npm run server:prod | Start server (production, uses compiled JS) |

CLI Flags

  • --dry-run or --dry: Enable dry-run mode
  • --override: Enable override mode (force Leantime → Trello)
  • --simulate or --simulation: Enable simulation mode
  • --simulation-output <dir>: Custom output directory for simulation
  • --restore-project <code>: Restore a project from backup
  • --restore-folder <path>: Backup folder path for restore

How It Works

Sync Process

  1. Project Matching: Matches Leantime projects to CSV entries by name (case-insensitive)
  2. Status Mapping: Fetches Leantime statuses and creates/uses Trello lists
  3. Milestone Mapping: Fetches Leantime milestones and creates/uses Trello labels
  4. User Mapping: Matches Leantime users to Trello board members (by email/username)
  5. Task Prefixing: Adds #CODE-<task-id> suffix to task names (at the end, e.g., "Task Name #XCR-123")
  6. HTML Conversion: Converts Leantime HTML descriptions to Markdown for Trello
  7. Sync Logic:
    • Normal mode: Bidirectional sync based on last modified timestamps
    • Override mode: Force all Leantime tasks → Trello cards (one-way)
    • New Leantime tasks → Create Trello cards with suffix
    • New Trello cards → Create Leantime tasks (normal mode only)
    • Updated items sync based on last modified timestamp (normal mode)
  8. Cleanup: Cards with project codes not in CSV are backed up and archived
  9. Backup: Full snapshots saved to BACKUP_DIR, removed projects saved to BACKUP_DIR/removed-projects/

Status Synchronization

  • Fetches status configuration from Leantime API
  • Uses status mapping configuration to map Leantime status names to Trello list names
  • Creates Trello lists for each mapped status (or uses existing lists with matching names)
  • Moves cards to the correct list based on task status
  • Status 100 (Done) → Card is closed in Trello

Status Mapping

You can configure custom mappings between Leantime status names and Trello list names using status-mapping.json:

{
  "statusMappings": {
    "New": "To Do",
    "In Progress": "Doing",
    "Review": "Review",
    "Done": "Done",
    "Blocked": "Blocked"
  },
  "statusIdMappings": {
    "1": "To Do",
    "2": "Doing",
    "3": "Review",
    "4": "Done",
    "5": "Blocked"
  },
  "defaultMapping": "To Do"
}
  • statusMappings: Maps Leantime status names (keys) to Trello list names (values)
  • statusIdMappings: Maps Leantime status IDs (keys as strings) to Trello list names (values). Use this when the status API doesn't return data or you want direct ID mapping.
  • defaultMapping: Default Trello list name if no mapping is found for a status

Note: If the status API doesn't return data, the system will use statusIdMappings to map status IDs directly. Check the console logs to see what status IDs your tasks have, then add them to statusIdMappings.

If no mapping file is provided, Leantime status names are used directly as Trello list names.

Milestone Labels

  • Fetches milestones from Leantime
  • Creates Trello labels for each milestone (with colors)
  • Assigns labels to cards based on task milestone

User Assignments

  • Fetches users from Leantime
  • Matches users to Trello board members by email or username
  • Assigns Trello members to cards based on Leantime user assignments

HTML to Markdown Conversion

  • Strips ProseMirror and other rich text editor data attributes
  • Converts HTML tags to Markdown (headings, lists, links, bold, italic, etc.)
  • Extracts plain text from nested HTML structures
  • Cleans up whitespace and formatting

Project Structure

.
├── src/
│   ├── index.ts              # Main entry point
│   ├── sync-service.ts       # Sync logic
│   ├── leantime-client.ts    # Leantime API client
│   ├── trello-client.ts      # Trello API client
│   ├── backup-service.ts     # Backup management
│   ├── project-config.ts     # CSV loader
│   └── types.ts              # TypeScript types
├── projects.csv              # Project configuration (not in git)
├── projects.csv.example     # Example project configuration
├── .env.example              # Example environment variables
├── package.json
├── tsconfig.json
└── README.md

Development

Type checking:

npx tsc --noEmit

Run in development mode:

npm run dev

Build for production:

npm run build
npm start

Notes

  • Project matching is case-insensitive but must match exactly after trimming
  • Trello cards are identified by the #CODE-<number> suffix pattern (at the end of the name)
  • Removed projects are archived (closed) in Trello, not deleted
  • All sync operations are logged to console
  • Backup files are JSON format with timestamps
  • Rate limiting: 3 seconds between Leantime API calls to avoid 429 errors
  • HTML conversion handles ProseMirror, TinyMCE, and other rich text editor formats

Troubleshooting

Cards not syncing

  • Check that project names in CSV exactly match Leantime project names
  • Verify API credentials are correct
  • Check console logs for errors

HTML not converting properly

  • The converter handles most HTML formats, but complex nested structures may need manual cleanup
  • Check the Trello card description to see the converted Markdown

Status lists not created

  • Ensure the Leantime API returns status configuration
  • Check console logs for status fetching errors
  • Lists are created automatically on first sync

Users not matching

  • Ensure Trello board members have email addresses set
  • Check that Leantime users have matching emails or usernames
  • User matching is case-insensitive

License

MIT