Package SDK
Manifest
type PackageDefinition = {
meta: {
displayName: string;
description?: string;
icon?: string;
window?: {
width?: number;
height?: number;
minWidth?: number;
minHeight?: number;
};
capabilities?: {
kernel?: string[];
outbound?: string[];
daemon?: string[];
storage?: string[];
};
};
browser?: {
entry: string;
assets?: string[];
};
backend?: {
entry: string;
public_routes?: string[];
};
cli?: {
commands?: Record<string, string>;
};
};Import the manifest helper from @gsv/package/manifest.
meta.capabilities.kernel is the package's syscall grant list. Declare only the calls the backend or CLI entrypoints actually need. Use repo.* when a package needs to inspect or edit ripgit repositories, and pkg.* only for package lifecycle operations such as install, checkout, review, and public visibility.
Example:
capabilities: {
kernel: ["repo.read", "repo.search", "fs.read"],
daemon: ["rpc-schedules"],
storage: ["sql"],
},meta.capabilities.daemon requests package daemon APIs such as RPC schedules. meta.capabilities.storage requests package-scoped storage APIs such as SQL.
Backend
Import the backend base class from @gsv/package/backend.
export default class ExampleBackend extends PackageBackendEntrypoint {
async fetch(request: Request): Promise<Response> {
return new Response("ok");
}
async onSignal(ctx: PackageSignalContext): Promise<void> {}
}Backend instance bindings:
this.meta{ packageName, packageId, routeBase }
this.kernel.request(call, args)- issue kernel requests
this.storage?.sql.exec(statement, ...bindings)- execute package-scoped SQLite statements
this.viewer- authenticated viewer identity for session-backed requests
this.app- browser app session metadata
this.daemon- RPC schedule helpers and current trigger metadata
Reserved built-ins:
fetch(request)- optional HTTP route handler
onSignal(ctx)- optional signal hook
Every other public method is exposed as backend RPC.
Browser helpers
Import browser helpers from @gsv/package/browser.
getAppBoot()
Returns browser boot metadata:
type PackageAppBoot = {
packageId: string;
packageName: string;
routeBase: string;
rpcBase: string;
sessionId: string;
sessionSecret: string;
clientId: string;
expiresAt: number;
hasBackend: boolean;
};hasAppBoot()
Returns true when the package boot payload is present.
connectBackend<T>()
Connects to the package backend RPC surface and returns a stable proxy.
Behavior:
- opens the backend websocket session on first use
- caches the backend proxy for reuse
- reconnects automatically on transport disconnect and retries the failed call once
- throws immediately when the package has no backend entrypoint
getBackend<T>()
Alias for connectBackend<T>().
CLI
Import CLI helpers from @gsv/package/cli.
type PackageCommandContext = {
meta: {
packageName: string;
packageId: string;
routeBase: string | null;
};
viewer: {
uid: number;
username: string;
};
kernel: {
request<T = unknown>(call: string, args?: unknown): Promise<T>;
};
storage?: {
sql: {
exec<T extends Record<string, unknown>>(
statement: string,
...bindings: Array<string | number | boolean | null>
): Promise<T[]>;
};
};
argv: string[];
stdin: {
text(): Promise<string>;
};
stdout: {
write(text: string): Promise<void>;
};
stderr: {
write(text: string): Promise<void>;
};
};Use defineCommand(handler) and default-export the handler module.
Installed package commands are exposed in the native GSV shell by command name. For example, a package manifest with cli.commands.wiki makes wiki ... available through shell.exec on target: "gsv", subject to the package's declared kernel grants.
Public routes
backend.public_routes is the only auth-bypass declaration in the manifest.
Rules:
- exact path matches only
- routing still lives in
backend.fetch() - undeclared backend paths remain session-authenticated
- package code is still responsible for webhook signature checks and any route-specific authorization
Browser entry rules
- browser entrypoints must be JS/TS modules, not HTML
- package apps render into the fixed platform shell
browser.assetsis for stylesheets and other static assets- JSX packages must declare
preact
Package state
this.storage.sql is package-scoped runtime storage surfaced by the platform.
Current behavior:
- the storage boundary is package-runtime scoped
- the API is async from package code
- bindings accept
string,number,boolean, andnull - booleans are stored as numeric SQLite values
Ship source changes
After changing a package source tree under /src/repos:
rgit diff owner/repo
rgit commit owner/repo --message "update package"
pkg update <package> --ref mainUse repo.import or the console's Pull upstream action to fetch upstream changes into a deployed root/gsv. The pull records refs/remotes/upstream/<ref> and fast-forwards the local branch only when safe. If local commits diverged, merge upstream first and then update affected packages explicitly.
If you changed the package runtime, SDK, assembler, or Gateway code, redeploy the relevant infrastructure before updating installed packages.