{
	"$schema": "https://json-schema.org/draft/2020-12/schema",
	"$id": "https://cdn.jsdelivr.net/npm/@nakido-official/pi-footer/config.schema.json",
	"title": "pi-footer configuration",
	"description": "Configuration for the pi-footer extension. Read from <agent-dir>/extension-settings/pi-footer.json; project-local configuration is deliberately ignored. `layout` is presentation, `widgets` is per-widget behavior. Unknown keys, unknown placeholders, unknown colors, and wrong types are reported as warnings and make the whole config fall back to the bundled defaults. This file is an editor aid only: the runtime reads and validates `config.default.json`, and the package README is the reference for the template grammar and the item list.",
	"type": "object",
	"additionalProperties": false,
	"properties": {
		"$schema": {
			"type": "string",
			"description": "Optional editor hint; ignored by the extension."
		},
		"layout": {
			"type": "object",
			"description": "Presentation of the footer: the lines in display order and the separator template they substitute. A missing key keeps its value from the bundled default.",
			"additionalProperties": false,
			"properties": {
				"lines": {
					"type": "array",
					"description": "The footer lines, top to bottom. Each entry renders one line with a left-aligned and a right-aligned template, and either side may be omitted, which is the empty string. A line whose items all render empty is dropped; the bundled first line also carries `MCP:{mcp}`, which is always a number, so it is always present. The list is complete: removing an entry removes that line, and an empty array renders no footer. The bundled layout is a status/MCP line, then the main line.",
					"items": {
						"type": "object",
						"description": "One rendered line. Both sides share the line and the right side is right-aligned; both keys are optional.",
						"additionalProperties": false,
						"properties": {
							"left": {
								"type": "string",
								"description": "Left-aligned template of this line; omit it (or write an empty string) for a right-only line. `{item}` inserts an item, `{separator}` the layout.separator template, `{color name}` … `{endcolor}` paints a run, `{if items}` … `{endif}` conditions one (holds while at least one listed item has content, nesting adds `and`), `{{`/`}}` are literal braces, and everything else is literal text. Neither placeholders nor tags take a color — `{color …}` is the only way to paint, so `{git:dim}` is an error — and there is no default color, so text outside a block takes the terminal's own foreground. An item with nothing to show renders the empty string rather than a placeholder, and `mcp` always renders a number. See the package README for the item list and the full grammar."
							},
							"right": {
								"type": "string",
								"description": "Right-aligned template of this line; omit it (or write an empty string) for a left-only line. Same syntax, items, colors and conditions as left. The right side has priority when the terminal is narrow."
							}
						}
					}
				},
				"separator": {
					"type": "string",
					"default": "{color dim}•{endcolor}",
					"description": "Substituted textually wherever a template says {separator}, so one key re-punctuates the whole layout. It is a template of its own: the bundled value is \"{color dim}•{endcolor}\", so the separator names its own color once instead of at every use, and a plain \"•\" simply inherits the {color …} block around the placeholder. Substitution happens before parsing, so the tags it brings are parsed where the placeholder sat, and it may not reference {separator} itself. Nothing is inserted automatically and there is no grouping: a separator written outside an {if …} always renders, and whitespace runs in the rendered line are normalized to a single space, so the spaces written here and the spaces around the placeholder do not add up — put them in one place. Set it to \"\" to render nothing."
				}
			}
		},
		"widgets": {
			"type": "object",
			"description": "Per-widget behavior. Everything about how the footer looks stays in `layout`; this block configures what an item does. The section is optional in a user config: an omitted widget or field keeps its value from the bundled default.",
			"additionalProperties": false,
			"properties": {
				"context": {
					"type": "object",
					"description": "Behavior of the three context items (context-bar, context-percent, context-window), which share one gauge.",
					"additionalProperties": false,
					"properties": {
						"adaptive": {
							"type": "object",
							"description": "Adaptive color for the context items. While enabled, the color the layout named is the calm level — `{color accent}` around the bar keeps it accent until warnAt — and the gauge switches to warnColor and then errorColor as usage rises. While disabled, each item renders in the color the layout gave it.",
							"additionalProperties": false,
							"properties": {
								"enabled": {
									"type": "boolean",
									"default": true,
									"description": "Group switch. false turns adaptive coloring off for all three context items, whatever items says; their placeholder colors then render."
								},
								"items": {
									"type": "object",
									"description": "Per-item overrides, honored while enabled is true. An omitted item keeps its value from the bundled default.",
									"additionalProperties": false,
									"properties": {
										"context-bar": {
											"type": "boolean",
											"default": true,
											"description": "Recolor the bar. When false, the bar always renders in the color the layout gave it."
										},
										"context-percent": {
											"type": "boolean",
											"default": true,
											"description": "Recolor the percentage. When false, it always renders in the color the layout gave it."
										},
										"context-window": {
											"type": "boolean",
											"default": true,
											"description": "Recolor the context window size. When false, it always renders in the color the layout gave it."
										}
									}
								},
								"warnAt": {
									"type": "number",
									"minimum": 0,
									"maximum": 100,
									"default": 70,
									"description": "Context usage percentage at which warnColor takes over. Absolute percentage of the context window, not a fraction of the compaction trigger. Must be less than errorAt. The bundled 70/90 bands turn a 128k window amber from 70 %, while the compaction trigger sits at 87.2 %."
								},
								"errorAt": {
									"type": "number",
									"minimum": 0,
									"maximum": 100,
									"default": 90,
									"description": "Context usage percentage at which errorColor takes over. Must be greater than warnAt. pi compacts at (window - reserveTokens) / window — 87.2 % for a 128k window — so set this below the trigger of the windows you use if the error color should be visible before compaction."
								},
								"warnColor": {
									"type": "string",
									"default": "warning",
									"description": "Theme color for the warning band. The layout's color remains the calm band."
								},
								"errorColor": {
									"type": "string",
									"default": "error",
									"description": "Theme color for the error band."
								}
							}
						}
					}
				},
				"cwd": {
					"type": "object",
					"description": "How the cwd item writes a path out. Home always becomes \"~\"; the only choice is what happens to the directories in between.",
					"additionalProperties": false,
					"properties": {
						"abbreviate": {
							"type": "boolean",
							"default": true,
							"description": "true shortens every directory but the last to its leading character, keeping the dot of hidden ones: ~/.pi/agent/source/pi-footer becomes ~/.p/a/s/pi-footer. false spells the path out in full but still writes ~ for home: ~/.pi/agent/source/pi-footer. A path outside home is never collapsed into an ellipsis beyond this rule."
						}
					}
				},
				"git": {
					"type": "object",
					"description": "Behavior of the git item: how often the working tree is re-checked, what text a dirty tree gets, and how clean and dirty trees are colored. The layout's color for git renders only while adaptive.enabled is false.",
					"additionalProperties": false,
					"properties": {
						"pollIntervalMs": {
							"type": "number",
							"default": 5000,
							"description": "How often to re-check the git working tree in the background, in milliseconds. The check also runs on events (tool end, turn end, branch change) regardless of this value. 0 disables the periodic part only.",
							"anyOf": [
								{
									"const": 0
								},
								{
									"minimum": 250
								}
							]
						},
						"dirtySuffix": {
							"type": "string",
							"default": " *",
							"description": "Appended to the branch name verbatim while the working tree has changes. The bundled value is a space and an asterisk, so a clean `main` renders as `main` and a dirty one as `main *`. The leading space is part of the value, not added by the renderer: `\"*\"` renders `main*`, and an empty string hides the marker and leaves only the adaptive color."
						},
						"adaptive": {
							"type": "object",
							"description": "Adaptive color for the git item: cleanColor while the working tree is clean, dirtyColor while it has changes (branch name and dirtySuffix together).",
							"additionalProperties": false,
							"properties": {
								"enabled": {
									"type": "boolean",
									"default": true,
									"description": "Turn adaptive git coloring on or off. When false, git renders in the color the layout gave it."
								},
								"cleanColor": {
									"type": "string",
									"default": "success",
									"description": "Theme color for a clean working tree."
								},
								"dirtyColor": {
									"type": "string",
									"default": "warning",
									"description": "Theme color for a working tree with changes, applied to the branch name and the dirty suffix."
								}
							}
						}
					}
				},
				"mcp": {
					"type": "object",
					"description": "Behavior of the mcp item, which always renders the number of connected MCP servers.",
					"additionalProperties": false,
					"properties": {
						"pollIntervalMs": {
							"type": "number",
							"default": 5000,
							"description": "How often to re-read the tool registry to see which MCP servers connected, in milliseconds. pi emits no MCP connection event, so a timer is the only way to notice a server that connects after startup. Tool-end and turn-end also trigger a read. 0 disables the periodic part only.",
							"anyOf": [
								{
									"const": 0
								},
								{
									"minimum": 250
								}
							]
						}
					}
				}
			}
		}
	}
}