Skip to main content
agentic-to-do is a self-contained Agent Application package that demonstrates every part of the v1 contract in one place: an APP.md manifest, a JSON-first CLI, application-owned state, a local skill for agents, and automated tests. Source: davetist/agentapplications

What it demonstrates

agentic-to-do shows how to build an Agent Application that an agent can inspect and operate safely without relying on prompt memory:
  • APP.md as the contract — the manifest defines the CLI entry command, every command signature, output shape, state location, scheduling support, and confirmation requirements.
  • JSON-first CLI — every command writes structured JSON to stdout. Errors also return JSON with a non-zero exit code, so agents can parse success and failure the same way.
  • Application-owned state — to-do items are stored in app/state/todos.json. The application manages reads and writes; agents interact only through the CLI.
  • Stable IDs — items get IDs like td_0001, td_0002 that persist across runs and are safe to reference in subsequent commands.
  • Local skillskills/agentic-to-do-usage/SKILL.md gives agents concise operating guidance without embedding it in the manifest.
  • Scheduling support — items accept an optional --due-at ISO date, surfaced in both add and update.
  • Confirmation guardremove requires --confirm so agents cannot delete items accidentally.

Package structure

agentic-to-do/
├── APP.md
├── app/
│   ├── cli.js
│   └── state/
│       └── todos.json
└── skills/
    └── agentic-to-do-usage/
        └── SKILL.md
PathRole
APP.mdManifest and CLI contract
app/cli.jsJSON-first CLI entrypoint
app/state/todos.jsonApplication-owned persistent state
skills/agentic-to-do-usage/SKILL.mdLocal skill for agent operating guidance

The APP.md frontmatter

The manifest opens with a YAML frontmatter block that a runtime reads at catalog time:
schema: agentapplications/v1
kind: app
slug: agentic-to-do
name: Agentic To-Do
description: Self-contained persistent to-do list operated through a JSON-first CLI
version: 0.1.0
entry:
  command: node app/cli.js
commands:
  - add
  - list
  - get
  - update
  - complete
  - remove
skills:
  - agentic-to-do-usage
scheduling: supported
confirmationRequired:
  - remove

CLI commands

Run any command from the package root with:
node app/cli.js <command> [...args]

add

node app/cli.js add <title> [--description <text>] [--due-at <iso-date>]
Creates an open to-do item. title is required. --description and --due-at are optional.

list

node app/cli.js list [--status all|open|completed]
Lists items filtered by status. Defaults to all when --status is omitted.

get

node app/cli.js get <id>
Fetches a single to-do item by its stable ID.

update

node app/cli.js update <id> [--title <text>] [--description <text>] [--due-at <iso-date>] [--clear-due-at]
Updates one or more mutable fields on an existing item. Pass --clear-due-at to remove a previously set due date.

complete

node app/cli.js complete <id>
Marks an item as completed. If the item is already completed, the command returns the item unchanged.

remove

node app/cli.js remove <id> --confirm
Deletes an item permanently. The --confirm flag is required because the operation is destructive.

JSON output

Every command writes JSON to stdout. You parse the same structure whether the command succeeded or failed.

Success

{
  "ok": true,
  "command": "list",
  "count": 1,
  "items": [
    {
      "id": "td_0001",
      "title": "Write docs",
      "description": "",
      "status": "open",
      "dueAt": "2026-04-05",
      "createdAt": "2026-04-01T00:00:00.000Z",
      "updatedAt": "2026-04-01T00:00:00.000Z",
      "completedAt": null
    }
  ]
}

Failure

When a command fails, the CLI writes a structured error payload and exits with a non-zero code:
{
  "ok": false,
  "error": {
    "code": "CONFIRMATION_REQUIRED",
    "message": "remove requires --confirm."
  }
}
Always check the ok field first. A non-zero exit code means ok is false and the error object contains a machine-readable code and a human-readable message.

State model

The application stores all to-do items in app/state/todos.json. The file is created automatically on the first command if it does not exist. IDs are stable and increment as td_0001, td_0002, and so on. Once assigned, an ID never changes. Each item has the following fields:
FieldTypeDescription
idstringStable identifier, e.g. td_0001
titlestringRequired non-empty string
descriptionstringOptional text, defaults to ""
status"open" or "completed"Current state of the item
dueAtstring or nullISO-8601 date or datetime, or null
createdAtstringISO-8601 timestamp set at creation
updatedAtstringISO-8601 timestamp updated on every write
completedAtstring or nullISO-8601 timestamp set by complete, otherwise null

Scheduling support

The manifest declares scheduling: supported. In practice, this means add and update both accept a --due-at flag that takes an ISO-8601 date or datetime string.
node app/cli.js add "Write tests" --due-at 2026-04-05
node app/cli.js update td_0001 --due-at 2026-04-10
node app/cli.js update td_0001 --clear-due-at

Confirmation rule

The manifest declares confirmationRequired: [remove]. The CLI enforces this by requiring --confirm on every remove call. Omitting the flag causes the command to fail with a CONFIRMATION_REQUIRED error rather than silently deleting data.

Isolated runs and testing

You can point the CLI at a different state file by setting the AGENTIC_TODO_STATE_FILE environment variable:
AGENTIC_TODO_STATE_FILE=/tmp/todos.json node app/cli.js add "Isolated item"
This is useful for tests and for running commands without touching the package’s default state.

Running the example

1

Install dependencies

npm install
2

Run CLI commands

node app/cli.js add "Write APP.md"
node app/cli.js list --status open
node app/cli.js complete td_0001
node app/cli.js remove td_0001 --confirm
3

Run the test suite

npm test