Skip to content

S2: Implementation Guidance

Version 1.0.0

This specification provides guidance for implementations that read, write, and present S1-compliant data. It covers field conventions, timestamp management, file safety, and common semantics.

Unlike S1 (which defines compatibility requirements), this document contains recommendations and best practices. Implementations that follow this guidance will behave more consistently and predictably, but deviation is acceptable where it serves user needs.

The key words “SHOULD”, “SHOULD NOT”, “RECOMMENDED”, “MAY”, and “OPTIONAL” in this document are to be interpreted as described in RFC 2119.


While S1 defines the file format and compatibility requirements, this specification addresses operational concerns: how to read files gracefully, how to write them safely, and how to present data consistently.

S1 defines what files look like and what implementations must do for compatibility. This specification provides guidance on how implementations should behave for a good user experience.


  1. Predictable over clever. Users should be able to predict what an implementation will do. Avoid magic or implicit behaviors that might surprise.

  2. Preserve user data. Never discard data you don’t understand. Unknown fields, custom metadata, and document bodies must survive round-trips.


Field names use kebab-case as defined in S1:

  • created-at, updated-at, completed-at
  • defer-until
  • blocked-by

Implementations MAY use alternative display names in user interfaces (e.g., “Created” instead of “created-at”), but programmatic interfaces and file output SHOULD use canonical names.

S1 defines projects as an array (for compatibility with systems that support multiple projects per task), but taskdn enforces single-project semantics. Implementations SHOULD:

  • Display as project (singular) in output
  • Accept project in input
  • Read projects[0] from files
  • Write projects: ["[[value]]"] to files

If a file contains multiple projects, use the first one. Validation commands SHOULD warn about multi-project files.


Dates SHOULD use ISO 8601 format when stored or output:

Field TypeFormatExample
Date fields (due, scheduled, defer-until)YYYY-MM-DD2025-12-20
Timestamp fields (created-at, updated-at, completed-at)YYYY-MM-DDTHH:MM:SS2025-12-15T14:30:00

Implementations SHOULD accept ISO 8601 format for input.

Implementations MAY accept natural language for human convenience (e.g., today, tomorrow, +3d). Ambiguous formats like 12/1 or 1/12 SHOULD be rejected.


When reading files, implementations SHOULD handle malformed data gracefully:

  • If a file cannot be parsed as valid YAML, skip the file and MAY emit a warning.
  • If a required field is missing, treat the file as invalid and MAY emit a warning.
  • If a status value is not recognized, preserve it (per S1) and MAY display it distinctively.

Implementations SHOULD NOT crash or halt entirely when encountering individual malformed files. Partial results (valid files only) are preferable to complete failure.

Implementations SHOULD ignore unknown frontmatter fields during processing. This allows users to add custom metadata without breaking compatibility. S1 requires that unknown fields be preserved when writing.


Implementations SHOULD automatically manage timestamp fields:

EventFieldAction
Task createdcreated-atSet to current datetime
Task modifiedupdated-atSet to current datetime
Status changed to done or droppedcompleted-atSet to current datetime
Status changed from done or droppedcompleted-atRemove or unset field

“Modified” includes any frontmatter change or body edit. Timestamps SHOULD use ISO 8601 format as specified in S1.

  • Implementations SHOULD NOT modify files that fail validation without explicit user consent.
  • After a write operation, the resulting file SHOULD be valid per S1.
  • If an operation would produce an invalid file (e.g., removing a required field), implementations SHOULD reject the operation or warn the user.

To prevent file corruption from crashes or interrupts, implementations SHOULD use atomic write patterns.

This specification does not define file locking, as taskdn is designed for single-user scenarios. In general, the files on disk should be considered the source of truth.

For long-running processes (TUI interfaces, desktop applications):

  • Implementations SHOULD watch for external file changes and reload affected data
  • Implementations SHOULD persist changes to disk quickly to avoid conflicts with external modifications
  • If a conflict arises, implementations SHOULD warn the user or require intervention
  • Files SHOULD NOT include a byte order mark (BOM)
  • Line endings SHOULD be LF (\n); implementations SHOULD tolerate CRLF on read
  • Files SHOULD end with a single newline character

By default, queries should return “active” items. The definition of “active” varies by entity type:

Active tasks:

  • Status NOT IN (done, dropped, icebox)
  • defer-until is unset or ≤ today
  • File is in the tasks directory (not a subdirectory)

Active projects:

  • Status is unset OR status NOT IN (done)

Active areas:

  • Status is unset OR status = active

Items excluded by default should be includable via explicit parameters or options.


For implementations that support querying and filtering:

When multiple filters are applied:

  • Same filter with multiple values: OR logic

    • Example: status=ready,in-progress matches ready OR in-progress
  • Different filter types: AND logic

    • Example: project=Q1 AND status=ready requires both conditions
  • Contradictory filters: Empty result (not an error)

    • Example: due=today AND overdue=true returns empty if logically impossible

  • Partial results: When reading multiple files, skip malformed files and return valid results. Emit warnings for skipped files.
  • Batch operations: Process all items; don’t stop at first error. Report successes and failures separately.

For programmatic interfaces (CLIs, SDKs, APIs), implementations SHOULD use consistent error codes. See Appendix A for a suggested catalog.


For implementations that output to AI agents or LLM-based tools: agents receive output in their context window and pay per token. Output should be token-efficient, gracefully degradable (truncated output should still be useful), and readable without programatic parsing. Structured Markdown is often preferable to JSON for agent-facing output. Include file paths in output so agents can perform follow-up operations.

The specific output format is implementation-defined.


The following error codes are suggested for programmatic interfaces (CLIs, SDKs, APIs). Graphical interfaces may present errors differently (dialogs, inline messages) but this catalog remains useful for logging and debugging.

CodeWhenContextual Info
NOT_FOUNDEntity doesn’t existSuggestions for similar items
AMBIGUOUSFuzzy search matched multipleList of matches
INVALID_STATUSBad status valueList of valid statuses
INVALID_DATEUnparseable dateExpected formats
INVALID_PATHPath outside configured dirsConfigured paths
PARSE_ERRORYAML malformedLine number, specific issue
MISSING_FIELDRequired field absentWhich field
REFERENCE_ERRORBroken project/area referenceThe broken reference
PERMISSION_ERRORCan’t read/write fileFile path
CONFIG_ERRORConfig missing/invalidHow to fix