Skip to content

The public API and how it changes

This page tells which interfaces of Pi Pocket are for extensions, what Pi Pocket promises about them, and how they change. The reference and the exact types in types/pocket.d.ts tell what each interface is, and the guides tell how to use it. This page does not repeat them.

  • Public: an interface in the list below. Pi Pocket keeps it, or changes it only by the rules on this page.
  • Internal: all other code and data. It can change in any release, with no notice.
  • Stable: public, and not experimental or deprecated. All public interfaces are stable unless the docs mark them.
  • Experimental: public, but it can change or go in any minor release, never in a patch release.
  • Deprecated: public, but it will go. A replacement is available.
  • Breaking change: a change after which a module that obeys the docs can fail, or work differently.
  • Addition: a change after which every such module works as before.

Each item below is public as the reference and the guides describe it: its names, its shapes, its behavior, and the limits.

  • A .ts file in the drop-in folder (extensions/ in the data folder), with the node_modules link to Pi Pocket’s packages.
  • The default export (host, web). It can be async. It returns one extension, a list, or nothing. Pi Pocket installs all of it or none of it.
  • export const pocketApi.
  • The first sentence of the module’s /** … */ comment, which is its description.
  • Files that start with _ or end in .test.ts are not modules.
  • Loading, reloading, and errors (Modules, loading, and errors), with the times in Limits.
  • The types in types/pocket.d.ts: Module, Host, SafeText, LinkedSessions, LinkedSession, Web, WebRequest, WebHandler, WebAccess, WebMethod, Command, CommandContext, CommandResult, BrowserModule, Pocket, the specs and props of what a browser module adds, Person, Role, and NoticeLevel. Import them with import type from ./_pocket.d.ts in the drop-in folder (Types for your editor): the import goes away at run time.
  • src/server/host.ts is internal. Its types (PocketHost, ExtensionWeb, and the others) are Pi Pocket’s own, and can change in any release. test/public-types.ts checks that they fit the public types.
  • The names that Pi Pocket keeps for itself (Names): extension names that start with pocket-, the extension name coding-tools, the names of built-in modules, and the names of built-in tools.
  • The rules for the names of modules, tools, commands, routes, and the IDs of what a browser module adds.
  • The paths of a module’s routes, /api/x/<module>/, and of its browser files, /x/<module>/.
  • Promises: the names of Pi Pocket’s own extensions start with pocket- (or are coding-tools). Its own commands never have a -. Its own document kinds, task names, and browser storage keys never start with x..

These members are public:

  • dataDir, agentDir
  • notice(level, message, id?)
  • resolveModel(spec), subagentModels(), modelProblem(ref, fresh?)
  • requesterOf(conversationId)
  • skillPaths(), skills(cwd)
  • heldBack(conversationId), onLimitsChanged(listener)
  • linkedSessions: start, send, list (experimental in 0.14, see Experimental)
  • text: quoted, defang
  • thinkingLevels

These members are on host for Pi Pocket’s own built-in extensions: guard, approvals, schedules, goals, browsers, memory, watches, repoWatches, gallery, pip, and pipCompaction. They are internal. A drop-in can read them, but their shapes can change in any release. One of them becomes public only through a request for an extension point (core-or-extension.md).

The host’s members do not change while modules reload. A new member comes only after a restart, so a module that uses a new member must check that it is there (Using the host).

  • api, module, route, client, command, send, error, and onDispose.
  • What a route handler gets (WebRequest: method, params, query, body, user, signal), and what its answer does.
  • The route paths, the methods, the access values (owner, steer, view), and the X-Pocket header that every call to a route must have.
  • ctx: user, conversationId, cwd, signal, snapshot, context, and commit.
  • The results { type: "toast", level, message } and { type: "card", output }.
  • The scopes conversation and global, and who may run each.
  • version, module, title.
  • h, html, Fragment, and the hooks: useState, useEffect, useLayoutEffect, useRef, useMemo, useCallback, and useReducer.
  • The pieces Icon, Loader, Spinner, Markdown, and Switch, with the props that pocket gives.
  • api, on, rail, menu, launcher, page, sheet, toolCall, openPage, closePage, openSheet, closeSheet, notify, me, conversationId, style, and onDispose.
  • What a page’s or a sheet’s component gets: pocket, close, and a sheet’s props.
  • The icon names that pocket lists. Other icon names can go. An unknown name shows grid, so a module does not fail.
  • Safe mode: ?noext=1 and ?noext=0 on the app’s address.
  • The variables --text, --muted, --accent, --bg, --card, --line, --err, --warn, and --ok. They follow the theme.
  • The classes button (with primary), error-box, muted, small, mono, and setting.
  • All other CSS is internal: other classes, other variables, the structure of the page, and the IDs of its elements.
  • Themes, new in 0.14.0, have a public surface of their own: the tokens, data-part names, and states in the theme surface reference.
  • web.send(event, data, { to }) on the server and pocket.on(event, run) in the browser, with their limits.
  • A module’s events are its own. An event goes only to the browser module of the module that sent it. Pi Pocket does not keep any event name for itself, and it reads none of them.
  • The app’s own events between the server and its tabs (hello, view, chat, ext, and the others) are internal.
  • The rule to name document kinds, tasks, entry kinds, and browser storage keys x.<module>.…, and to keep a name once people used it: Rules that are easy to break.
  • Promise: core’s names start with pocket., and core never uses x. names, in the store or in the browser.
  • Index format 1, and the fields of an entry, as the index’s README gives them. Where the README and src/server/gallery/entry.ts do not agree, entry.ts is correct.
  • Pi Pocket refuses an entry with a field that it does not know. So an entry can use a new field only when its minPocket is a release that reads that field. Tools that make entries (Share…) leave a new field out when it is empty, as they do with declares.commands.
  • A change to the meaning of a field, or a new field that is necessary, needs a new index format. Pi Pocket reads only its own format.
  • The <name>.gallery.json file next to an installed drop-in, the gallery’s routes, and its screens are internal.
  • All files under src/ and web/, and what they export, src/server/host.ts too. The public types are in types/pocket.d.ts (The module).
  • The app’s HTTP API, other than a module’s own routes under /api/x/<module>/.
  • The events between the server and its tabs, and the pocket.* keys in browser storage.
  • Pi Pocket’s document kinds (pocket.*), and the shapes of its documents, entries, and tasks. A module can read them with api.snapshot, but their fields can change.
  • config.json, pocket.sqlite, and the rest of the data folder, except extensions/.
  • All CSS that is not in CSS.
  • The words of errors, notices, logs, and the system prompt.
  • The tools of built-in extensions: their arguments and results. Only their names are public, as reserved names.
  • The host members for built-in extensions (host).
  • The test helpers in test/. The index’s checks use them, and pin the Pi Pocket version they use.

Extensions import @earendil-works/pi-durable, @earendil-works/pi-ai, and the other packages that Pi Pocket has. Earendil makes them, not Pi Pocket. Pi Durable is experimental, and its API can change between its releases. Pi Pocket pins their versions in package.json, and a drop-in gets the same versions through the node_modules link.

  • A1. The release notes name each update of a pinned package in “For extension authors”.
    Reason: an author can then find the cause when a module breaks after an update.
  • A2. When an update breaks a use that the guides document (defineTool, section, hook, api.memo, api.snapshot, wrapTool, and the others), the notes tell what changed and how to change a module, and pocketApi goes up (A7).
    Reason: authors learn these uses from Pi Pocket’s docs, and they check one number for all that a module uses.

All public interfaces are stable, unless the docs mark them experimental or deprecated.

  • A3. The docs mark an experimental member. The reference writes “Since … · Experimental” under the member. In types/pocket.d.ts, its comment has @experimental. The docs build checks that the two agree.
    Reason: authors must know before they use it.
  • A4. An experimental member can change or go in any minor release, with no deprecation, but never in a patch release (A14). The release notes say so.
    Reason: a new interface must be able to change while its first users find its problems.
  • A5. An experimental member becomes stable when the release notes say so.
    Reason: the change of status is then easy to find.
  • A6. A gallery entry that uses an experimental member should say so in its description.
    Reason: the owner then knows that an update of Pi Pocket can break it.

In 0.14, only host.linkedSessions is experimental. It changed a lot in the betas, and Agent Teams is its only user. It becomes stable in 0.15 if it does not have to change. All other public members of 0.14 are stable.

See Deprecation.

  • POCKET_API is one number for the whole public API, on the server and in the browser. web.api and pocket.version give it. It is 1 from Pi Pocket 0.14.0.
  • A7. pocketApi goes up by one in a release that has a breaking change to a stable member. A release with many breaking changes adds one.
    Reason: one number tells if a module can work, with no need to compare release numbers.
  • A8. Additions do not change pocketApi. Changes to experimental members do not change it.
    Reason: a number that moves for each addition says nothing about breaks.
  • A module’s pocketApi export is the API version that the module was written for. Pi Pocket does not load a module that needs a newer API. It says so in the Extensions sheet. A gallery entry’s pocketApi is the same number. The gallery hides an entry that needs a newer API.
  • A9. Pi Pocket loads modules that were written for the previous pocketApi for at least the deprecation period (A17). After that, it refuses them with an error that tells the owner to update the module. A module with no pocketApi export counts as version 1.
    Reason: authors get the same time to update as for one deprecated member, and an old module fails with a clear message, not at its first use of a member that is gone.
  • A10. A module that uses an addition checks for it at run time, as typeof web.command === "function". In the gallery, it also sets minPocket to the release that added it.
    Reason: the server’s part changes only after a restart, so a running server can have an older host and web than its files.
  • A11. minPocket names a release, such as 0.15.0, not a pre-release. Pi Pocket counts 0.15.0-beta.2 as 0.15.0.
    Reason: a beta can change before the release, and an entry for a beta can break on the release.

These are breaking changes when they touch a stable member:

  • remove or rename a member, a field, an option, an access value, or a CSS name;
  • change the type or the meaning of a parameter, a field, or a result;
  • make an optional parameter or field necessary;
  • accept less than before: a stricter check, a lower limit, or a shorter time limit;
  • give a module less than before: fewer fields, or a narrower access;
  • change a default, such as the owner default of access;
  • change when Pi Pocket calls a module’s code, where the docs say when;
  • change a naming rule for stored data, or the paths of routes;
  • change the gallery entry format so that Pi Pocket refuses a valid entry.
  • a new member, option, field, icon, or CSS name;
  • a higher limit, or a longer time limit;
  • a new optional field in the gallery entry, used with minPocket (The gallery entry format);
  • a fix that makes the behavior agree with the docs.

These can change in any release: the words of errors and notices, timing that the docs do not give, speed, the look of the app beyond the CSS names, and all that is internal.

  • A12. Pi Pocket can keep a new name for itself in any minor release: a module, an extension, a tool, a command, or a theme id (a theme or a palette that comes with Pi Pocket). The release notes list it.
    Reason: new built-in features need names. A module with its own prefix (Names) never meets them.
  • When a new reserved name is the name of a drop-in, Pi Pocket refuses the drop-in, and the Extensions sheet says why. For example, 0.14 keeps the tool team and the module agent-teams.
  • When a new reserved theme id is the id of a theme folder of the owner’s, Pi Pocket does not read that folder, and tells the owner. The gallery does not accept a theme entry with a reserved id. For example, 0.14 keeps the theme lantern.
  • A13. A security fix can change or remove a stable member with no deprecation period, in any release, a patch included. The release notes say so under “Security”. Pi Pocket keeps the change as small as the fix permits.
    Reason: owners must not stay at risk for the length of a deprecation period.
  • Pi Pocket’s version is 0.Y.Z before 1.0. Y is the minor release. Z is the patch.
  • A14. A patch release (0.14.1) has fixes only. It has no additions, no breaking changes to stable members, and no new deprecations. Only a security fix (A13) can break.
    Reason: an owner must be able to take a patch with no risk to their extensions, and each minPocket is then a .0 release.
  • A15. A minor release (0.15.0) can add, deprecate, and change experimental members. It can remove a deprecated member after its minimum time. Then pocketApi goes up.
    Reason: authors then read the notes of minor releases only, to know what changes.
  • A16. Pre-releases (0.15.0-beta.1) have no promise. Members can change from one beta to the next.
    Reason: betas are for tests of new interfaces before they become stable.
  • The two numbers move apart. Many releases of Pi Pocket can have pocketApi 1. pocketApi tells if a module can work. minPocket tells from which release.
  • Pi Pocket is young. Its public API is small, and it will grow.
  • The rules on this page are in force before 1.0. They can change in a minor release. A change that gives authors less is told as a breaking change is.
  • Pi Durable is experimental (see Limitations in the README).
  • At 1.0, Pi Pocket plans to follow semantic versioning: breaking changes only in a major release. This page will say so then.
  1. The replacement ships first, or in the same release. If the feature goes with no replacement, the notes say so.
  2. In types/pocket.d.ts, the member gets @deprecated with what to use instead and when it goes: “Deprecated in 0.15.0. Use web.example. It goes in 0.17.0 or later, and not before 2027-02-01.” Editors then show it.
  3. Its page in the reference gets the line “Since 0.14.0 · Deprecated”, with the same words under it. The docs build checks that the reference and the types file agree.
  4. The release notes list it under “Deprecated”, in “For extension authors”.
  • A17. A deprecated member stays for at least one minor release and at least 90 days, from the first stable release that deprecates it. The later of the two applies. Experimental members have no minimum (A4). Security fixes have none (A13).
    Reason: an author who updates a few times a year must have time to see the warning and change the module.
  • A18. A deprecated member goes only in a minor release, after its minimum time. That release raises pocketApi by one.
    Reason: authors then know when to look, and one number shows the break.
  • The release notes list it under “Removed”, with what to use instead.
  • A20. When what a theme part names leaves the app, the part goes with it, in the same release, with a release note. A theme’s rules for it then match nothing, and the rest of the theme works as before. A part whose region stays but changes its name keeps the old name as an alias, by A17 and A18.
    Reason: the app cannot keep a screen for the sake of a selector; a rename costs nothing to keep.

Release notes: “For extension authors”

Section titled “Release notes: “For extension authors””
  • A19. The notes of each release have a section “For extension authors”. The 0.14 betas already have it. It uses these headings, in this order, with one line and a link for each item:

    • Added
    • Changed: changes to experimental members, and fixes that authors can see.
    • Deprecated: each with its replacement and its earliest removal. The first release with a deprecated member also tells how the owner sees the warning (Warnings).
    • Removed: and the new pocketApi.
    • Reserved names
    • Security: changes with no deprecation period (A13).
    • Packages: updates of the pinned packages from Earendil (A1).

    When nothing changed, the section says “No changes.”
    Reason: authors read one place, and “No changes” is also information.

  • Nothing is deprecated now, and Pi Pocket shows no deprecation warnings. The first release that deprecates a public member adds a warning that the owner sees when a module uses it. Its notes say so under “Deprecated”.
  • The check for the oldest supported pocketApi (A9) comes with pocketApi 2. Until then, every version is supported.

These pages describe Pi Pocket 0.14.0. Your copy has the pages of its own version in its docs/ folder.