Pingerchips LogoPingerchips

Getting Started

Get up and running with Pingerchips in minutes.

What is Pingerchips?

Pingerchips is real-time infrastructure for AI applications. It gives your agents and users a shared, live connection — so LLM streams reach the browser instantly, agent state is visible as it changes, and multiple agents can coordinate without polling.

Core primitives:

PrimitiveWhat it does
ChannelsFast pub/sub — public, private, and presence
Durable ObjectsNamed, persistent key-value entities with real-time subscriptions
Chat / SessionsDurable threads with LLM token streaming and message history
SpacesEphemeral presence — cursors, members, locations, and locks
PingerflowsVisual pipeline to filter, transform, throttle, and route events

1. Create an App

  1. Sign up or log in at dashboard.pingerchips.com
  2. Go to Dashboard → Apps → New App
  3. Give it a name and click Create

You will see three credentials on the app settings page:

CredentialUse
App IDInternal identifier
App KeyPublic — pass to the client SDK to connect
App SecretPrivate — authenticates server requests and mints capability tokens. Never expose in frontend code

Store them as environment variables:

PINGERCHIPS_APP_KEY=your-app-key
PINGERCHIPS_APP_SECRET=your-app-secret

2. Install the SDKs

npm install pingerchips-js pingerchips-js-server

pingerchips-js runs in the browser; pingerchips-js-server runs on your backend. Both are ESM only ("type": "module" or .mjs).


3. Choose your primitive

Channels — fast pub/sub

Send events between your server and clients. Use this when you don't need persistence.

Server:

import PingerchipsServer from 'pingerchips-js-server';

const pc = new PingerchipsServer(
  process.env.PINGERCHIPS_APP_KEY,
  process.env.PINGERCHIPS_APP_SECRET
);

await pc.trigger('my-channel', 'my-event', { message: 'Hello!' });

Client:

import Pingerchips from 'pingerchips-js';

const client = new Pingerchips(process.env.PINGERCHIPS_APP_KEY);
const channel = await client.subscribe('my-channel');

channel.bind('my-event', (data) => {
  console.log('Received:', data);
});

Durable Objects — persistent agent state

Named objects with slots, atomic operations, and real-time subscriptions. Every write is logged and streamed to all subscribers. Use this for agent run state, shared working memory, and approval queues.

Server — write state:

import PingerchipsServer from 'pingerchips-js-server';

const pc = new PingerchipsServer(
  process.env.PINGERCHIPS_APP_KEY,
  process.env.PINGERCHIPS_APP_SECRET
);

const run = pc.object('run', 'run-abc123');

await run.set('status', 'processing');
await run.set('model', 'claude-sonnet-5');
await run.append('steps', { tool: 'web_search', at: Date.now() });
await run.increment('token_count', 512);

Client — subscribe to changes:

import Pingerchips from 'pingerchips-js';

const pc = new Pingerchips('YOUR_APP_KEY', { authEndpoint: '/auth/durable' });
const run = await pc.object('run', 'run-abc123');

console.log(run.state);
// { status: "processing", model: "claude-sonnet-5", token_count: 512, steps: [...] }

run.on('change:status', ({ value }) => updateStatusBadge(value));

Add the auth endpoint with pc.authenticateObject(...) from pingerchips-js-server — see the Durable Objects quickstart.


Chat / Sessions — LLM streaming with persistence

Durable threads where agents stream tokens and messages are stored. Use this for AI chat interfaces, copilots, and multi-agent pipelines that need an audit log.

Client — connect and receive:

import { PingerchipsChat } from 'pingerchips-js/chat';

const chat = new PingerchipsChat('YOUR_APP_KEY', {
  authEndpoint: '/chat/auth',   // your route → mints a capability token via POST /api/auth
});

const session = await chat.connect('thread-uuid', { clientId: 'user-123' });
const { view } = session;

view.on('update', () => {
  paint(view.getMessages());
  for (const run of view.runs()) {
    if (run.status === 'active') stream(run.runId, view.getStream(run.runId));
  }
});

await view.send('Hello!');

Agent — stream a response:

import { AgentSession } from 'pingerchips-js-server/agent-session.js';
import Anthropic from '@anthropic-ai/sdk';

// called from your invocation route with { threadId, runId } from the body
export async function onInvocation({ threadId, runId, userText }) {
  const agent = new AgentSession(
    process.env.PINGERCHIPS_APP_KEY,
    process.env.PINGERCHIPS_APP_SECRET,
  );
  const thread = await agent.connect(threadId, 'my-bot');
  const run = thread.createRun(runId);
  await run.start();

  let text = '';
  const stream = new Anthropic().messages.stream(
    { model: 'claude-sonnet-5', max_tokens: 1024, messages: [{ role: 'user', content: userText }] },
    { signal: run.abortSignal },
  );
  stream.on('text', async (delta) => {
    text += delta;
    await run.write(text);          // full string so far
  });

  await stream.finalMessage();
  await run.write(text);
  await run.end('complete');
  thread.close();
}

See the Chat quickstart for the auth endpoint and history loading.


Spaces — ephemeral presence

Show who's online, share cursors, and coordinate locks. State is fully ephemeral — disconnecting cleans everything up automatically.

import { PingerchipsSpaces } from 'pingerchips-js/spaces';

const spaces = new PingerchipsSpaces('YOUR_APP_KEY');
await spaces.connect();

const space = await spaces.get('doc-abc123', {
  clientId: 'user-42',
  profile: { name: 'Alice', color: '#FF0099' },
});

space.members.subscribe('enter', (member) => addMember(member));
space.members.subscribe('leave', (member) => removeMember(member));

space.cursors.set({ x: 124, y: 88 });
space.cursors.subscribe('update', ({ member, position }) => {
  renderCursor(member.clientId, position);
});

See the Spaces quickstart.


Next Steps

On this page