Parley Sqlite
FreeMaintainedParley SQLite backend: zero-infra, polling-only seam implementation. The seam-proving reference backend.
About
Parley SQLite backend: zero-infra, polling-only seam implementation. The seam-proving reference backend.
README
Plan a task in your Claude chat, hand it to a Claude Code session that catches up on the shared thread and does the work, then read the result back in a chat app you already keep open.
Parley is an MCP server — the standard way Claude connects to outside tools — that turns your Claude chat, your Claude Code sessions, and you into one shared, durable thread over a messaging backend you choose.
Put plainly, it lets you share context between Claude chat and Claude Code, hand off a task to a coding agent and get the result back, and keep humans and agents in the same chat room — running on a self-hosted message bus for AI agents that you operate.
Contents: The loop · Two ways in · Quickstart A — local, 5 min · Quickstart B — chat→Code, 15 min · Today vs. preview · How it works · Backends · Tools · Configuration · Remote / chat mode · Compare · Status · Docs
The loop
Your Claude chat and your Claude Code sessions can't talk to each other. Right now you are the cable: you copy a plan out of one window, paste it into the other, wait, then ferry the answer back. Parley is the shared thread that lets them confer over a durable backend while you watch from an ordinary chat app.
Keep Matrix open on your phone, run a Claude Code session on your acme project, and wire a Claude chat to the same topic — project-acme:
- In your Claude chat, post a self-contained brief to
project-acme: "Add retry-with-backoff to the S3 upload path inuploader.ts; cap at 5 attempts; add a unit test." (Under the hood:parley_post.) - You copy nothing. Go back to what you were doing.
- A Claude Code session on
acmestarts (asclaude-code-acme) and, on start, callsparley_fetch_recentonproject-acme— catch-up-on-start over the durable backend, not a live push — reading your brief as if it had been in the room the whole time, though it wasn't running when you posted. (The chat-handoff skill is what wires this fetch to fire automatically on session start.) - It does the work — edits
uploader.ts, adds the test, runs it — then posts the result back into the same topic (threaded viain_reply_to): "Done — addedwithBackoff(), capped at 5, testretries on 503passing." - You read the answer where you asked it — the whole plan → hand-off → result thread lands in your ordinary Matrix app. No terminal, no copy-paste.
Two ways in
The full chat→Code loop above needs remote mode: a Claude chat lives in Anthropic's cloud and can't reach a stdio server on your laptop, so chat joins the thread over an HTTP connector, not a local file. Two on-ramps — price the gap before you start:
- Kick the tires in 5 minutes — no accounts, no domain, no server; Node ≥ 22. A local taste on one SQLite file, Code↔Code. It proves the whole shared-thread spine end to end; the only thing left off is the chat seat.
- The real hand-off — needs a public HTTPS URL + a claude.ai connector; ~15 min. chat→Code over remote/OAuth mode. The maintainer runs this remote-mode hand-off in production, in a hardened Keycloak/OIDC + Zulip variant (see Remote / chat mode); Quickstart B is the lighter built-in-OAuth + SQLite on-ramp to the same mode.
About the phone. The hero's "read it back in a chat app you already keep open" is the full loop — remote mode plus a chat backend — so it's Quickstart B with one swap, not the 5-minute path. Today the honest, live-proven phone pick is Matrix (or XMPP with a MAM server); the consumer apps most people keep open are still fake-conformance (details). Quickstart B lands chat→Code and reads back in Claude chat; its Land it on your phone step swaps SQLite for Matrix to also drop the thread onto your phone.
Quickstart A: the local taste (5 min, zero infra)
The deliberate local taste — two Claude Code sessions, two directories, one SQLite file — the shared-thread spine with the chat seat left off (that's Quickstart B). No broker, no server, no flags.
Prereqs: Node ≥ 22, two Claude Code sessions, ~5 min — no accounts, no domain, no server.
Give each session its own directory so their configs and .mcp.json don't collide; both point at the same db_path, which is the bus.
1. Install core plus the SQLite backend (in each directory):
npm install @sharptrick/parley-core @sharptrick/parley-sqlite
2. Write a parley.config.yaml in each directory — identical except the handle:
# planner/parley.config.yaml (coder/ is identical but handle: "coder")
# The backend is chosen by which binary you run (parley-sqlite, below) — not by config.
identity:
handle: "planner" # session B uses "coder"
topics:
- "ctx-demo"
backend_config:
db_path: "../parley-demo.db" # BOTH sessions point at this one file — it is the bus
Defaults are catch-up-only and safe: no live push. The rest of the knobs are in Configuration; you need none of them for the aha.
3. Point a .mcp.json in each directory at the stdio server:
{
"mcpServers": {
"parley": {
"command": "npx",
"args": ["parley-sqlite", "--config", "parley.config.yaml"]
}
}
}
parley-sqliteis the bin shipped by@sharptrick/parley-sqlite;npxresolves it from your local install. Every backend package ships one —parley-redis,parley-matrix,parley-postgres, and so on — and which one you run is how you choose a backend.
4. Run the hand-off. Open two Claude Code sessions, one per directory (planner and coder), both resolving to the same parley-demo.db:
- In
planner: "postplan: add retry-with-backoff to uploader.ts, cap at 5to ctx-demo" → it runsparley_post. - In
coder: "fetch recent on ctx-demo, then reply with a result" → it runsparley_fetch_recent, readsplanner's brief even though it wasn't running when planner posted, and replies withparley_post+in_reply_to. - Back in
planner: "fetch recent on ctx-demo" → the coder's threaded reply is right there.
Here you trigger each fetch by hand to watch it work; in a wired session the on-start catch-up from The loop fires automatically.
That's the round-trip. parley_fetch_recent hands back the message plus the bookmark that makes catch-up durable:
{
"messages": [
{
"topic": "ctx-demo",
"senderHandle": "planner",
"content": "plan: add retry-with-backoff to uploader.ts, cap at 5",
"backendMsgId": "1",
"cursor": "1",
"mentions": [],
"timestamp": "2026-07-12T18:03:11.204Z"
}
],
"nextCursor": "1"
}
Why this survives a restart (optional)
nextCursor is the whole trick: persist it, pass it back as since, and the next catch-up returns only messages newer than it — never re-sending one you already read. Kill coder mid-hand-off and start it again: it catches up from its bookmark, re-reads the thread, and loses nothing. Then run parley-redis / parley-nats / parley-matrix instead of parley-sqlite and the same participants run across machines with zero code changes — correctness lives in the seam, not in any one host. The mechanics (cursor, backendMsgId) are spelled out in How it works.
Quickstart B: the chat-to-Code hand-off (remote mode, ~15 min)
The loop the hero promised — a Claude chat plans, a Claude Code session does the work — over the built-in OAuth front door. No external identity provider for this light path.
Prereqs: a public HTTPS URL (a one-command tunnel works) and a claude.ai connector, ~15 min. Node ≥ 22 for the server; no external IdP on this light path.
Run the self-host-remote reference server as an HTTP server (same seam, a local SQLite backend, just spoken over HTTP). Set
PARLEY_OWNER_PASSPHRASElocally and start it on127.0.0.1:3000.Put it behind HTTPS. Claude requires a public HTTPS endpoint. The fastest way is one tunnel command (install cloudflared first):
cloudflared tunnel --url http://127.0.0.1:3000Set
PARLEY_ISSUER_URLto thehttps://…trycloudflare.comURL it prints. That URL is ephemeral — for a stable one, front the server with Caddy/nginx instead (there's a ready Caddyfile in the self-host README).Add a claude.ai connector pointed at
https://parley.example.com/mcp(your HTTPS URL +/mcp). Claude runs discovery → dynamic client registration → PKCE; on the consent page, enter your owner passphrase to authorize. Backend creds never leave the server — Claude holds only a consented token.Hand off. In your Claude chat,
parley_posta brief toproject-acme. A Claude Code session on that project catches up on start withparley_fetch_recentand does the work — so the brief is waiting whether or not any session was live when you posted.
Step 4 is the real, in-production shape: chat→Code lands over the durable catch-up path. The other half — an already-running session reacting the instant you post — is the live-push preview (below), not needed here. Full recipe + connector gotchas + the optional Keycloak/OIDC front door: examples/self-host-remote/README.md.
Optional — land it on your phone. Quickstart B reads back in Claude chat. To get the hero's phone experience, swap the SQLite backend for Matrix — the live-proven phone pick (backends): install
@sharptrick/parley-matrix, runparley-matrixinstead ofparley-sqlite, swapbackend_configfor your homeserver's, and keep the same topics. The plan → hand-off → result thread then also shows up in an ordinary Matrix app on your phone. Same seam, zero participant-code changes; config is in the bridge-matrix README.Give the Matrix instance its own
instance_id(or delete the old read-state file it names). Read-state is keyed per instance, and cursors are backend-specific — replaying a SQLite cursor into Matrix is an error, though a clearly-worded one.
What runs today, and what's still preview
Two delivery paths — one is the product, one is a preview. Stated once, here:
Tier 1 — durable catch-up (the product, works today). parley_post + parley_fetch_recent over standard MCP: a session catches up on start from the backend's own store, with ordering and dedup from the cursor + backendMsgId, never timestamps. Live-tested on 6 of 10 backends against real implementations — SQLite as a real on-disk file, plus real Redis/NATS/Postgres servers and live Matrix/XMPP homeservers — with no subscription, no flag, and on the SQLite path no server at all. This is what buys restart-survival, a swappable backend, and a human reading in a real chat app — and it's what the remote hand-off in Quickstart B rides.
Tier 2 — live <channel> push (research preview). Proactive events into an already-running Code session, riding Claude Code's native claude/channel capability. Verified headless-only — an InMemoryTransport harness plus a human manual checklist — and not yet demonstrated in a real interactive Claude Code session. It needs Claude Code v2.1.80+, a claude.ai subscription or a Console API key (not Bedrock, Vertex, or Foundry), and the --dangerously-load-development-channels flag against the fakechat loopback (--channels plugin:fakechat@claude-plugins-official). It rides Anthropic's research preview and may break on any Claude Code release — treat it as experimental, never load-bearing: a dropped or duplicated push is reconciled by the next parley_fetch_recent, and Tier 1 stands on its own.
Reading on your phone. Of the 6 live backends, Matrix is a mainstream chat app with clients on every phone — the honest end-to-end pick right now (XMPP is the other, given a MAM-enabled server). The consumer apps most people already keep open — Zulip, Slack, Discord, Telegram — are fake-conformance today (see the table below; Zulip is additionally the maintainer's operator-run production backend). So for the loop end-to-end on live-proven code, reach for Matrix.
How it works
Three numbers: 10 backends, each implementing the same 6 seam methods; Claude itself calls just 3 MCP tools.
The seam is that one small interface every backend implements. All the hard, backend-independent logic — live push, catch-up, dedup, ordering, reply fan-out, OAuth mode — is written once above it in @sharptrick/parley-core. Dependencies point one way: a plugin depends on core, never the reverse.
Messaging backend SQLite · Redis · Postgres · Matrix · XMPP · NATS · Zulip · Discord · Slack · Telegram
│ backend-native protocol
Backend plugin implements the seam (the six methods below)
│ normalized Message (topic · sender · content · backendMsgId · cursor · mentions)
@sharptrick/parley-core reactive tools (post · fetchRecent) + proactive push (<channel> events)
│ dedup + ordering via cursor · reply fan-out · topic allowlist · OAuth mode
┌────┴───────────────────────────┐
Claude Code Claude chat · you, in a normal chat client
catch-up + live push (preview) post + fetchRecent
The whole product is these six seam methods:
interface BackendPlugin {
connect(config): Promise<void>;
disconnect(): Promise<void>;
subscribe(topic, handler): Promise<void>; // live path (push) — lossy, see below
post(topic, identity, content, opts?): Promise<BackendMsgId>; // the single durable write
fetchRecent({ topic, since?, limit? }): Promise<{ messages, nextCursor }>; // catch-up
resolveIdentity(handle): Promise<BackendIdentity>;
}
Four requirements make a backend correct. Two are about the message: a stable, unique backendMsgId (the dedup key — how core throws away a message it has already seen) and a monotonic cursor (an opaque, ever-advancing per-topic position). Two are about the live path: what subscribe delivers is a subset of the post-subscribe tail and no more, and it must actually deliver — a subscriber does not fall behind a topic written a message at a time. A backend satisfying only the first two is not conformant: one with no live listener at all, which meets both, fails 10 of the suite's cases. Catch-up is exclusive on since: it returns only messages newer than the cursor you pass, never re-sending it (ordering is the plugin's job; core never orders or parses a cursor, but it does compare two for byte equality as a no-progress brake, so a cursor naming a position has to be byte-stable across calls). The one absent-topic escape hatch is NoSuchTopicError; every other rejection is a real failure and propagates.
The two paths owe different things, and this is deliberate. fetchRecent is complete — every message above since comes back, page by page. subscribe is lossy: what it delivers is a subset of the post-subscribe tail, in cursor order, never twice, never anything from before the subscribe; what it leaves out is returned by the next fetchRecent. That is what keeps a backend from having to rebuild its transport's own gaps client-side — a Matrix burst wider than the 100 timeline events the plugin's own /sync filter asks for, or a SQLite row a peer commits during start-up, is left to catch-up rather than reconstructed by hand. A live path that delivers nothing is still non-conformant, and the shared suite grades both bounds.
Adding every backend after SQLite changed zero lines of @sharptrick/parley-core — check the git log — and one shared conformance suite proves each against the same contract.
Add a backend. Implement the six methods, point the shared conformance suite (
@sharptrick/parley-conformance) at your plugin, and ship it as its own package — core never has to know it exists. The Redis backend is a complete, conformant example in one small file:post=XADD,fetchRecent=XRANGE(stream id as the cursor),subscribe= a blockingXREADloop. Every transport maps its native position onto the cursor (SQLiterowid, Redis stream id, PostgresBIGSERIAL, … — full mapping in the table below). → packages/bridge-redis/src/index.ts
Backends
Ten backends — six live-tested against real implementations, four proven against in-process API fakes of the vendor protocol. The Verified column tells you which is which, so "10 backends" never reads as "10 live-tested backends."
This is what backend-agnostic MCP messaging buys: the same six-method seam gives you
agent-to-agent messaging over Matrix/NATS or plain SQLite, and moving between them changes a
binary and a backend_config block, not a line of participant code.
| Backend | Transport / mechanism | Cursor | Verified |
|---|---|---|---|
| SQLite | local file, polling-only (WAL, no broker) | rowid |
live |
| Redis | Redis Streams, blocking XREAD push |
stream id | live |
| Postgres | table + LISTEN / NOTIFY push |
BIGSERIAL |
live |
| Matrix | hand-rolled Client-Server HTTP + /sync |
event_id |
live |
| XMPP | MUC + MAM archive (server must enable MAM) | MAM id | live |
| NATS | JetStream (persistent streams) | stream sequence | live |
| Zulip | event-queue long-poll (raw fetch) |
message id | fake-conformance + operator-run |
| Discord | gateway websocket (raw ws) |
snowflake (Discord's time-sortable id) | fake-conformance |
| Slack | Socket Mode websocket (raw ws) |
ts |
fake-conformance |
| Telegram | Bot API getUpdates + local observed store |
local observation sequence, qualified by the store file (<id>.<seq>) |
fake-conformance |
live— exercised against real implementations in CI/dev: SQLite on a real on-disk file, real Redis/NATS binaries, live Synapse/Prosody homeservers, and Postgres 16 (SQLite, Redis, Matrix, NATS, XMPP, Postgres — 6 of 10).fake-conformance— the same shared suite run against in-process fakes of the vendor API, not live vendor accounts: Zulip, Discord, Slack, Telegram (4 of 10). Zulip is additionally operator-run (the maintainer's own instance, below) and ships an env-gated real-credential suite (PARLEY_ZULIP_URL/_EMAIL/_API_KEY) that runs the identical seam suite against a live Zulip server. Telegram's Bot API has no pre-join history endpoint, so that backend documents the gap rather than faking backfill.
Every backend clears the identical seam contract — cursor monotonicity, exclusive-since catch-up, subset-but-never-duplicated live push, and double-delivery dedup — plus multi-process write safety wherever the transport allows concurrent writers (Telegram is single-writer by design: one bridge per bot token, since a second getUpdates poller gets HTTP 409, so that one conformance case is deliberately skipped). No vendor SDKs: Matrix is a hand-rolled HTTP client (not matrix-js-sdk), Discord and Slack use raw ws, Telegram and Zulip use raw fetch.
The three MCP tools
Distinct from the six seam methods a backend implements, these are the 3 tools Claude actually calls:
parley_fetch_recent— catch a topic up from the durable backend.{topic, since?, limit?, block_ms?, from?}→{messages, nextCursor}.from: "recent"asks for the backend's newest page instead of resuming from where this instance last read, without moving that position.block_mslong-polls where the backend's own read primitive takes a wait, and is refused by name where it cannot — see Waiting for a reply below.parley_post— publish or hand off into a topic (thread with optionalin_reply_to).{topic, content, in_reply_to?}→{backendMsgId}.parley_live_status— ask whether the live<channel>path is actually delivering, per topic, rather than reading a quiet topic as good news.{}→ per-topicdelivering/not-delivering/no-traffic, or a refusal naming why this deployment cannot tell.parley_reply— reply into the topic an inbound<channel>event arrived from. Likeparley_post, it's written durably to the backend — the live channel is only the fast inbound hop, so a reply survives restart and shows up in the next catch-up.
Waiting for a reply (block_ms)
A session that hands off work usually wants the answer. Without help that means polling
parley_fetch_recent on a timer and burning a tool call per tick, most of them empty.
block_ms is on the schema everywhere, and served where the backend's own read primitive takes a
caller's wait — today Redis (XREAD BLOCK) and NATS (a JetStream pull expiry). There, pass it and
the call blocks server-side until a message newer than since arrives, or the budget expires —
whichever comes first:
{ "topic": "ctx-demo", "since": "<nextCursor from the last call>", "block_ms": 30000 }
It returns the moment a message lands, so the cost is one call per message rather than one
per interval. Keep block_ms comfortably under your client's tool timeout — a blocked call that
outlives the timeout looks like a hang. Core clamps it to catchup.block_max_ms (default 60s)
before it ever reaches a plugin, so a caller cannot exceed the server's own ceiling.
On the other eight — discord, telegram, matrix, slack, xmpp, postgres, zulip and sqlite — there
is no read primitive to park a budget on, so fetchRecent fails fast: it rejects with
BlockingFetchUnsupportedError naming the backend, and the tool hands that error back rather than a
page. That is the point of refusing rather than ignoring — an empty page is exactly what a long-poll
that timed out looks like, so an agent handed one goes on polling in the belief that it is parked.
Retry without block_ms and poll on your own cadence, or run under Claude Code with
live_push.enabled and be pushed a <channel> event as well — push is a latency shortcut over
catch-up, never a replacement for it. The
chat-hand-off skill shows both loops.
The refusal lives entirely in the plugin: the seam carries blockMs and nothing else, so a backend
that cannot serve a wait costs zero changes to any other package.
Configuration
Full reference in DESIGN.md §11. The knobs worth knowing before you run this against a real account:
| Key | Default | Why you'd touch it |
|---|---|---|
identity.handle |
(required) | This instance's logical name; what peers @mention. |
instance_id |
identity.handle |
Read-state namespace. Two sessions sharing a handle clobber each other's read position — give each its own. Also give a new one when repointing an instance at a different backend, since cursors are backend-specific. |
state_path |
$XDG_STATE_HOME/parley/<instance>/read-state.json |
Where that cursor file lives. Core writes three siblings beside it: .warmed (how far on-start catch-up has paged — a cache, always safe to delete), and a .corrupt copy of either file that could not be parsed. Each update also passes through a transient .<pid>.<uuid>.tmp file renamed into place; a process killed mid-write leaves one behind and nothing removes it. |
topics |
(required) | Subscribe + catch-up list. This is the allowlist. Capped at 64 topics: each one is an allowlist entry every post/fetch_recent is matched against, and — with live_push.enabled — a live subscription too. |
post_topics |
[] |
Extra topics allowed for post/fetch only, as anchored regexes. Never subscribed or caught up on. Patterns are screened for catastrophic backtracking at load, capped at 64 patterns (every post/fetch matches its topic against all of them), and matched only against topics of at most 64 characters — a longer topic must be listed in topics. |
catchup.on_start |
true |
At startup, read forward to the topic's live boundary and mark those ids seen, so the live push cannot re-deliver them. Nothing is emitted and nothing is consumed: your read position does not move, and parley_fetch_recent still owes you every message it has not handed you. The driver keeps its own marker beside the read-state file, so a restart costs a page for what arrived rather than a re-read of the backlog. |
catchup.limit |
100 |
Page size per fetchRecent. |
catchup.block_max_ms |
60000 |
Server-side ceiling on block_ms (above). 0 is a load error, not "disabled": every caller's block_ms is clamped to this before it reaches a plugin, so a ceiling of 0 would mean no backend is ever handed a budget and none can refuse one. To turn the long poll off, stop sending block_ms. |
catchup.block_poll_interval_ms |
250 |
How often core re-drives fetchRecent after a plugin has come back from a budget early and with nothing for the topic asked for — a page of somebody else's traffic on a backend whose delivery is coarser than a topic, or a native blocker cut short. It does not set the delivery latency while a plugin is parked: Redis and NATS spend the budget inside a single fetchRecent. Measured on both, a message posted 400 ms into an 8 s budget arrived at 402 ms and an idle 1 200 ms budget returned at ~1 205 ms — identical at a cadence of 250 ms and of 5 000 ms. They do not always stay parked, though: Redis returns early on a disconnect inside the budget, on a caught reader failure, and for a caller past its concurrent-reader cap, and this cadence is what honours the rest of that budget. The other eight backends refuse block_ms outright, so their long poll never starts. |
live_push.enabled |
false |
Claude Code only — push <channel> events into a running session. |
live_push.mention_filter |
false |
true = only surface messages that mention your handle. Only the live push path reads it, so true with live_push.enabled: false is a load error rather than a filter that never runs. Requires a handle an @mention can name (ASCII letters/digits, optional interior . - _); anything else is a load error rather than a bridge that silently receives nothing. |
backend_config |
{} |
Opaque to core, passed verbatim to the plugin. Secrets live here — never committed. |
There is no backend key: the backend is whichever parley-<name> binary you run. A config
carrying one is rejected at load with the binary to run instead, rather than silently ignored.
Every other key outside backend_config is checked too: an unrecognised one (live_push: enable:,
presense:) is a load error naming it, not a silently dropped line that leaves you with a bridge
quietly doing nothing. backend_config stays open — it is opaque to core.
Remote / chat mode
The same codebase runs as a public HTTP MCP server so a Claude chat connector can reach it directly — the mechanism behind Quickstart B. It sits behind a standards-compliant built-in OAuth 2.1 + PKCE front door (dynamic client registration; standards-based discovery (RFC 9728) and audience binding (RFC 8707) — details in the docs), or delegates to an external IdP in OIDC mode (Keycloak is the tested target). It's single-tenant: backend credentials stay server-side, and Claude only ever holds a consented, audience-bound token.
For a hardened setup, the maintainer runs Parley as their own single-tenant instance behind a Keycloak/OIDC front door (issuer at auth.example.com) fronting a self-hosted Zulip backend (zulip.example.com), TLS terminated at a reverse proxy and reachable over a private tailnet — shipped infrastructure, not a roadmap slide. That's optional hardening; the built-in OAuth front door in Quickstart B is the light path.
Security posture: secrets live in backend_config / .env, never in core and never committed. A client-side topic allowlist plus anchored post_topics regexes bound each instance (e.g. general + project-.*). Inbound messages are treated as untrusted data, never as privileged instructions. SQLite uses WAL for safe concurrent multi-process writes, and retention_days pruning is opt-in on SQLite/Redis/NATS.
How it compares
- vs. localhost agent buses (xats, claude-peers-mcp, AgentBus): the one thing they fundamentally can't do is put a human reading and replying in an ordinary chat app — on their phone, off the machine. Those buses are localhost-only and agents-only. Parley is the same primitives — topics, durable history,
claude/channelpush — but off one machine and carrying a human plus a Claude chat too. Should you switch from xats today? Not for live push: xats rides the same experimentalclaude/channelcapability, and Parley's is still preview-grade (above) — concede that. Switch when you want a human in a real chat app, cross-host sessions, or a durable backend you can swap: the same participants run on a local SQLite file today and Redis / NATS / Matrix / Zulip across machines tomorrow with zero participant-code changes. - vs. a plain MCP server: Parley is dual-role. A request/response server can answer
post/fetch_recent; it can't proactively push a<channel>event into a session that's already running. Parley does both (the push half is the research preview above). - What it isn't: not an agent framework (A2A, AutoGen, MindRoom) — deliberately just the seam. No built-in chat UI.
Project status & maintenance
- Single maintainer, MIT, no hosted service. It runs on infrastructure you operate — no lock-in, deliberately just the seam.
- Pre-1.0, actively developed. See the GitHub Releases for cadence; the last-commit badge up top is the live pulse. Per project convention, early breaking changes land as
feat:until 1.0 is deliberately cut. - The one risk to price in. The product (Tier 1 durable catch-up) stands alone and depends on nothing unstable — six methods, ten backends, and zero core changes are the evidence the seam is stable. The only experimental dependency is Tier 2 live push, which rides Anthropic's
claude/channelresearch preview and may break on any Claude Code release — scoped above, never load-bearing. - Releases are automated. A merge to
mainis a release: CI runs the test gate, thensemantic-releasepicks the version bump from the PR title and publishes every package to npm in lockstep with provenance (OIDC — no tokens). See CONTRIBUTING.md. - Contributing. Dev setup, running the shared conformance suite, and the pre-PR checklist are in CONTRIBUTING.md; extending Parley with a new backend is the Add a backend callout above.
- Support: open a GitHub issue; report vulnerabilities via SECURITY.md.
Docs & license
- DESIGN.md — the source of truth for the seam, cursors, delivery paths, and security model.
- docs/CONVENTIONS.md — catch-up-on-start and the hand-off conventions.
- docs/keycloak-integration.md — OIDC / Keycloak remote-mode setup.
- docs/1.0-readiness.md — the evidence for cutting 1.0, what it would and wouldn't promise, and the per-backend verification matrix.
- skills/chat-handoff/SKILL.md — the chat-handoff skill (the full, runnable chat→code walkthrough).
- docs/REVIEW_PROTOCOL.md — the adversarial review protocol (ten lenses, computed convergence), and docs/findings/critical-review/ — what we've measured about the review process itself.
- examples/fakechat-loopback/MANUAL-CHECKLIST.md — the headless live-push loopback and its manual checklist.
- examples/self-host-remote/README.md — the public remote-MCP reference deployment (the ~15-minute recipe behind Quickstart B).
- examples/dev-compose/docker-compose.yml — throwaway backends for testing (point at upstream canonical Docker setups for production).
- Per-backend details live in each packages/*/README.md.
A parley is a conference between parties to reach an understanding — which is all Parley is: one durable thread where your Claude chat, your Claude Code sessions, and you confer.
MIT licensed.
Install Parley Sqlite in Claude Desktop, Claude Code & Cursor
unyly install parley-sqliteInstalls into Claude Desktop, Claude Code, Cursor & VS Code — handles npx, uvx and build-from-source repos for you.
First time? Get the CLI: curl -fsSL https://unyly.org/install | sh
Or configure manually
Run in your terminal:
claude mcp add parley-sqlite -- npx -y @sharptrick/parley-sqliteStep-by-step: how to install Parley Sqlite
FAQ
Is Parley Sqlite MCP free?
Yes, Parley Sqlite MCP is free — one-click install via Unyly at no cost.
Does Parley Sqlite need an API key?
No, Parley Sqlite runs without API keys or environment variables.
Is Parley Sqlite hosted or self-hosted?
Self-hosted: the server runs locally on your machine via the install command above.
How do I install Parley Sqlite in Claude Desktop, Claude Code or Cursor?
Open Parley Sqlite on unyly.org, pick your client tab (Claude Desktop, Claude Code, Cursor) and press Install — the config is generated automatically, no JSON editing.
Changes
Versions and requested access over time.
- New version published
- New version published
- New version published
- New version published
- New version published
- New version published
- New version published
- New version published
Related MCPs
Gmail
Read, send and search emails from Claude
by GoogleSlack
Send, search and summarize Slack messages
by SlackRunbear
No-code MCP client for team chat platforms, such as Slack, Microsoft Teams, and Discord.
Discord Server
A community discord server dedicated to MCP by [Frank Fiegel](https://github.com/punkpeye)
Klavis AI
Open Source MCP Infra. Hosted MCP servers and MCP clients on Slack and Discord.
Work90210/APIFold
Turn any REST API into a hosted MCP server, with ready-made public servers for GitHub, Stripe, Slack, OpenAI, Notion and more.
by Work90210arikusi/deepseek-mcp-server
DeepSeek AI chat and reasoning with multi-turn sessions, function calling, thinking mode and cost tracking.
by arikusihashgraph-online/hashnet-mcp-js
Discover, register and chat with AI agents on the Hashgraph network via the Registry Broker.
by hashgraph-onlineprofullstack/mcp-server
Developer utilities: SEO optimization, document conversion, domain lookup, email validation, QR codes, weather data, social media posting and security scanning.
by profullstackWayStation-ai/mcp
Connect MCP hosts to apps such as Notion, Slack, Monday and Airtable.
by waystation-aiCompare Parley Sqlite with
Not sure what to pick?
Find your stack in 60 seconds
Author?
Embed badge for your README
Browse similar
All communication MCPs
