Skip to content

ctx.storage

Persisted, per-extension key/value storage in two scopes (ExtensionStorageScopes). Each scope is an ExtensionStorage namespaced to your extension id, shared across all your surfaces (status bar, side panels, settings page).

ts
ctx.storage: ExtensionStorageScopes // { global, workspace }
ScopeLifetimeUse for
ctx.storage.globalone bag, shared across all workspacesthe extension's own settings (enabled features, …)
ctx.storage.workspaceone bag per active workspacestate that should differ per workspace

Example

Read settings up front in activate and persist on change. get/set are safe to call immediately — but the app state hydrates asynchronously (and the workspace bag is swapped when the active workspace changes), so subscribe and re-read to pick up a value that lands after activate:

ts
export const extension: Extension = {
  id: "my.extension",
  activate(ctx) {
    const store = ctx.storage.global;

    const apply = () => render(store.get<Settings>("settings", DEFAULTS));
    apply();
    ctx.subscriptions.push({ dispose: store.subscribe(apply) });

    // later, from a settings page or panel:
    store.set("settings", next);
  },
};

Methods

On each ExtensionStorage scope. Method names link to the full signature.

MethodWhat it does
get(key, fallback?)Read a value; returns fallback (or undefined) when the key is missing.
set(key, value)Write a value. Passing undefined deletes the key.
keys()The keys currently set in this namespace.
subscribe(listener)Observe changes in this namespace (also fires on hydration and workspace swap); returns an unsubscribe function.

Types

Pass ExtensionStorageScopes ({ global, workspace }), each an ExtensionStorage.

Related: SidePanelProps exposes the same workspace scope keyed by panel id, for panel-local UI state.

See also

Other Services on ctx.