Planner /Docs

HTTP API

Config

Read and change Planner's settings, and try a change out before saving it. The command line does the same from a terminal; this is for scripts and agents that prefer HTTP.

GET/api/config

The settings saved in the config file, which flags this run was started with, and where the file is.

curl -s http://localhost:4173/api/config

Response

type ConfigResponse = {
  // The whole saved config, defaults filled in. See Configuration for every key.
  config: Config
  // --root / --port given to this run; they override `config` but are never saved.
  overrides: { folders?: DocsFolder[]; port?: number }
  // The config file, ~ for the home folder.
  file: string
}

Example

Trimmed:

{
  "config": {
    "folders": [{ "name": "plans", "path": "~/plans" }],
    "port": 4173,
    "statusFolders": { "active": "active", "done": "done" },
    "plansFolder": "plans",
    "phasePattern": "^phase-(?<num>\\d+[a-z]*)-(?<slug>.+)$",
    "fileTypes": ["html", "md"]
  },
  "overrides": {},
  "file": "~/.config/planner/config.json"
}

PUT/api/config

Checks a config and, if it is valid, saves it to the config file. Planner then rescans and every open tab updates.

The body is the whole config, not just the keys you change: read it with GET /api/config, change it, and send it back. Every key is described in Configuration and in the JSON schema.

curl -s http://localhost:4173/api/config |
  jq '.config | .folders += [{"name": "side", "path": "~/code/side/plans", "statusFolders": null, "plansFolder": ""}]' |
  curl -s -X PUT http://localhost:4173/api/config -H 'Content-Type: application/json' -d @-

Response

{ "ok": true }

Errors

StatusWhen
400The config is invalid, has no folders, or a folder does not exist
403Sent by a web page on another site

error lists every problem, one per line, each starting with the key it is about:

{ "error": "phasePattern: needs a (?<num>...) group\nfolders.1.path: ~/code/side/plans does not exist" }

POST/api/config/preview

What a config would find in each folder, without saving it: the same check as the settings page's preview and planner config check. Use it to try a layout until it matches the folders, then PUT it.

The body is a whole config, as for PUT /api/config.

curl -s http://localhost:4173/api/config | jq '.config' |
  curl -s -X POST http://localhost:4173/api/config/preview -H 'Content-Type: application/json' -d @-

Response

// The settings page's dry run: how a draft config reads its folders.
export type Preview = { ok: boolean; error?: string; folders: FolderPreview[] }
// What one folder's layout finds, for the settings page and `config check`.
export type FolderPreview = {
  name: string
  label: string
  problem?: string
  tasks: number
  phases: number
  docs: number
  byKind: Record<string, number>
  // Phase folders whose names the phase pattern does not match.
  unnumbered: string[]
  // Extensions found next to plans but not listed in fileTypes, with counts.
  skipped: Record<string, number>
}

An invalid config is not an error here: it replies 200 with ok: false, the problems in error, and no folders.

Example

{
  "ok": true,
  "folders": [
    {
      "name": "plans",
      "label": "~/plans",
      "tasks": 4,
      "phases": 9,
      "docs": 18,
      "byKind": { "plan": 6, "md": 4, "eli5": 2, "recap": 3, "overview": 2, "doc": 1 },
      "unnumbered": [],
      "skipped": {}
    }
  ]
}

A folder with 0 tasks almost always needs a different statusFolders or plansFolder; see Troubleshooting.