
Security News
/Research
Fake Corepack Site Distributes Infostealer and Proxyware to Developers
A fake corepack.org site is impersonating the Node.js tool and delivers an infostealer and proxyware to developers who download it.
@getremoteapp/wire
Advanced tools
Shared message wire types and Zod schemas for Remote clients and services
Canonical wire specification package for Remote clients and services.
This package defines shared wire contracts as TypeScript types + Zod schemas. It is intentionally small and focused on protocol-level data only.
Both legacy and new formats are transported inside encrypted session messages.
Legacy format examples (decrypted payload):
{
"role": "user",
"content": {
"type": "text",
"text": "fix the failing test"
},
"meta": {
"sentFrom": "mobile"
}
}
{
"role": "agent",
"content": {
"type": "output",
"data": {
"type": "message",
"message": "I found the issue in api/session.ts"
}
},
"meta": {
"sentFrom": "cli"
}
}
New session protocol format example (decrypted payload):
{
"role": "session",
"content": {
"id": "msg_01",
"time": 1739347230000,
"role": "agent",
"turn": "turn_01",
"ev": {
"t": "text",
"text": "I found the issue in api/session.ts"
}
},
"meta": {
"sentFrom": "cli"
}
}
Modern session protocol user envelope (decrypted payload):
{
"role": "session",
"content": {
"id": "msg_legacy_user_01",
"time": 1739347231000,
"role": "user",
"ev": {
"t": "text",
"text": "fix the failing test"
}
},
"meta": {
"sentFrom": "cli"
}
}
Protocol invariant:
role = "session" marks modern session-protocol payloads.content, envelope role is only "user" or "agent".Session protocol send rollout (ENABLE_SESSION_PROTOCOL_SEND):
role = "session" with content.role = "user").role = "user", content.type = "text") and drops modern user payloads.1, true, yes (case-insensitive).Wire-level encrypted container (same for legacy and new):
{
"id": "msg-db-row-id",
"seq": 101,
"localId": null,
"content": {
"t": "encrypted",
"c": "BASE64_ENCRYPTED_PAYLOAD"
},
"createdAt": 1739347230000,
"updatedAt": 1739347230000
}
@getremoteapp/wire centralizes definitions for:
The goal is to keep CLI/app/server/agent on the same wire contract and avoid schema drift.
@getremoteapp/wirepackages/remote-wiresrc/index.tszod, @paralleldrive/cuid2src/index.ts exports everything from:
src/messages.tssrc/legacyProtocol.tssrc/sessionProtocol.tsmessages.ts exportsSchemas + inferred types:
SessionMessageContentSchemaSessionMessageSessionMessageSchemaMessageMetaSchemaMessageMetaSessionProtocolMessageSchemaSessionProtocolMessageMessageContentSchemaMessageContentVersionedEncryptedValueSchemaVersionedEncryptedValueVersionedNullableEncryptedValueSchemaVersionedNullableEncryptedValueUpdateNewMessageBodySchemaUpdateNewMessageBodyUpdateSessionBodySchemaUpdateSessionBodyVersionedMachineEncryptedValueSchemaVersionedMachineEncryptedValueUpdateMachineBodySchemaUpdateMachineBodyCoreUpdateBodySchemaCoreUpdateBodyCoreUpdateContainerSchemaCoreUpdateContainerCompatibility aliases:
ApiMessageSchema -> SessionMessageSchemaApiMessage -> SessionMessageApiUpdateNewMessageSchema -> UpdateNewMessageBodySchemaApiUpdateNewMessage -> UpdateNewMessageBodyApiUpdateSessionStateSchema -> UpdateSessionBodySchemaApiUpdateSessionState -> UpdateSessionBodyApiUpdateMachineStateSchema -> UpdateMachineBodySchemaApiUpdateMachineState -> UpdateMachineBodyUpdateBodySchema -> UpdateNewMessageBodySchemaUpdateBody -> UpdateNewMessageBodyUpdateSchema -> CoreUpdateContainerSchemaUpdate -> CoreUpdateContainerlegacyProtocol.ts exportsSchemas + inferred types:
UserMessageSchemaUserMessageAgentMessageSchemaAgentMessageLegacyMessageContentSchemaLegacyMessageContentsessionProtocol.ts exportsSchemas + inferred types:
sessionRoleSchemaSessionRolesessionTextEventSchemasessionServiceMessageEventSchemasessionToolCallStartEventSchemasessionToolCallEndEventSchemasessionFileEventSchemasessionTurnStartEventSchemasessionStartEventSchemasessionTurnEndStatusSchemaSessionTurnEndStatussessionTurnEndEventSchemasessionStopEventSchemasessionEventSchemaSessionEventsessionEnvelopeSchemaSessionEnvelopeCreateEnvelopeOptionscreateEnvelope(...)These are schema-level requirements, not just recommendations.
id, sid, machineId, call, name, title, description, ref: stringseq, createdAt, updatedAt, size, width, height, version, activeAt: number.nullable()..optional()..nullish() means undefined | null | <type>.messages.ts)SessionMessageContentSchema{
t: 'encrypted';
c: string;
}
Meaning:
t is a strict discriminator with value 'encrypted'.c is encrypted payload bytes encoded as a string (typically base64 in current usage).SessionMessageSchema{
id: string;
seq: number;
localId?: string | null;
content: SessionMessageContent;
createdAt: number;
updatedAt: number;
}
Notes:
localId is .nullish() for compatibility with different producers.createdAt and updatedAt are required in this shared schema.MessageMetaSchema{
sentFrom?: string;
permissionMode?: 'default' | 'acceptEdits' | 'bypassPermissions' | 'plan' | 'read-only' | 'safe-yolo' | 'yolo';
model?: string | null;
fallbackModel?: string | null;
customSystemPrompt?: string | null;
appendSystemPrompt?: string | null;
allowedTools?: string[] | null;
disallowedTools?: string[] | null;
displayText?: string;
}
legacyProtocol.ts)UserMessageSchema (legacy decrypted payload){
role: 'user';
content: {
type: 'text';
text: string;
};
localKey?: string;
meta?: MessageMeta;
}
AgentMessageSchema (legacy decrypted payload){
role: 'agent';
content: {
type: string;
[key: string]: unknown;
};
meta?: MessageMeta;
}
LegacyMessageContentSchemaDiscriminated union on role:
'user' -> UserMessageSchema'agent' -> AgentMessageSchemamessages.ts)SessionProtocolMessageSchema (modern decrypted payload wrapper){
role: 'session';
content: SessionEnvelope;
meta?: MessageMeta;
}
MessageContentSchemaDiscriminated union on top-level role:
'user' -> UserMessageSchema (legacy)'agent' -> AgentMessageSchema (legacy)'session' -> SessionProtocolMessageSchema (modern)messages.ts) ContinuedVersionedEncryptedValueSchema{
version: number;
value: string;
}
Used for encrypted, version-tracked blobs that cannot be null when present.
VersionedNullableEncryptedValueSchema{
version: number;
value: string | null;
}
Used where payload presence can be intentionally reset to null while still versioning.
VersionedMachineEncryptedValueSchema{
version: number;
value: string;
}
Machine update variant. Equivalent shape to VersionedEncryptedValueSchema.
UpdateNewMessageBodySchema{
t: 'new-message';
sid: string;
message: SessionMessage;
}
UpdateSessionBodySchema{
t: 'update-session';
id: string;
metadata?: VersionedEncryptedValue | null;
agentState?: VersionedNullableEncryptedValue | null;
}
Important distinction:
metadata.value is string when metadata block exists.agentState.value may be string or null when block exists.UpdateMachineBodySchema{
t: 'update-machine';
machineId: string;
metadata?: VersionedMachineEncryptedValue | null;
daemonState?: VersionedMachineEncryptedValue | null;
active?: boolean;
activeAt?: number;
}
CoreUpdateBodySchemaDiscriminated union on t with exactly 3 variants:
'new-message''update-session''update-machine'CoreUpdateContainerSchema{
id: string;
seq: number;
body: CoreUpdateBody;
createdAt: number;
}
sessionProtocol.ts)sessionRoleSchema'user' | 'agent'
Role meaning:
'user': user-originated envelope.'agent': agent-originated envelope.sessionEventSchema is a discriminated union on t with 9 variants.
{
t: 'text';
text: string;
thinking?: boolean;
}
{
t: 'service';
text: string;
}
{
t: 'tool-call-start';
call: string;
name: string;
title: string;
description: string;
args: Record<string, unknown>;
}
{
t: 'tool-call-end';
call: string;
}
{
t: 'file';
ref: string;
name: string;
size: number;
image?: {
width: number;
height: number;
thumbhash: string;
};
}
{
t: 'turn-start';
}
{
t: 'start';
title?: string;
}
{
t: 'turn-end';
status: 'completed' | 'failed' | 'cancelled';
}
{
t: 'stop';
}
sessionEnvelopeSchema{
id: string;
time: number;
role: 'user' | 'agent';
turn?: string;
subagent?: string; // must pass cuid2 validation when present
ev: SessionEvent;
}
Additional validation (superRefine):
ev.t === 'service', then role MUST be 'agent'.ev.t === 'start' or ev.t === 'stop', then role MUST be 'agent'.subagent is present, it MUST satisfy isCuid(...).createEnvelope(role, ev, opts?)Input:
role: SessionRoleev: SessionEventopts?: { id?: string; time?: number; turn?: string; subagent?: string }Behavior:
opts.id is absent, generates id using createId().opts.time is absent, sets time to Date.now().turn only when provided.subagent only when provided.Output:
SessionEnvelope parsed by sessionEnvelopeSchema.role = 'user' with ev.t = 'service').new-message{
"id": "upd-1",
"seq": 100,
"createdAt": 1739347200000,
"body": {
"t": "new-message",
"sid": "session-1",
"message": {
"id": "msg-1",
"seq": 55,
"localId": null,
"content": {
"t": "encrypted",
"c": "Zm9v"
},
"createdAt": 1739347199000,
"updatedAt": 1739347199000
}
}
}
new-message content examplemessage.content.c (ciphertext) decrypts into the payload below for a session-protocol message:
{
"role": "session",
"content": {
"id": "env_01",
"time": 1739347232000,
"role": "agent",
"turn": "turn_01",
"ev": {
"t": "text",
"text": "I found 3 TODOs."
}
},
"meta": {
"sentFrom": "cli"
}
}
For user text migration behavior:
role = "session" with content.role = "user").ENABLE_SESSION_PROTOCOL_SEND is disabled, app keeps consuming legacy payloads and drops modern payloads.ENABLE_SESSION_PROTOCOL_SEND is enabled, app consumes modern payloads and drops legacy payloads.update-session{
"id": "upd-2",
"seq": 101,
"createdAt": 1739347210000,
"body": {
"t": "update-session",
"id": "session-1",
"metadata": {
"version": 8,
"value": "BASE64..."
},
"agentState": {
"version": 13,
"value": null
}
}
}
update-machine{
"id": "upd-3",
"seq": 102,
"createdAt": 1739347220000,
"body": {
"t": "update-machine",
"machineId": "machine-1",
"metadata": {
"version": 2,
"value": "BASE64..."
},
"daemonState": {
"version": 3,
"value": "BASE64..."
},
"active": true,
"activeAt": 1739347220000
}
}
{
"id": "x8s1k2...",
"role": "agent",
"turn": "turn-42",
"ev": {
"t": "turn-start"
}
}
import {
CoreUpdateContainerSchema,
sessionEnvelopeSchema,
} from '@getremoteapp/wire';
const maybeUpdate = CoreUpdateContainerSchema.safeParse(input);
if (!maybeUpdate.success) {
// invalid update payload
}
const maybeEnvelope = sessionEnvelopeSchema.safeParse(envelopeInput);
if (!maybeEnvelope.success) {
// invalid envelope/event payload
}
package.json contract:
main: ./dist/index.cjsmodule: ./dist/index.mjstypes: ./dist/index.d.ctsexports["."] provides both CJS and ESM entrypoints with type paths.Build script:
shx rm -rf dist && npx tsc --noEmit && pkgrollTests:
vitest against src/*.test.tsPublish gate:
prepublishOnly runs build + testPublished files:
distpackage.jsonREADME.mdIn this repository, consumer workspaces import @getremoteapp/wire through package exports that point at dist/*.
That means on a clean checkout:
yarn workspace @getremoteapp/wire buildAfter publishing to npm, dependents consume prebuilt artifacts from the published tarball.
When modifying wire schemas:
t) as protocol-level API and avoid breaking renames.# from repository root
yarn workspace @getremoteapp/wire build
yarn workspace @getremoteapp/wire test
# interactive release target selection from repo root
yarn release
# direct release invocation
yarn workspace @getremoteapp/wire release
This prepares release artifacts using the same release-it flow as other publishable libraries in the monorepo.
FAQs
Shared message wire types and Zod schemas for Remote clients and services
The npm package @getremoteapp/wire receives a total of 2 weekly downloads. As such, @getremoteapp/wire popularity was classified as not popular.
We found that @getremoteapp/wire demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Security News
/Research
A fake corepack.org site is impersonating the Node.js tool and delivers an infostealer and proxyware to developers who download it.

Research
/Security News
A large-scale campaign abused GitHub Actions in compromised repositories to exploit CVE-2026-41940 in cPanel and WHM and steal server credentials.

Security News
Five frontier LLMs generated the same nonexistent package names, leaving 53 available for potential slopsquatting across PyPI and npm.