npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@silo-software/app-sdk

v0.2.1

Published

Silo app SDK, host bridge and publisher CLI

Readme

@silo-software/app-sdk

Framework-independent toolkit for building Silo apps. The package contains compiled JavaScript and TypeScript declarations and has no @repo/* dependencies.

Build an app

Run silo-app init my-app --name my-app, install dependencies, and follow the generated README. Register the first manifest with silo-app register --manifest manifest.json using an apps:create publisher token. This scope also permits releases for the apps listed on that token, including the new app.

Define a manifest with @silo-software/app-sdk/contracts, implement your tools with defineSiloAppTool and createSiloAppHandler from @silo-software/app-sdk/server, and use createSiloAppClient for platform services. In your embedded UI, connect an MCP App and pass it to createSiloHostClient from @silo-software/app-sdk/host. Use its callTool for app tools and ui, tableViews, files, resources, and publications for host actions. The host enforces the app's declared capabilities.

import { App } from '@modelcontextprotocol/ext-apps';
import { createSiloHostClient } from '@silo-software/app-sdk/host';
const app = new App({ name: 'My app', version: '1.0.0' }, {});
await app.connect();
const host = createSiloHostClient(app);
await host.ui.navigate('/my-app');

Exports: . (platform client and manifest types), ./server (app runtime), ./identity (identity helpers), ./contracts (schemas and types), and ./host (UI bridge).

Release

Set SILO_API_URL and SILO_PUBLISHER_TOKEN in your CI environment, then run:

silo-app release --manifest manifest.json
silo-app release --manifest manifest.json --promote

The manifest is a JSON object containing the app ID and release definition. Registration prints the release ID and review status. Promotion requires an approved release and a token with promotion scope; it prints the number of installations moved and skipped. Publisher tokens are secrets and should never be committed.

Start a new app

npx @silo-software/app-sdk init my-app
cd my-app
pnpm install
SILO_API_URL=<your Silo API URL> pnpm dev

Request publisher access through an app request in Silo; the Silo team enables your organisation as a publisher and issues a publisher token with apps:create. After deploying and obtaining the deployment manifest, set SILO_API_URL and SILO_PUBLISHER_TOKEN, then run silo-app register --manifest manifest.json for the first release. Use silo-app release for later releases. The GitHub Actions workflow needs VERCEL_TOKEN and SILO_PUBLISHER_TOKEN as secrets; configure SILO_API_URL in Vercel as well.

The public developer documentation covers manifests, platform services, embeds and updates.

Platform ports

createSiloAppClient({ appId, apiOrigin, accessToken }) calls /v1/apps/{appId}/… with a Silo-issued app credential.

| Client | Endpoint | Needs | | --- | --- | --- | | identity.context(), identity.checkPermission() | /identity, /identity/permission | any credential | | data.* (bindings per site/scope, commits) | /data | declared data templates | | directory.listSites(), directory.searchCrm() | /directory | directory.read | | connections.list/startConnection/refresh/update/disconnect | /connections | connections.read / connections.manage (owner or admin when delegated), platforms from connectionPlatforms | | ai.text() | /ai | ai.text, a service credential and a meter from serviceMeters | | media.preview/project/referencePreview | /media | media.read, a delegated user | | commerce.* | /commerce | commerce.read / commerce.write, a delegated user | | publicationCatalog(operation, input) | /publication-catalog | publication.<kind>.read|write grants | | connections.providers.list/set | /connections | connections.read / connections.manage; providers EXA, FIRECRAWL declared in connectionPlatforms; switch per organisation (siteId: null) or site, off by default | | web.search (Exa), web.scrape (Firecrawl) | /web | web.search / web.scrape, provider declared and switched on, a meter from serviceMeters (1 unit per request), content read on the site for delegated users; scrape only public http(s) URLs on default ports |

Web operations run at most once per operationId: repeating it returns the stored result (409 while it runs, 409 if the request differs). failed means nothing ran or the provider refused; ambiguous (APP_OPERATION_AMBIGUOUS) means the provider may have run (timeout, unreadable answer, state not saved) — it is never retried or billed automatically; web.status(operationId) reads the state. Both need a new id to try again. Firecrawl fetches the target itself: Silo checks the URL and its DNS answers at request time, but redirects and later DNS answers seen by the crawler depend on Firecrawl's own target guards. Bound service grants act only for their binding's site. A site switch overrides the organisation switch. The SDK waits up to 45 s and never retries on its own.

Provider secrets (social networks, AI models, payment) never leave Silo; apps act through these ports.

Streaming tools

A tool that sends a sequence of events (for example a chat answer) declares stream: { maxEvents, maxBytes, maxDurationMs } in its manifest entry. It must be visible only to the app UI (visibility: ['app'], not public) and cannot be a block, e-mail or upgrade tool. Silo caps every stream at 10,000 events, 8 MiB, 10 minutes and 64 KiB per event; the lower of the two limits applies. Each event must match the tool's outputSchema.

// Server: each yielded value is one event.
const count = defineSiloAppStreamTool(z.object({ to: z.number().int() }), async function* (input, { signal, resumeFrom }) {
  for (let n = resumeFrom ? Number(resumeFrom) + 1 : 1; n <= input.to && !signal.aborted; n++) yield { n, cursor: String(n) };
});
createSiloAppHandler({ manifest, apiOrigin, resource, tools: { 'my-app.count': count } });

// UI: events arrive in order; the promise settles when the stream ends.
const result = await host.openStream({ tool: 'my-app.count', input: { to: 5 }, signal, onEvent: (event, seq) => render(event) });

Silo checks the same installation, release, role, tool and site permissions as for callTool before the stream opens, re-checks them at least every 15 seconds, and revokes the stream's credential when it ends. result is { status: 'end' } or { status: 'error', code }: APP_STREAM_LIMIT (a limit was exceeded), APP_ACCESS_REVOKED (installation paused or access changed), APP_RUNTIME_UNAVAILABLE (invalid frames or the runtime failed), your own AppToolError code, or APP_STREAM_CANCELLED after signal aborted. Aborting cancels the request to your runtime and aborts the generator's signal. resumeFrom (up to 200 characters) is your own cursor, passed through unchanged; your app keeps whatever it needs to continue from it. A UI frame may hold three open streams; they end when the frame closes or its installation changes.

Public data views and safe actions

See data and platform services and website, embed and newsletter integration for the complete public/private contract, manifest fields, cache revocation, configurable budgets and retry migration.

client.publications.readView({publicationId, view, version, locale, query, ifNoneMatch}) performs an anonymous GET without a participant or app runtime call. The result is {status: 200, etag, data} or {status: 304, etag, data: null}. Public responses are private, no-store; the server cache retains entries for 300 seconds and fences committed changes immediately by generation. A withdrawal is checked before every response, including conditional and versioned reads.

For direct public actions, keep the token from publications.session, generate one operation ID per action, then use publications.invokeWithRetry. Recover with publications.operation({publicationId, operationId, participantToken, proofToken}). For the first website/embed action, use the website SDK's apps.createAction and persist its participant seed and exact content before sending. Both SDK errors expose retryAfter; automatic safe retry is capped at three attempts and a five-second pause. A 409 must be resolved without changing the payload under the same ID.

Plugin bundles receive no implicit database permission. An admin can attach dataBinding: {appId, bindingId, operations: ['read', 'write']}; pass pluginId to createSiloAppClient and continue using client.data.* with that binding. Every marked request rechecks the enabled plugin and current app authority. Existing independently granted app credentials retain their original authority.

Dev reproduction and observed boundaries: data standard acceptance. This source has not been published to npm.