Console widgets

Widgets are the interactive views the web console (apps/console) shows for repo files with a known file suffix, such as .todos.md or .bookmarks.json. Each widget is a Preact component in packages/ui/src/LifeOS/Organisms/Widgets/, and each change it makes is committed to your GitHub repo at once. Files are placed as tiles on a dashboard through .kh/.dashboard.config.json; the shared parsers for most formats live in packages/formats.

Which file types get a widget

Dashboard.tsx and MainApp.tsx pick a widget by the end of the file name. Any of these may also end in .enc (encrypted).

SuffixWidget
.todos.mdTodo list (TodoWidget)
.actionlog.mdAction log (ActionLogWidget)
.prompts.mdPrompt library (PromptsWidget)
.commands.mdCommand library (CommandsWidget)
.bookmarks.jsonBookmarks (BookmarksWidget)
.readitlater.jsonRead it later (ReadItLaterWidget)
command-palette.settings.jsonCommand palette settings (CommandPaletteSettingsWidget)
.board-overview.jsonBoard overview (BoardOverviewWidget)
.habit.csvHabit tracker (HabitTrackerWidget)
.events.csvEvents (EventsWidget)
.timetracking.csvTime tracking (TimeTrackingWidget)
.budget.csvBudget (BudgetWidget)
.data-collection.csvData collection (DataCollectionWidget)
.consumption.csvConsumption (ConsumptionWidget)
.stocks.csvStocks (StocksWidget)
.timezones.jsonTimezones (TimezoneWidget)
.rss.jsonRSS reader (RssWidget)

Other files show “No widget available for this file extension” as a tile and open in the editor. A focused tile switches between a WIDGET view and a CODE view (the raw file). CSV files also get a TABLE view (CsvTableView).

Creating a new widget file

The New File wizard (NewFileWizard in packages/ui/src/LifeOS/Organisms/NewFileWizard.tsx) opens at /new or /files/new, or by Create new File in Ctrl+K. You pick a template, a file name and a folder. The suffix is added for you.

TemplateSuffixStarts with
Note.mdempty
Action Log.actionlog.md# Action Log
Prompts.prompts.md# Prompts
Commands.commands.md# Commands
Todo List.todos.md- [ ] New Task
Data Collection.data-collection.csva column header
Habit Tracker.habit.csvid,title,frequency,target,history
RSS Reader.rss.json
Events.events.csvid,title,date,type,description
Consumption Tracker.consumption.csvcreated
Stocks / Portfolio.stocks.csvempty
Timezones.timezones.json[]
Read It Later.readitlater.json
Bookmarks.bookmarks.json{ "bookmarks": [], "updatedAt": "" }
Command Palette Settings.settings.jsonsuggests .kh/command-palette
Board Overview.board-overview.json{}

Encrypt Content with a password adds .enc to the name. The wizard rejects a path that already exists.

Adding a file to a dashboard

A file becomes a dashboard tile when it is an entry in .kh/.dashboard.config.json:

{ "path": ".kh/inbox.todos.md", "dashboard": "default" }

The ADD TO DASHBOARD modal (AddToDashboardModal.tsx) adds the entry for the open file to a chosen workspace. The console saves the config and pre-loads the new file. Deleting a file also removes its entries and its place in files.recentlyOpened. Workspaces are edited in Settings → DASHBOARDS (WORKSPACES).

Managing todos in the todo widget

A .todos.md file opens in TodoWidget (Widgets/TodoWidget.tsx). The widget shows TASKS and TOP PRIORITIES.

  • Add a task with TodoAddForm; it uses the shared addTodoEntry from @lifosy/formats.
  • Add, assign and delete milestones; edit due dates.
  • A task can carry an AI prompt and a ref: to a prompts file.
  • A file in an old format shows a button to migrate it.

The same files feed /board and /analytics. .kh/inbox.todos.md is the inbox that /quick-todo and the palettes write to. The .todos.md line format is documented with the file formats.

Keeping bookmarks in the console

A .bookmarks.json file opens in BookmarksWidget (Widgets/BookmarksWidget.tsx, logic in BookmarksLogic.ts).

  • Search bookmarks… matches title, URL and tag; a tag chip narrows the list.
  • Sort: NEWEST (file order), LEAST USED (never-opened first) or MOST USED.
  • Each row can be opened, pinned or unpinned, edited (rename and change the link, also in search results) or deleted.
  • Add a bookmark with BookmarkAddForm. Only http/https URLs are accepted, and a duplicate URL is rejected.
  • Usage counts are written by the browser extension’s sync; the console keeps them when it rewrites the file.

The browser extension mirrors .kh/browser.bookmarks.json. Pinned bookmarks come first on its start page. Tests: apps/console/src/bookmarks-logic.test.ts and bookmarks-widget.test.tsx.

Saving articles to read later

A .readitlater.json file opens in ReadItLaterWidget (Widgets/ReadItLaterWidget.tsx) as the READING LIST.

  • Each item can be opened or deleted.
  • Read items move to an ARCHIVED ITEMS view.
  • CLEAR ALL empties the reading list after a confirmation.

The console’s own “add to read it later” handler in Dashboard.tsx writes to <appFolder>/.readitlater.json (normally .kh/.readitlater.json). It parses with parseReadItLater, skips a URL that is already there, puts the new item first, and creates the file if needed. The browser extension’s Read later: this page also adds to the repo’s .readitlater.json.

Using the prompt library

A .prompts.md file opens in PromptsWidget (Widgets/PromptsWidget.tsx) as PROMPTS.

  • Search prompts… and tag chips (sorted by how often they are used) filter the list.
  • Copy prompt copies the prompt text.
  • New prompts are added with PromptsAddForm.

The palettes’ >p mode lists prompts from the repo’s .prompts.md files and copies one on ⏎. The .prompts.md format is documented with the file formats.

Using the command library

A .commands.md file opens in CommandsWidget (Widgets/CommandsWidget.tsx) as COMMANDS.

  • Search commands… and tag chips filter the list.
  • In the focused view, each command with {{name}} parameters gets one field per parameter. Copy command copies it with the values filled in.
  • Outside the focused view a command copies as written, {{name}} and all.
  • New commands are added with addCommandEntry from @lifosy/formats.

The desktop palette runs these commands with >x; the extension copies them. The .commands.md format is documented with the file formats.

Editing command palette settings

.kh/command-palette.settings.json opens in CommandPaletteSettingsWidget (Widgets/CommandPaletteSettingsWidget.tsx). The browser extension and the desktop palette read it; the console only edits it. Create it with New File → Command Palette Settings, which suggests the folder .kh and the name command-palette.

SectionHolds
SEARCH ENGINESOffered for anything typed, in order. ⏎ with nothing else matching searches the first.
AI ASSISTANTSWhat >a offers the question to, in order.
TOOLSA link behind a prefix, like >l then a term.
  • {query} in a URL or parameter value is replaced by what is typed.
  • A parameter has a name, a value, and an optional value used when nothing is typed.
  • Entries can be added, removed, moved up or down, and restored from the defaults.
  • A tool cannot use a built-in prefix (BUILT_IN_PALETTE_PREFIXES). Invalid entries are listed under “Left out of the palette until fixed”.
  • Edits are a draft: Save commits, Revert drops them.
  • If the file cannot be read, the widget says so, and the palettes use the defaults.

The format and defaults (DEFAULT_PALETTE_SETTINGS, PALETTE_SETTINGS_PATH) are in packages/formats/src/palette-settings.ts. Tests: apps/console/src/palette-settings-widget.test.tsx.

Showing board counts on the dashboard

A .board-overview.json file opens in BoardOverviewWidget (BOARD OVERVIEW). It shows counts from the todo files: inbox, in progress and overdue. A click opens /board. The JSON holds its options; missing keys use these defaults:

{
  "showBacklog": true,
  "showInProgress": true,
  "showDone": false,
  "showRejected": false,
  "showOverdue": true,
  "overdueDays": 7,
  "minAgeDays": 0
}

Tracking habits, time, money and other data

These widgets are in packages/ui/src/LifeOS/Organisms/Widgets/, each with a *Logic.ts parser where it has one:

WidgetFilePurpose
HabitTrackerWidget.habit.csvDaily habits and streaks
TimeTrackingWidget.timetracking.csvStart/stop time tracking, with charts
EventsWidget.events.csvUpcoming events and schedule (EventAddForm)
BudgetWidget.budget.csvBudget entries (BudgetAddForm)
DataCollectionWidget.data-collection.csvCustom metrics with typed columns and a chart
ConsumptionWidget.consumption.csvMeter readings (electricity, gas, water, solar), monthly and yearly reports
StocksWidget.stocks.csvPortfolio value and investment over time, with forecast
TimezoneWidget.timezones.jsonWorld clocks (TimezoneAddForm)
RssWidget.rss.jsonNews feeds
ActionLogWidget.actionlog.mdTagged action log entries (ActionLogAddForm)

Demo mode seeds one file of each kind under .kh/ (see packages/core/src/demo/seed.ts).

Encrypting a file in the console

A file whose name ends in .enc is stored encrypted in the repo. Create one by ticking Encrypt Content in the New File wizard and setting a password.

  • The tile asks for the password before it shows the content (EncryptedTileWrapper in packages/ui/src/LifeOS/Molecules/EncryptedTileWrapper.tsx).
  • The suffix before .enc still picks the widget, for example budget.budget.csv.enc.
  • Saving encrypts the content again and commits it.
  • The password is kept by passwordStore (packages/core/src/stores/password.store.ts).