Every agent lives on someone's server. Until now.
The problem
OpenAI's GPTs live in OpenAI's store. Claude's Projects live in Anthropic's account. Custom instructions stick to one app. If you built a great agent, you can't just send it to a friend — you have to send them back to the host.
The move
Compress the whole agent into ~600 chars of URL fragment. The
fragment never touches a server (no access log, no referrer). Any
page that reads window.pocketAgentRead() picks it
up. The browser extension exposes that reader on every
site. Paste, preview, install. Done.
Try a starter agent.
Each card below is a real PocketAgent bundle. Click install — the embed widget will show you the full payload, then save it to your browser. After install, visit any site on this domain that reads PocketAgents (the EML-LM chat, ZeroClaw, or AI Assistant), or — if you have the extension — any chat site you've allowed.
Install PocketAgent Companion.
The browser extension adds window.pocketAgentRead() to
every site you visit (passive mode) and, with your per-domain
opt-in, prepends your agent to chat textareas on sites like
chat.openai.com, claude.ai,
gemini.google.com, and chat.mistral.ai
(active mode).
Load the dev build
git clone https://github.com/johnjboren/johnjboren.github.io.git
cd johnjboren.github.io/pocketagent-extension
# Chrome / Edge:
# 1. Visit chrome://extensions
# 2. Turn on Developer mode
# 3. Load unpacked → select this directory
# Firefox:
# 1. Visit about:debugging#/runtime/this-firefox
# 2. Load Temporary Add-on → pick manifest.json
Web store submission is a TODO. Until then, the unpacked load above is the install path. Read the extension README for the full spec.
Adopt PocketAgent on your own site.
Three <script> tags and an opt-in attribute. After
that, every URL with #pa=… gets a preview card; every
<install-pocketagent> tag renders as a styled
install button.
<html data-pocketagent-auto>
<head>
<script src="https://johnjboren.github.io/scripts/pocketagent/pocketagent-codec.js"></script>
<script src="https://johnjboren.github.io/scripts/pocketagent/pocketagent-reader.js"></script>
<script src="https://johnjboren.github.io/scripts/pocketagent/pocketagent-ui.js"></script>
<script src="https://johnjboren.github.io/scripts/pocketagent/pocketagent-embed.js"></script>
</head>
<body>
<install-pocketagent href="https://example.com/#pa=H4sIAAA...">
install pirate-reviewer
</install-pocketagent>
</body>
Read the installed agent
Prepend it to your own LLM's system prompt:
const agent = window.pocketAgentRead?.() || '';
const systemPrompt = (agent ? agent + '\n\n' : '') + yourBasePrompt;
// feed systemPrompt to WebLLM / Ollama / remote API
Compose your own URL
const payload = window.PocketAgent.buildPayloadFromLocalStorage({
name: 'my-reviewer',
role: 'You are a careful code reviewer…',
tags: ['code review'],
rules: ['always explain your reasoning'],
});
const { url } = await window.PocketAgent.composeUrl(payload);
// → "https://yoursite/#pa=H4sIAAA…"
Works with anything that takes a system prompt.
In-browser (WebLLM)
Try your installed agent against a local LLM running entirely in your browser tab — no server, no API key.
Ollama (local server)
Chat with a model from your local localhost:11434
Ollama server with the installed agent prepended automatically.
Remote APIs
Read pocketAgentRead() in your app, prepend to any
system prompt you send to OpenAI, Anthropic, Mistral, etc.
PocketAgent is provider-agnostic — it's just text.
Untrusted by default.
- Preview before install. Every receiver shows the full payload (role, rules, examples) before anything is saved. No silent imports, no auto-apply.
- Field caps are the boundary. Role ≤ 1200 chars, rules ≤ 6×120, examples ≤ 4 × (200+300). Bounds the attack surface regardless of intent.
-
Jailbreak-phrase scrub at decode. Well-known injections like
ignore previous instructions,<|im_start|>tokens,[[SYSTEM]]markers get redacted. Not a wall — paraphrases pass — but a clear speed bump. -
Clear delimiters in the output. Downstream LLMs see
=== BEGIN POCKETAGENT: <name> ===/=== END POCKETAGENT ===around the imported section. Good models treat it as provenance; adversarial agents can still try to argue past it. Assume the agent controls the model's behavior and design UX around that. -
All state is local. The payload lives in
localStorage['pocketagent-v1']. Nothing syncs, nothing leaves the tab (or the extension). Ever. - Active mode is opt-in per domain. The extension never injects into a chat site until you explicitly allow it from the popup.
PocketAgent v1 specification.
Full schema, encoding format, storage keys, read API, and versioning rules:
- pocketagent/spec.md — the human-readable spec
- pocketagent/schema.json — JSON Schema draft 2020-12
- scripts/pocketagent/ — reference JS implementation (codec, reader, UI, embed, QR)
- pocketagent-extension/ — browser extension reference