Skip to content

Plugin API reference

Every value on this page is read out of the Whittl build it was generated from, so it cannot drift from what the plugin loader accepts.

For what to do with it, see Plugins and the plugin format.

=== WHITTL PLUGIN API 1 (generated from this build) ===

A plugin is a folder with manifest.json. The manifest lists CONTRIBUTIONS, each of one type below; a plugin may contribute several. (A manifest with top-level kind/entry instead of a contributions list is read as one contribution.)

CONTRIBUTION TYPES (contribution key: type)
  tool         - A function the AI can call while it builds. run(args) -> str, or run(args, context).
                 runs: subprocess
                 requires: entry   optional: name, parameters, context, examples, timeout
                 * Offered to the AI beside Whittl's built-in tools, under its name. The description is the only thing telling the model when to use it.
                 * The manifest examples are RUN and are the acceptance test.
                 * One plugin may contribute several tools; give each its own name.
  panel        - A widget Whittl shows on one of its surfaces. create_panel(context) -> QWidget.
                 runs: in_process on the interface thread
                 requires: entry   optional: title, placement, order
                 * Never offered to the AI. Verified by building it once in an offscreen process before it is ever loaded.
                 * placement is tab (default), dialog or statusbar.
                 * order (an integer, default 100) decides where a tab goes: lower first. Code is 0; Whittl's own Assets, Archives, Terminal and Help tabs use 5, 8, 10 and 20.
                 * Take colours from context.colors() and subscribe to the events you display, or the panel goes stale.
  menu_action  - An entry in the Edit > Plugins menu that runs a function. The function receives the same context a panel does.
                 runs: in_process on the interface thread
                 requires: entry, function, label
                 * For something done on demand: export a file, open a folder, reset a state. Keep it fast - the window waits for it.
                 * Return a string and it is shown in the status bar.
  hook         - A function Whittl calls when something happens: a generation starting or finishing, a project opening, a run starting.
                 runs: in_process on a helper thread of Whittl's, with a 3 second deadline - never touch a widget from a hook; record what you saw and let a panel poll
                 requires: entry, function, point
                 * The function receives one dict, the payload for that point.
                 * generation.before may return a string; it is appended to the prompt as guidance. Every other return value is ignored.
                 * A hook that raises three times, or one that does not return within 3 seconds, is switched off for the session and the reason is logged.
  skill        - A skill file (markdown with the usual front matter) that joins the skill library while the plugin is enabled.
                 runs: static
                 requires: file
                 * Same format as ~/.whittl/skills/. Triggers and budgets apply exactly as they do to any other skill.
                 * Disabling the plugin removes the skill.

HOOK POINTS (a hook contribution's 'point')
  generation.before    - A generation is about to start.
                         thread: a helper thread; the window waits up to 3 seconds
                         payload keys: message, target, project_id, files
                         may return: a string appended to the prompt as extra guidance
  generation.after     - A generation finished, successfully or not.
                         thread: a helper thread; the caller waits up to 3 seconds
                         payload keys: message, target, project_id, files, cancelled
  project.opened       - A different project is now open.
                         thread: a helper thread; the window waits up to 3 seconds
                         payload keys: project_id, name, target
  run.before           - The user pressed Run.
                         thread: a helper thread; the window waits up to 3 seconds
                         payload keys: project_id, files

PLACEMENTS for a panel (contribution key: placement)
  tab        - its own tab in the preview pane. The default.
  dialog     - a window opened from the Edit > Plugins menu. For something consulted occasionally rather than watched.
  statusbar  - a small always-visible widget in the status bar, capped at 320 pixels. For a live number or state; keep the text short.
  A panel may not be placed anywhere else. These are the surfaces Whittl offers.
  A dialog panel is opened from Edit > Plugins; a tab is reached by its tab and a statusbar panel is always visible.

PERMISSIONS (manifest key: permissions) - DISCLOSURE, not enforcement. Declare what the code really does.
  files       - reads or writes files outside the project
  network     - makes network requests
  hardware    - touches devices: camera, serial, audio
  subprocess  - runs other programs

CONTEXT KEYS for a tool (contribution key: context)
  project_dir  - absolute path of the user's project on disk
  files        - {filename: contents} for the project. The WHOLE project
  target       - pyside6, flet, customtkinter, general or plugin

LIMITS
  api_version    - this Whittl provides 1; declare it in the manifest
  plugin name    - lowercase letters, digits, underscores, 2-40 chars, starts with a letter (tool names likewise)
  panel title    - at most 24 characters
  panel order    - integer 0-1000, lower mounts first (default 100)
  reserved tab titles (a TAB panel may not use these): code, assets, archives, terminal, help
  timeout        - seconds, at most 120 (default 30)
  returned text  - truncated at 100000 characters
  reserved names (a tool may NOT be called these): bash, create_file, delete_file, download_file, edit_code, edit_function, glob, list_files, load_skill, multi_edit, probe_app, question, read_code, run_code, run_script, search_code, str_replace_based_edit_tool, syntax_check, web_fetch, web_search

WHAT A PANEL'S OR MENU ACTION'S context OFFERS - this is the whole surface, nothing else about Whittl is reachable:
  context.archives() -> 'Dict[str, Any]' The open project's archives - snapshots of its code and assets - as ``entries``, oldest first, each with ``index`` (what the actions take), ``version``, ``name``, ``timestamp`` (ISO 8601), ``file_count``, ``total_lines``, ``asset_count`` and ``has_assets``.
  context.archives_create(name: 'str' = '') -> 'bool' Save a snapshot of the open project's code and assets.
  context.archives_delete(index: 'int') -> 'bool' Delete an archive and its files on disk.
  context.archives_restore(index: 'int') -> 'bool' Put an archive's code back in the editor.
  context.assets() -> 'Dict[str, Any]' The open project's assets: ``folder`` (the assets directory, "" when no project is open), ``project_folder``, and ``entries`` sorted by name, each with ``name``, ``path``, ``size``, ``is_image`` and ``source`` - "user" (the user's, protected from regeneration), "ai" (regenerable) or "unknown".
  context.assets_delete(paths: 'List[str]') -> 'Dict[str, Any]' Delete assets.
  context.assets_import(paths: 'List[str]') -> 'Dict[str, Any]' Copy files into the project's assets folder and mark them the user's.
  context.assets_rename(path: 'str', new_name: 'str') -> 'Dict[str, Any]' Rename an asset in place, keeping its provenance.
  context.assets_set_source(names: 'List[str]', source: 'str') -> 'bool' Mark assets as "user" (protected from regeneration) or "ai".
  context.chat_prefill(text: 'str') -> 'bool' Put text in the chat input and focus it, WITHOUT sending: the user still sends it.
  context.colors() -> 'Dict[str, str]' The current theme palette, as a name -> "#rrggbb" mapping.
  context.console() -> 'Dict[str, Any]' The Terminal transcript Whittl keeps: ``generation`` (bumped on every clear) and ``entries``, oldest first, each with ``seq``, ``kind`` (stdout, stderr, command or info) and ``text``.
  context.console_clear() -> 'bool' Empty the Terminal transcript for every viewer.
  context.console_write(text: 'str', kind: 'str' = 'stdout') -> 'bool' Append text to the Terminal transcript, for every viewer.
  context.get_setting(key: 'str', default: 'Any' = None) -> 'Any' Read a value this plugin stored.
  context.icon(name: 'str', color: 'Optional[str]' = None, size: 'int' = 16) One of Whittl's own icons (Phosphor names: "plus", "image", "arrows-clockwise", "trash", ...) as a QIcon tinted to ``color``, or None when the host has none.
  context.log(message: 'str') -> 'None' Print a line tagged with this plugin's name, for the terminal.
  context.model() -> 'Dict[str, Any]' The model Whittl is talking to right now: ``backend``, ``model`` (its id), ``context_window`` (tokens it can hold, 0 when unknown) and ``window_source`` ("provider", or "num_ctx" when the Ollama setting is the smaller limit).
  context.project() -> 'Dict[str, Any]' The open project: ``id``, ``name``, ``dir``, ``target``, ``files`` (a name -> source mapping).
  context.set_setting(key: 'str', value: 'Any') -> 'bool' Persist a value for this plugin.
  context.subscribe(event: 'str', callback: 'Callable[[], None]') -> 'None' Call ``callback`` when ``event`` happens.
  context.usage() -> 'List[Dict[str, Any]]' Recorded API calls, oldest first.
  context.usage_summary() -> 'Dict[str, Any]' Totals for the current session: ``requests``, ``input_tokens``, ``output_tokens``, ``cost``, and ``by_model`` / ``by_backend`` maps.
  context.version          Whittl's version string.
  events                   subscribe() accepts: theme, usage, project, console, assets, archives.

Where these come from

Thing Defined in
kinds, placements, permissions, context keys, limits core/plugin_manager.py
what a panel's context offers core/plugin_context.py
the events a panel can subscribe to core/plugin_context.py

A plugin whose manifest breaks any rule above is listed in Edit > Plugins with the reason, rather than silently failing to appear.

Generated from Whittl 2.6.0.