Project Management

Building on task dependencies, Scimax turns a set of org TODO tasks into a small project-management view: a *task table*, a *project view* with a graphical Gantt chart, a *dependency graph*, and a *people database* with assignee autocomplete. Everything is driven off metadata you already put on headings — SCHEDULED/DEADLINE, EFFORT, priority, :DEPENDS:, and :ASSIGNEE:.

✅ The data a task carries

* Project X
  :PROPERTIES:
  :ID: proj-x
  :ASSIGNEE: jrk          ← whole subtree assigned to jrk (inherited)
  :END:
** TODO Run analysis
   SCHEDULED: <2026-07-01 Wed>
   :PROPERTIES:
   :ID: analysis
   :EFFORT: 2d
   :END:
** NEXT Make figures                      :@ana:   ← @tag also assigns
   :PROPERTIES:
   :ID: figures
   :EFFORT: 4h
   :DEPENDS: id:analysis
   :END:
** TODO [#A] Write paper
   DEADLINE: <2026-07-20 Mon>
   :PROPERTIES:
   :ID: paper
   :EFFORT: 1d
   :DEPENDS: id:analysis id:figures
   :END:
  • EFFORT accepts 2d, 4h, 0:30, 90m (a day = 8 hours).

  • :ASSIGNEE: holds one or more handles; it is inherited from ancestor subtrees, and @name tags count as assignees too.

✅ Task table

Insert a table with cmd:scimax.org.insertProjectTable, or write the dynamic block yourself and refresh it with C-c C-c:

#+BEGIN: project-table :columns task,todo,priority,assignee,deadline,effort,blocked
#+END:

Parameters:

ParamMeaning
:columnsAny of task, todo, priority, assignee, scheduled, deadline, effort, blocked, deps
:idScope to the subtree with this heading :ID: (whole file if omitted)
:maxlevelOnly include headings up to this level
:matchOnly tasks with these tags, e.g. +urgent
:groupbyassignee or state — adds a grouping column
:include_non_todot to include headings without a TODO keyword
:scopefile (default), project (every org file under the project root), or agenda (every indexed file)

The blocked column shows 🔒 when a dependency in the block's scope is not yet done. Columns may also include file, the task's file relative to this one.

With :scope project, the table gathers tasks from every .org file under the project root (the nearest folder above this file with .git, .projectile and the like), read from disk, with this file's unsaved text. A file column is added by default, dependencies between files count for blocked, and :id does not apply:

#+BEGIN: project-table :scope project :groupby assignee
#+END:

✅ Project view

cmd:scimax.project.view (Scimax: Project View (Gantt Chart)) opens a panel with every TODO task in the active file's project on a graphical Gantt chart. The tasks come from all the .org files under the project root, read the same way as the task table's :scope project, and the panel reloads whenever one of them is saved.

Each row shows the task's state, priority, a 🔒 when it is blocked, its title and its assignees, with a bar on the timeline coloured by status: green done, red blocked, dark blue in progress (its SCHEDULED date has come), light blue planned, and a yellow diamond for a milestone. Priority [#A] bars are outlined. Arrows run from each dependency to the task that waits for it, and a red line marks today. SCHEDULED is a bar's start, else the end of its latest dependency, else the deadline minus the effort, else the project's earliest start (or today). EFFORT sets the length in working days of 8 hours; a task with SCHEDULED and DEADLINE but no effort runs to the deadline, and a task with only a DEADLINE is a milestone. Children of an :ORDERED: t parent follow one another. Rows (within each group) list the tasks that have a DEADLINE first, by start date, then the tasks without one, also by start date. The Outline grouping keeps the order of the headings instead.

  • Double-click a task (or select it and press Enter) to open it beside the chart. The arrow keys move the selection.

  • Drag a task's bar to move it, or the right end of a bar that ends on its deadline to move just the deadline. See ✅ Dragging tasks on the chart.

  • Right-click a task for: Open Task, Cycle TODO State, Set Priority..., Set Tags..., Assign..., Set Effort..., Schedule..., Set Deadline..., Later by a Day, Earlier by a Day, Clock In, Refile..., Archive Subtree and Store Link. Each runs the ordinary Scimax command on the task's heading (so repeaters, CLOSED timestamps and dependency blocking behave as usual), saves the file, and comes back to the chart. The agenda view has the same menu (see Agenda View); the two date moves shift both the SCHEDULED and DEADLINE dates here.

  • Depends On... in the right-click menu lists the project's other tasks (not done first, with their dates and files). Pick the task that must be done first: it is added to this task's :DEPENDS:, both headings get an :ID: if they lack one, both files are saved, and the chart redraws with the new arrow. The target can be in another file of the project. Tasks that already wait on this one, directly or through others, are not offered, so a cycle cannot be made.

  • Remove Dependency... lists the task's dependencies; check the ones to drop. They are taken out of its :DEPENDS: (the property goes when none are left), the file is saved, and the arrows disappear from the chart.

  • When Set Deadline... moves a task's deadline (here or in the editor, see ✅ Moving a deadline moves the tasks that wait on it), scimax offers to move the tasks that wait on it, directly or through other tasks, by the same number of days, so the gaps between them stay the same. The list shows each task's dates with every task checked: uncheck the ones to leave alone, or press Escape to move none. Their SCHEDULED and DEADLINE dates move, keeping times, repeaters and warning periods. Done tasks and tasks with no dates are not listed; an undated task already starts when its dependencies end. A task that had no deadline before has nothing to measure from, so nothing is offered.

  • The toolbar filters by Assignee (or Unassigned), groups rows by assignee, file, parent heading or Outline (the file's heading tree, see Progress, rollups and the behind flag), shows or hides Done tasks, undoes and redoes drags, zooms the timeline with - and +, and scrolls to Today.

  • Fit squeezes the whole date range into the panel's width, so there is no sideways scrolling: handy for a screenshot or a presentation. It keeps fitting when the panel is resized or the chart changes. As the days narrow, the day numbers thin out to one a week and then only today, weekend shading goes, and month names drop the year. Press - or + to zoom by hand again, or Fit to turn it off. The chart remembers the choice.

  • Tags opens a checklist of the project's tags. Check one or more to show only the tasks that have any of them; Clear shows every task again. A task's tags include those it inherits from parent headings and from #+FILETAGS, so checking :paper: on a parent heading's tag shows all the tasks under it. @name tags are assignees and are left out of the list. The button shows the chosen tags, and the tag filter combines with the assignee filter. A task's tags appear in its tooltip.

  • Files opens a checklist of the project's files that have tasks. Uncheck a file to leave its tasks out of the chart, its rollups and its exports; Show all and Hide all check or clear every file. The choice is remembered for each project, so a hidden file stays hidden when the view is reopened. To keep files out of the project altogether (the task table's :scope project too), list them in a .projectileignore or .gitignore at the project root.

Progress, rollups and the behind flag

Tick Progress in the toolbar to show how far along each task is. It is off by default, and with it off the chart and its exports look exactly as before.

  • Leaf tasks (tasks with no TODO subtasks) are 100% when DONE and 0% otherwise, unless they carry a :PROGRESS: property (50 or 50%, from 0 to 100). DONE always counts as 100%. A plain leaf without :PROGRESS: shows no percentage.

  • Parent tasks take their percentage from the leaf tasks under them; a parent's own :PROGRESS: is ignored. CANCELLED tasks are left out of both the done share and the total.

  • Weighting is set by scimax.project.progressWeighting:

    • count: every leaf counts the same.

    • effort: each leaf counts by its EFFORT. A leaf without one counts as scimax.project.defaultEffort (default 1d).

    • auto (the default): effort when at least half the leaf tasks have an EFFORT, count otherwise. The choice is made once for the whole chart, so every bar uses the same method, and the tooltip says which it is and how many tasks had no estimate.

  • Rollups count the tasks that pass the assignee and tag filters. DONE tasks still count when Done tasks is unticked, so hiding them does not drop the percentage.

  • The done share is hatched on the bar, and the percentage is shown after the bar and beside the title. A parent task becomes a grey-blue summary bar spanning its subtasks (cancelled ones excluded). Summary bars cannot be dragged. Group rows get a summary bar and percentage too.

** TODO Aim 1: Synthesis
*** DONE Prepare precursors
    :PROPERTIES:
    :EFFORT: 2d
    :END:
*** TODO Run reactions
    :PROPERTIES:
    :EFFORT: 4d
    :PROGRESS: 25
    :END:
*** CANCELLED Try the old route

Weighted by effort, Aim 1 is (2d × 100% + 4d × 25%) / 6d = 50% done; the cancelled task does not count.

Behind schedule

A task is behind when work remains and either its end date has passed, or it has started and its percentage is more than scimax.project.behindTolerance points (default 10) below the share of its span that has elapsed. For a task running Monday to Friday, on Wednesday the expected share is 40%, so with the default tolerance it is behind below 30%. Finished tasks, tasks that have not started, and plain leaves without :PROGRESS: are never behind.

Behind rows get a small amber dot by the title and a thin amber band under the bar, from the end of the hatch to today. The tooltip gives the expected and actual percentages.

Finding your way in large charts

  • Outline grouping lays rows out in the order of the headings in the files. Headings that are not shown tasks become group rows, and each file gets its own row when the project spans several files.

  • Click the ▸/▾ triangle on a row to fold or unfold what is under it. Depth (All, 1, 2, 3) shows only the top levels.

  • The N behind button with ‹ and ›, or the n and p keys, jump from one behind row to the next, opening folded rows as needed. Behind only keeps the behind rows and the rows above them for context.

  • While you scroll, the top-left corner shows the headings above the first visible row.

Folding, Depth and Behind only apply to the PDF and Excel exports too, so you can export just the level you want to present.

✅ Dragging tasks on the chart

Unfinished tasks can be moved with the mouse. The bar follows the pointer a whole day at a time, and a tip shows the new dates and how many days it moved. Press Escape before letting go to put it back.

  • Drag the bar to move the whole task: its SCHEDULED and DEADLINE dates both move by the same days, keeping times, repeaters and warning periods. A milestone (a task with only a deadline) moves its deadline. A task with neither date gets SCHEDULED on the day you drop it.

  • Drag the right end to move only the deadline. Only bars that end on their deadline have this handle: tasks with SCHEDULED and DEADLINE and no EFFORT. A bar whose length comes from EFFORT is moved by its middle instead, or by setting its effort.

When you let go, the file is saved and the chart redraws. If other tasks wait on the one you moved, the same list as for a moved deadline appears (see below): uncheck tasks to leave them alone, or press Escape to move none. Done tasks cannot be dragged.

Undo in the toolbar (or Cmd+Z / Ctrl+Z in the chart) puts the last drag back, together with the tasks that moved with it, and saves the files; Redo (Shift+Cmd+Z, Shift+Ctrl+Z or Ctrl+Y) moves them again. Hover over either button to see which move it acts on. The view remembers the last 50 drags while it is open. If a changed line was edited since, the undo is refused with a message rather than overwriting the edit.

✅ Moving a deadline moves the tasks that wait on it

Changing a task's deadline in the editor offers the same list as the project view:

  • C-c C-d (or the d speed command at a heading) sets a new deadline; the list appears right after.

  • Shift+Up / Shift+Down (or Shift+Left / Shift+Right) on a DEADLINE date move it a day at a time, so scimax waits until you stop: after a second and a half without another press, or when the cursor leaves the line, it offers to move the waiting tasks by the total. Changing only the time moves nothing.

The tasks come from the file's project, so tasks in other project files that depend on this one are listed too. Tasks in other files are saved after they move; edits in the file you are in are left for you to save. Typing a new date by hand does not trigger it.

✅ Exporting the chart

The Excel, PDF, SVG, PNG and HTML buttons in the toolbar, the right-click menu on the chart, and the commands cmd:scimax.project.exportExcel, cmd:scimax.project.exportPdf, cmd:scimax.project.exportSvg, cmd:scimax.project.exportPng and cmd:scimax.project.exportHtml save the chart as it is shown, with the current assignee and tag filters and grouping:

  • Excel (.xlsx): one sheet with the task table (task, file, state, priority, assignees, effort in hours, start and end as real dates, blocked) and a day-by-day timeline to its right, each task's days filled in its status colour, weekends shaded and today highlighted. The header rows and table columns are frozen, so the timeline scrolls under them.

  • PDF: a one-page vector chart with the same bars, milestones, dependency lines, today line and a legend. The page grows to fit every row and day, and viewers and printers scale it to the paper. Text is set in Helvetica, so characters outside Latin-1 (emoji, CJK) print as ?; blocked tasks are marked [blocked].

  • SVG: the same chart as a vector image, with full Unicode text. Hovering a row in a browser shows its dates, assignees, effort and file.

  • PNG: the SVG drawn at twice its size, for documents and slides that need a bitmap. The project view draws it, so exporting a PNG from the command palette opens the view first.

  • HTML: one self-contained, read-only page holding the chart (nothing is loaded from the network). It fits itself to the window; hovering a task shows its details, clicking it highlights everything it waits on and everything waiting on it (click again or press Esc to clear), and the -, + and Fit buttons, which appear in the top-right corner once you move the mouse (or Ctrl/Cmd + mouse wheel), zoom.

A Gantt chart in a Marp slide

Export the chart as HTML next to the deck and put it in a slide with an iframe:

<iframe src="project-gantt.html" style="width:100%;height:85%;border:0"></iframe>

The iframe is raw HTML, so the deck needs HTML allowed (scimax.marp.enableHtml, or a presenter deck, which always allows it). In the slideshow and an HTML export the chart stays interactive, and a presenter export copies the page into the deck, so the single deck file still works on its own. PDF, PPTX and image exports of the deck show the chart as a still picture (this needs scimax.marp.allowLocalFiles, on by default in a trusted workspace). If HTML is not allowed, use the PNG or SVG export with an ordinary image link instead (![](project-gantt.svg)).

See also Marp Slides.

With Progress ticked, both exports hatch the done share of each bar, draw summary bars for parent tasks and groups, indent rows by outline level, and mark behind rows. The Excel sheet gains a % done column and a Status column (behind, done or on track); the PDF legend explains the hatch, the summary bar and the behind mark. Folded rows, Depth and Behind only are respected.

✅ Dependency graph

cmd:scimax.org.showTaskGraph opens an interactive graph (nodes = tasks, arrows = "depends on"), colored by status:

  • 🔵 ready · 🔴 blocked · 🟢 done · ⚪ unresolved id

It is seeded from the active file's tasks and expands over the dependency edges to show the connected component. Click a node to jump to that task.

People and assignments

A person is any heading tagged :person:, with contact properties:

* John Kitchin                              :person:
  :PROPERTIES:
  :ID: person-jrk
  :EMAIL: jkitchin@andrew.cmu.edu
  :NICK: jrk
  :ROLE: PI
  :END:
  • *Assign*: cmd:scimax.org.assignTask (Scimax: Assign Task to Person) lists the indexed :person: headings, fuzzy-matches on handle/name/role/email as you type, and sets the current task's :ASSIGNEE: property to the picked handle(s). Run it from anywhere inside the entry; pick more than one for a shared task. Existing assignees are pre-selected. Enter takes the ticked people and the highlighted one, so arrowing to a person and pressing Enter assigns them without ticking the box; with a filter typed and nobody highlighted, it takes the only person the filter leaves. Once you tick or untick a box, Enter takes exactly the ticked people, so clearing every box unassigns.

  • *Autocomplete*: while editing an :ASSIGNEE: value, completion suggests known people (name + email) and inserts their handle (:NICK:, or a slug of the name).

  • *Hover*: hovering an assignee handle shows the person's name, email, and role.

  • *Capture*: cmd:scimax.org.newPerson prompts for name/email/nick/role and appends a :person: heading to your people file (scimax.org.peopleFile, default {scimax.directory}/people.org).

Assignees feed the table's assignee column and grouping (:groupby assignee), the project view's assignee filter and grouping, and the agenda's @ filter.

✅ Configuration

SettingDefaultDescription
scimax.org.peopleFile(empty)Where "New Person" appends; empty ⇒ people.org
scimax.project.progressWeightingautoProgress rollup: auto, count or effort
scimax.project.defaultEffort1dEffort assumed for a task without EFFORT when weighting
scimax.project.behindTolerance10Points below the expected percentage before a task is behind

Task-dependency settings (blocking, promotion, indicators) are documented in Task Dependencies.

✅ Notes and limitations

  • Without :scope, the task table is computed from a single file (or a subtree via :id). Use :scope project to cover the whole project.

  • "Blocked" and the chart's ordering resolve dependencies within the scope: a dependency on a task outside the project is not counted. The dependency graph and completion blocking (Task Dependencies) still see every indexed file.

  • A project is read from disk each time the view or block refreshes. Very large trees are capped at 2,000 org files, with a warning.

  • The Mermaid #+BEGIN: gantt block and its Insert Gantt Chart command were removed in favour of the project view. Updating an old gantt block reports "Unknown dynamic block type"; delete it and use the project view instead.