Skip to content

Configuration

taskmd supports .taskmd.yaml configuration files for setting default options.

Config File

Create a .taskmd.yaml file in your project root or home directory:

yaml
# .taskmd.yaml

# Default directory to search for task files
dir: ./tasks

# Web server configuration
web:
  # Default port for the web dashboard
  port: 8080

  # Automatically open browser when starting the web server
  auto_open_browser: false

Config File Locations

Config files are loaded in this order (highest precedence first):

  1. Project-level: ./.taskmd.yaml - project-specific settings
  2. Global: ~/.taskmd.yaml - user-wide defaults
  3. Custom: --config path/to/config.yaml - explicit path
  4. Built-in defaults - fallback values

Command-line flags always override config file values.

Supported Options

OptionTypeDefaultDescription
dirstring.Default task directory
ignorestring[][]Additional directories to skip when scanning (beyond the built-in skip list)
worklogsbooleanfalseAllow writing worklog entries; set to true to opt in
workflowstring"solo"Workflow mode: "solo" or "pr-review"
worktree_scopestring"unified"unified merges task state across git worktrees; isolated keeps each worktree to its own files (details)
todos.excludestring[][]Glob patterns to exclude from TODO/FIXME scanning
web.portinteger8080Web server port
web.auto_open_browserbooleanfalseAuto-open browser on web start
web.readonlybooleanfalseStart web server in read-only mode (disables editing)
id.strategystring"sequential"ID generation strategy (details)
id.prefixstring""Prefix for prefixed strategy
id.lengthinteger6Length of generated IDs (used by random and ulid strategies)
id.paddinginteger3Zero-padding width for sequential strategy
effortstring[][small, medium, large]Ordered effort vocabulary, lowest to highest (details)
scopesmapScope-to-path mappings for the touches field (details)
phasesarray[]Phase definitions with metadata (details)
projectsarray[]Registered projects for multi-project workflows (details) (global config only)
default_projectstring""Default project ID to use when no --project flag is specified (global config only)

ignore — The scanner already skips common directories (node_modules, vendor, dist, build, .next, .nuxt, out, target, __pycache__, and hidden directories). Use ignore to add project-specific directories:

yaml
ignore:
  - "tmp"
  - "cache"
  - "legacy"

worklogs — Worklogs are opt-in; an absent key means disabled. Until you set worklogs: true, taskmd worklog <id> --add refuses to write and explains why, and agents skip worklog steps. Only writing is gated — existing worklogs can always be read regardless of this setting, and taskmd rm still deletes a removed task's worklog.

workflow — Controls the development workflow mode:

  • solo (default) — optimized for single-developer workflows
  • pr-review — optimized for PR-based collaborative workflows

todos.exclude — Glob patterns to exclude files from taskmd todos scanning. These are additive with CLI --exclude flags:

yaml
todos:
  exclude:
    - "parser_test.go"
    - "**/*_test.go"

TIP

Only project-level settings are supported in config files. Per-invocation preferences like format, verbose, and quiet are intentionally CLI-only.

ID Strategy Configuration

The id section controls how task IDs are generated by the add and next-id commands. Four strategies are available:

StrategyFormatExample IDDescription
sequentialZero-padded number001, 042Default. Finds the highest existing ID and increments.
prefixedPrefix + numberdr-001, jk-042Like sequential, but with a user-defined prefix. Useful for multi-contributor projects.
randomRandom alphanumerica3f9x2Short random string. Avoids ID collisions across branches.
ulidULID01HGW3...Universally Unique Lexicographically Sortable Identifier. Guarantees uniqueness with natural sort order.
yaml
# .taskmd.yaml

# Default: sequential IDs
id:
  strategy: sequential
  padding: 3            # 001, 002, ... 999

# Prefixed IDs (useful for teams)
id:
  strategy: prefixed
  prefix: "dr"          # dr-001, dr-002, ...

# Random IDs (branch-safe)
id:
  strategy: random

# ULID IDs (sortable + unique)
id:
  strategy: ulid

Avoiding ID Collisions

When multiple contributors create tasks on separate branches, sequential IDs can collide after merge. Use prefixed (with unique per-contributor prefixes), random, or ulid to avoid this. If collisions do occur, use taskmd deduplicate to resolve them.

Scopes Configuration

The scopes key defines concrete mappings for the abstract scope identifiers used by the touches frontmatter field. The tracks command uses touches to detect spatial overlap between tasks and assign them to parallel work tracks — tasks sharing a scope are placed in separate tracks to avoid merge conflicts.

yaml
# .taskmd.yaml
scopes:
  cli/graph:
    description: "Graph visualization and dependency rendering"
    paths:
      - "apps/cli/internal/graph/"
      - "apps/cli/internal/cli/graph.go"
  cli/output:
    paths:
      - "apps/cli/internal/cli/format.go"

Each scope entry has the following fields:

FieldRequiredDescription
descriptionNoHuman-readable explanation of what the scope covers. Included in validation error messages.
pathsNoList of file or directory paths that the scope maps to.

Behavior:

  • When scopes are configured, any touches value in a task that does not match a configured scope produces a warning.
  • When no scopes config exists, all touches values are accepted silently.

Worktree Scope Configuration

The worktree_scope key controls what taskmd reads in a git repository with multiple worktrees:

  • unified (default) — taskmd merges task state across all worktrees so each checkout sees one coherent view. The merge activates by itself only when sibling worktrees actually exist, so single-worktree repos and non-git directories are entirely unaffected.
  • isolated — each worktree sees only its own task files. For worktrees that keep intentionally independent task states.
yaml
# .taskmd.yaml
worktree_scope: isolated

When the overlay is active:

  • Read commands (list, next, board, stats, get, graph, …) show each task's effective status — the most advanced status across all worktree copies — with provenance for the worktree that owns it.
  • taskmd next never recommends a task that is in-progress (or further along) in a sibling worktree, so marking a task in-progress in one worktree claims it for the whole repository.
  • Mutations (set, add, rm, archive) always write to the current worktree's files; taskmd set fails with a guard error when the target task exists only in a sibling worktree.
  • All worktrees of one repository resolve to a single registered project — no duplicate entries or double-counting in --all-projects.

Across projects. --all-projects reads merge each repository's worktrees too, so a task claimed in a sibling worktree shows the same effective status whether you ask from inside that repo or from a cross-project view. Each project's scope comes from its own .taskmd.yaml, so one repository can set worktree_scope: isolated while the others keep merging.

Override per invocation with the global --worktree-scope flag or the TASKMD_WORKTREE_SCOPE environment variable — unlike the config key, an explicit override applies to every project in the run. See the CLI guide for the full behavior reference.

Usage Examples

Project Setup

bash
# Create project config
cat > .taskmd.yaml <<EOF
dir: ./tasks
web:
  port: 3000
  auto_open_browser: true
EOF

# Now these commands use config defaults
taskmd list              # Uses ./tasks directory
taskmd web start         # Uses port 3000 and opens browser

# CLI flags still override config
taskmd list --dir ./other-tasks
taskmd web start --port 8080

Global Defaults

Create ~/.taskmd.yaml for defaults that apply to all projects:

yaml
web:
  port: 3000
  auto_open_browser: true

Environment Variables

taskmd supports environment variables with the TASKMD_ prefix:

bash
export TASKMD_DIR=./tasks
export TASKMD_VERBOSE=true

Precedence (highest to lowest):

  1. Command-line flags
  2. Project-level .taskmd.yaml
  3. Global ~/.taskmd.yaml
  4. Environment variables
  5. Built-in defaults

Sync Configuration

The sync command reads its configuration from the sync section of .taskmd.yaml. Each source defines where to fetch tasks from, how to map fields, and where to write files.

GitHub source:

yaml
# .taskmd.yaml
dir: ./tasks

sync:
  sources:
    - name: github
      project: "owner/repo"
      token_env: GITHUB_TOKEN       # Environment variable holding the API token
      output_dir: ./tasks/synced     # Where to write synced task files
      field_map:
        status:
          open: pending
          closed: completed
        priority:
          urgent: critical
          high: high
          medium: medium
          low: low
        labels_to_tags: true         # Convert issue labels to task tags
        assignee_to_owner: true      # Map assignee to owner field
      filters:
        state: open                  # Only sync open issues

Jira source:

yaml
# .taskmd.yaml
dir: ./tasks

sync:
  sources:
    - name: jira
      project: "PROJ"                        # Jira project key
      base_url: https://myteam.atlassian.net  # Jira Cloud instance URL (required)
      token_env: JIRA_API_TOKEN               # Jira API token
      user_env: JIRA_USER_EMAIL               # Jira account email (for Basic auth)
      output_dir: ./tasks/jira
      field_map:
        status:
          To Do: pending
          In Progress: in-progress
          Done: completed
        priority:
          Highest: critical
          High: high
          Medium: medium
          Low: low
          Lowest: low
        labels_to_tags: true
        assignee_to_owner: true
      filters:
        jql: 'status != "Done"'              # Additional JQL (ANDed with project)

Jira Authentication

Jira Cloud uses Basic authentication with your account email and an API token. Both token_env and user_env are required. Generate an API token at id.atlassian.net/manage-profile/security/api-tokens.

Jira Descriptions

Jira Cloud API v3 returns descriptions in Atlassian Document Format (ADF). taskmd automatically converts ADF to Markdown, supporting paragraphs, headings, lists, code blocks, blockquotes, and inline formatting.

Source fields:

FieldRequiredDescription
nameYesUnique name for this source
projectNoProject identifier (e.g., owner/repo for GitHub)
base_urlNoCustom API base URL
token_envNoEnvironment variable name for API token
user_envNoEnvironment variable name for username
output_dirYesDirectory where synced task files are written
field_mapNoHow to map external fields to taskmd frontmatter
filtersNoSource-specific filters (e.g., state: open)

Field mapping (field_map):

Sub-fieldTypeDescription
statusmap[string]stringMap external status values to taskmd statuses
prioritymap[string]stringMap external priority values to taskmd priorities
labels_to_tagsboolConvert external labels/categories to task tags
assignee_to_ownerboolMap external assignee to the owner field

Phases Configuration

The phases key defines the phases available for your project. Tasks reference phases via the phase frontmatter field.

yaml
# .taskmd.yaml
phases:
  - id: v0.2
    name: "v0.2 – Core CLI"
    description: "Core CLI features"
    due: 2026-04-01
  - id: v0.3
    name: "v0.3 – Web Dashboard"
    description: "Web dashboard"
    due: 2026-06-01

Each phase entry has the following fields:

FieldRequiredDescription
idYesUnique phase identifier (must match the task's phase field)
nameYesHuman-readable display name for the phase
descriptionNoDescription of the phase's scope
dueNoTarget date in YYYY-MM-DD format

Behavior:

  • When phases are configured, any phase value in a task that does not match a configured phase name produces a warning.
  • When no phases config exists, all phase values are accepted silently.

Effort Configuration

The effort key defines the values the effort frontmatter field may take. It replaces the built-in small, medium, large entirely — it is not additive.

yaml
# .taskmd.yaml
effort: [xs, s, m, l, xl]

Values are listed lowest to highest, and the order is significant:

BehaviorHow the order is used
Comparison filters--filter "effort>=m" ranks values by position
board --group-by effortColumn order follows the configured order
list --sort effortSorts lowest first; unset values sort last
next scoringPoints scale with position — the lowest value earns the most, the highest earns none
next --quick-winsSelects tasks at the lowest configured value

Behavior:

  • When no effort config exists, the default small, medium, large applies and nothing changes. A bare effort: with no value is treated the same way.
  • When configured, taskmd validate reports any task using a value outside the list, and add/set reject one.
  • The config itself is rejected when it is not a list, is empty, contains a blank entry, contains duplicates, or contains a non-string item.
  • Items are effort values as strings. Object items are reserved for future per-value metadata.

Changing an existing project

The configured vocabulary replaces the default, so existing task files using small/medium/large become invalid. Update them in the same change, or keep the old values in the list.

Projects Configuration

The projects key in the global config (~/.taskmd.yaml) registers projects for multi-project workflows. Use taskmd projects register to add entries, or edit the config directly.

yaml
# ~/.taskmd.yaml
projects:
  - id: frontend
    name: "Frontend App"
    path: /Users/me/projects/frontend
  - id: backend
    name: "Backend API"
    path: /Users/me/projects/backend

# Optional: set a default project so --project can be omitted
default_project: frontend

Each project entry has the following fields:

FieldRequiredDescription
idYesUnique project identifier (auto-generated from directory basename if omitted during registration)
nameNoHuman-readable display name (defaults to the same value as id)
pathYesAbsolute path to the project directory (must contain a .taskmd.yaml file)

Usage:

bash
# List all registered projects
taskmd projects

# Run commands against a specific project
taskmd list --project backend
taskmd next --project frontend

# Aggregate tasks from all projects
taskmd stats --all-projects
taskmd list --all-projects

When default_project is set, commands automatically scope to that project unless --project or --all-projects is explicitly provided.

Shell Aliases

For quick access, add aliases to your shell config:

bash
# ~/.bashrc or ~/.zshrc
alias tm='taskmd --dir ./tasks'
alias tmw='taskmd web start --port 8080 --open'
alias tnext='taskmd next --limit 3'
alias thigh='taskmd list --filter priority=high --filter status=pending'

Released under the MIT License. v0.5.0