Per-app SDKs
Each ENC Protocol app ships as a typed JavaScript SDK at @enc-protocol/<app>-cli. Each exports a class extending AppSdk (from @enc-protocol/cli-sdk-base) with method-per-action / method-per-read:
import { HelloSdk } from '@enc-protocol/hello-cli'
const sdk = new HelloSdk({ mode: 'cf', nodeUrl: process.env.NODE_URL })
await sdk.init()
await sdk.submitMessages({ draft: 'hi' }) // → Hello.post (via tableMap)
const events = await sdk.queryMessages()Install
echo "@enc-protocol:registry=https://npm-registry.ocrybit.workers.dev/" >> .npmrc
npm install @enc-protocol/<app>-cliConstructor
new <App>Sdk(opts: {
mode: 'mem' | 'cf'
identity?: Identity // required for cf mode
nodeUrl?: string // cf mode (or set NODE_URL env)
repoRoot?: string // path to find apps/<id>/ + enclaves/
encHome?: string // state directory (defaults to ~/.enc)
forceReadable?: boolean // test-only Public-R escape (cf)
})Then:
await sdk.init() // loads app definition, registers all enclaves, wires dataviewEncryption hook
Apps with schema.encrypt (DM, Wallet) have _encrypt(dataType, args) called before each submit. Default is pass-through; subclass to add real encryption:
class EncryptedDm extends DmSdk {
async _encrypt(dataType, args) {
return { ciphertext: await mlsEncrypt(args) }
}
}Per-app reference
hello
@enc-protocol/hello-cli — enclaves: Hello.
import { HelloSdk } from '@enc-protocol/hello-cli'
await sdk.submitMessages({ draft: 'hello' }) // → Hello.post
const events = await sdk.queryMessages()dm
@enc-protocol/dm-cli — enclaves: DM, Personal, Registry. Encrypted: messages, invites.
import { DmSdk } from '@enc-protocol/dm-cli'
await sdk.submitMessages({ message_draft: 'hi' }) // → DM.message (encrypted)
await sdk.deleteInvites({}) // → DM.invite
const profiles = await sdk.queryProfiles() // → cross_enclave dataview
const invites = await sdk.queryInvites()
const messages = await sdk.queryMessages()group
@enc-protocol/group-cli — enclaves: Group, Personal. Encrypted: messages.
personal
@enc-protocol/personal-cli — enclaves: Personal, Group. Encrypted: private.
await sdk.submitPublic({ draft: '...' }) // → Personal.public
await sdk.submitPrivate({ draft: '...' }) // → Personal.private (encrypted)
const notices = await sdk.queryNotices() // → cross_enclave (Group.notice)registry
@enc-protocol/registry-cli — enclaves: Registry. Pure read-only at the app level (writes happen at the enclave level via the registry's customs).
timeline
@enc-protocol/timeline-cli — enclaves: Timeline, Personal. Encrypted: none.
super
@enc-protocol/super-cli — multi-enclave composition. Enclaves: DM, Group, Personal.
import { SuperSdk } from '@enc-protocol/super-cli'
await sdk.submitMessages({ message_draft: 'hi' }) // → DM.message
await sdk.submitMoments({ moment_draft: 'wow' }) // → Personal.public
const profiles = await sdk.queryProfiles() // → cross_enclave dataviewwallet
@enc-protocol/wallet-cli — multi-enclave + external chain. Enclaves: DM, Personal, Registry. Encrypted: messages.
appstore
@enc-protocol/appstore-cli — host app. Bundles all 6 enclaves; no own write commands. Use bundled-enclave SDKs directly.
node
@enc-protocol/node-cli — host app. Same shape as appstore.
Multi-enclave routing
For apps like super (3 enclaves), each submit<DataType>(args) resolves to the correct enclave via the schema's tableMap:
super.submitMessages({...})
→ tableMap.messages = "message"
→ "message" is declared in DM's customs
→ routes to DM.messageResolution happens at runtime in AppSdk._resolve(name). Both data_types AND raw enclave event names are accepted — useful for backward-compat with enclave-shaped workflows.
Dataview (cross_enclave reads)
cross_enclave: true reads (e.g. super.profiles, dm.profiles) are served by DataView. It captures matching submits on the source enclave (per apps/<id>/infra.json's cross_enclave_reads) and serves rows on query — in-memory, Map-based UPSERT for Shared(<key>) slots and registry snapshots.
Production dataview (CF Durable Object + SQLite) lives in impl-emulator/dataview-workers/. The mem-mode dataview in @enc-protocol/cli-sdk-base mirrors its semantics without SQLite — sufficient for local development, testing, and most CLI use.
See also
- Apps overview
- Claude Code skills — agent-friendly install
@enc-protocol/cli-sdk-base—AppSdk,AppClient,DataViewreference