gantt2drawio
gantt2drawio turns a small YAML project definition into an editable draw.io (.drawio) Gantt chart.
The package is intentionally a renderer, not a full project-management system. You provide calendar dates or relative positions such as M0 and M6; the package handles validation, timeline layout, and draw.io XML generation.
See it in action
| 1. YAML input | 2. Terminal preview |
|---|---|
|
|
|
3. Editable draw.io output
What it supports
- Calendar tasks using ISO dates and calendar-day (
d) or week (w) durations - Relative-month tasks using positions such as
M0and durations such as6M - Milestones on calendar dates or within complete relative months
- Optional compact rows with milestone IDs placed on their preceding task bars
- Optional inherited starts for relative tasks
- Weekly, monthly, or automatically selected timelines
- Optional task and milestone colors
- Configurable wrapping, clipping, and ellipsis for long item names
- Strict validation with field-specific errors
- Editable draw.io shapes with stable IDs
- A command-line interface and a small Python API
- Dependency-free Unicode and ASCII terminal previews
- Deterministic, uncompressed XML suitable for version control
Version 0.7 deliberately does not include dependencies, automatic scheduling, nested groups, progress bars, business-day calendars, or critical-path analysis.
Installation
The package requires Python 3.9 or newer.
Install the package from PyPI:
python -m pip install gantt2drawio
Install the project from this directory:
python -m pip install .
For development, install it in editable mode with the test dependency:
python -m pip install -e ".[dev]"
Quick start
Calendar timeline
Create project.yaml:
version: 1
chart:
title: Research project
scale: month
items:
- id: literature-review
type: task
name: Literature review
start: 2026-08-01
duration: 4w
- id: experiments
type: task
name: Run experiments
start: 2026-09-01
end: 2026-11-30
color: "#59A14F"
- id: final-report
type: milestone
name: Final report submitted
date: 2026-12-15
Validate it:
gantt2drawio validate project.yaml
Generate the diagram:
gantt2drawio build project.yaml -o project.drawio
If -o is omitted, the output uses the input name with a .drawio suffix:
gantt2drawio build project.yaml
# writes project.drawio
Open the resulting file in the draw.io desktop application or import it into diagrams.net. Task bars, milestone diamonds, labels, and table cells are native editable diagram elements.
Relative timeline
Use relative mode when exact calendar dates are not known:
version: 1
chart:
title: Relative research programme
mode: relative
unit: month
start: M0
end: M18
items:
- id: literature-review
type: task
name: Literature review
duration: 6M
- id: first-review
type: milestone
name: First review
date: M3
- id: experiments
type: task
name: Run experiments
start: M4
end: M12
Because the first task has no start, it inherits chart.start. Its 6M
duration covers the six complete months M0 through M5. Save the definition
as relative-project.yaml and generate it in exactly the same way:
gantt2drawio build relative-project.yaml
Terminal preview
Preview a chart without creating a draw.io file:
gantt2drawio preview examples/relative.yaml
Example output:
Relative research programme — M0 to M18 (relative-month)
Item M0 M1 M2 M3 M4 M5
────────────────────────────────────────────────
Literature review ███████████████████████████
First review ◆
Run experiments ██████████
█ task ◆ milestone
The preview uses the same resolved dates, relative positions, and timeline geometry as the draw.io renderer. It scales to the current terminal width and truncates long names when necessary.
Useful preview options:
# Select a width
gantt2drawio preview project.yaml --width 120
# Use portable ASCII characters
gantt2drawio preview project.yaml --ascii
build prints a preview automatically when its output is an interactive terminal. This avoids adding noise when the command is redirected or used in a script. The behavior can be controlled explicitly:
# Force a preview when output is redirected
gantt2drawio build project.yaml --preview
# Suppress an interactive preview
gantt2drawio build project.yaml --no-preview
# Configure the build preview
gantt2drawio build project.yaml --preview-width 120 --ascii-preview
YAML reference
Top level
| Field | Required | Description |
|---|---|---|
version |
No | Schema version. If present, it must be the integer 1. |
chart |
No | Chart-wide configuration. |
items |
Yes | A non-empty list of tasks and milestones. |
Unknown fields are rejected. This helps catch spelling mistakes rather than silently ignoring them.
Chart
Calendar mode is the default:
chart:
title: Research project
scale: auto
start: 2026-01-01
end: 2026-12-31
| Field | Default | Description |
|---|---|---|
title |
Gantt chart |
Title shown above the chart. |
mode |
calendar |
calendar or relative. |
compact |
false |
Place milestones on the preceding task row and show only task/milestone IDs. |
scale |
auto |
Calendar mode only: week, month, or auto. |
unit |
month |
Relative mode only. Version 0.6 supports month. |
start |
Mode-dependent | An ISO date or relative position such as M0. |
end |
Latest item | An inclusive ISO date or relative month such as M18. |
label_width |
240 |
Item-name column width, from 120 to 600. |
label_max_lines |
2 |
Maximum displayed lines for ellipsis or clip, from 1 to 10. |
label_overflow |
ellipsis |
ellipsis, wrap, or clip. |
auto selects a weekly timeline for projects up to 120 days and a monthly
timeline for longer projects. Explicit chart bounds may extend the item range,
but may not exclude an item.
Relative mode uses equal-width abstract month intervals:
chart:
mode: relative
unit: month
start: M0
end: M18
chart.start defaults to M0 in relative mode. chart.end is optional and is derived from the latest task or milestone. Calendar dates and relative positions cannot be mixed in the same chart. scale is not used in relative mode because unit determines the timeline.
Tasks
Every task requires id, type, and name, plus exactly one of end or
duration.
In calendar mode, start is required:
Using an explicit end date:
- id: experiments
type: task
name: Run experiments
start: 2026-09-01
end: 2026-11-30
Using a duration:
- id: review
type: task
name: Literature review
start: 2026-08-01
duration: 10d
End dates are inclusive. Therefore, a task starting on 2026-08-01 with duration: 10d ends on 2026-08-10.
Supported duration units are:
| Suffix | Meaning | Example |
|---|---|---|
d |
Calendar days | 10d |
w |
Seven-day weeks | 4w |
In relative mode, start may be omitted. An omitted start inherits chart.start, which defaults to M0:
- id: work-package
type: task
name: Work package
duration: 6M
This task starts on the first day of M0 and ends on the last day of M5,
representing exactly six complete relative months. An explicit range uses
inclusive month semantics:
- id: experiments
type: task
name: Run experiments
start: M4
end: M12
Relative positions must be non-negative integer values such as M0, M3, or M18. Relative durations use an uppercase M, such as 1M or 6M.
Timeline columns represent complete months and are labelled M0, M1, M2,
and so on. Both start and end are inclusive: a task with start: M0 and
end: M6 spans seven full columns, M0 through M6. A task with start: M0
and duration: 6M spans M0 through M5.
Milestones
A milestone requires id, type, name, and date:
- id: approval
type: milestone
name: Protocol approved
date: 2026-09-18
In relative mode, date identifies a complete relative month:
- id: approval
type: milestone
name: Protocol approved
date: M3
The milestone diamond is placed in the centre of the M3 month cell.
Compact mode
Set chart.compact to true to remove separate milestone rows:
chart:
mode: relative
compact: true
end: M8
items:
- id: T1
type: task
name: Literature review
duration: 6M
- id: M1
type: milestone
name: Initial review
date: M2
- id: M2
type: milestone
name: Review complete
date: M5
Compact mode displays T1 in the task column and places diamonds labelled
M1 and M2 on the same row at their timeline positions. Each milestone is
attached to the nearest preceding task and remains attached until another task
entry begins. Its date must fall within that task's inclusive start/end range,
so the diamond can be drawn on the colored duration bar. Multiple milestones
may share one task row. A milestone before the first task is rejected because
it has no task to attach to.
Task and milestone names are hidden visually in compact mode, but their
complete values remain available as fullName and tooltip metadata in the
draw.io XML. The terminal preview follows the same grouping and ID-only display.
The regular one-item-per-row layout remains the default.
Long item names
Control task and milestone name layout through the chart settings:
chart:
label_width: 240
label_max_lines: 2
label_overflow: ellipsis
The available overflow modes are:
| Mode | Behavior |
|---|---|
ellipsis |
Show at most label_max_lines and add ... when text is omitted. |
wrap |
Show the complete name and expand the row height as necessary. |
clip |
Show at most label_max_lines without adding .... |
Wrapping prefers word boundaries, breaks unusually long words when necessary, and treats Chinese, Japanese, and Korean characters as double-width. Task bars and milestone diamonds remain vertically centered when a row expands.
The complete original name is always retained in the generated XML as fullName and tooltip metadata, even when the visible label is shortened.
IDs and colors
IDs must be unique and may contain letters, numbers, dots, underscores, and hyphens. They are used to create stable draw.io cell IDs.
Colors are optional six-digit hexadecimal values:
color: "#4C78A8"
Tasks default to blue and milestones default to red.
Python API
Generate a file directly:
from gantt2drawio import render_file
render_file("project.yaml", "project.drawio")
Or validate and render in memory:
from gantt2drawio import load_project, render
project = load_project("project.yaml")
xml = render(project)
Terminal previews are also available through the Python API:
from gantt2drawio import load_project, render_preview
project = load_project("project.yaml")
print(render_preview(project, width=100))
Validation failures raise GanttValidationError; file access failures raise GanttInputError. Both inherit from GanttError.
Validation errors
The validator reports the YAML location and all issues it can safely identify:
project.yaml is not a valid Gantt definition:
- items[0].duration must use a positive 'd' or 'w' duration such as '10d' or '4w'
- items[1].date must be a valid ISO date in YYYY-MM-DD form
The CLI returns status code 0 on success and 2 for validation or file
errors.
Examples
examples/basic.yamldemonstrates a monthly research plan.examples/weekly.yamldemonstrates a short weekly plan.examples/relative.yamldemonstrates an 18-month relative plan.examples/compact.yamldemonstrates multiple milestones on each task row.examples/long-labels.yamldemonstrates ellipsis with English and Chinese names.
Generate all examples with:
gantt2drawio build examples/basic.yaml
gantt2drawio build examples/weekly.yaml
gantt2drawio build examples/relative.yaml
gantt2drawio build examples/compact.yaml
gantt2drawio build examples/long-labels.yaml
Development
Run the test suite:
python -m pytest
Run the static style and import checks:
python -m flake8 src tests
The tests cover calendar and relative durations, strict YAML validation, inclusive calendar dates, inclusive relative-month semantics, timeline geometry, Unicode-aware label formatting, terminal previews, deterministic XML rendering, and all CLI commands.
License
MIT
Metadata
Release files for gantt2drawio 0.7.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| gantt2drawio-0.7.0.tar.gz | 33.5 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| gantt2drawio-0.7.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 60.7 kB
Release files / gantt2drawio-0.7.0.tar.gz
| Download URL | gantt2drawio-0.7.0.tar.gz |
|---|---|
| Size | 33.5 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
0d07ad7b0604e8382c3f30826f77cda2f9255ed78b972c14b84863e2c92f59a2
|
|
BLAKE2b-256 checksum How to use checksums |
5652c1d60290fa81acefc57d0ed34c11869b939c2aabec20a3a02f6f92a810c4
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.11.13
|
Release files / gantt2drawio-0.7.0-py3-none-any.whl
| Download URL | gantt2drawio-0.7.0-py3-none-any.whl |
|---|---|
| Size | 27.3 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
137814b931d22539cd0e045cf7cd52ac0505aaa4b73292b2d7719541cd435da0
|
|
BLAKE2b-256 checksum How to use checksums |
8914d7e45b4ee9a98b73c841022292bba5fba3136ecd1577aa743e07938e4d0d
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.11.13
|