RememberStackremember.dev/docs

TypeScript SDK

@rememberdev/client is the asynchronous Node.js memory client. It stores and searches documents, queries facts and sources, reads graphs, checks pipeline readiness, and includes methods for optional deployment-side connector configuration. It supports Node.js 22 or newer, ESM and CommonJS. Use it in an application backend.

Build and install

The package is available as source in the RememberStack repository. It has not been published to npm. Build a local tarball:

git clone https://github.com/writeitai/remember-stack.git
cd remember-stack
uv sync --group dev
cd packages/typescript-client
npm ci
npm run build
npm pack

In your application, install the actual tarball that command produces:

npm install /absolute/path/rememberdev-client-0.1.0.tgz

TypeScript consumers need their usual Node types installed (@types/node). The tarball exports the client and its types from @rememberdev/client; it has no command-line executable or MCP server.

Connecting

import { Client } from '@rememberdev/client';
 
const client = new Client({
  apiKey: process.env.REMEMBER_API_KEY,
  baseUrl: 'http://127.0.0.1:8000',
  timeoutMs: 30_000,
});
try {
  const info = await client.deploymentBuildInfo();
  const receipt = await client.ingestFile({
    filePath: '/sources/note.md',
    sourceKind: 'feeder',
    sourceRef: 'sources/note',
  });
  await client.waitForReadiness({ versionIds: [receipt.version_id] });
  const result = await client.factsContext({ query: 'What changed?' });
  console.log(info.build_revision, result.grain);
} finally {
  client.close();
}

Client, MemoryClient, and the RememberClient alias share the memory methods. Client.fromEnv(overrides) uses the ordinary constructor's precedence; Client.ingestFile is a file-path convenience, and client.account exposes get and whoami for a signed key's issuer account API. Account access fails explicitly when that issuer does not advertise an account endpoint.

Explicit apiKey, baseUrl, and project take precedence over REMEMBER_API_KEY, REMEMBER_API_URL and REMEMBER_PROJECT, then the existing version-2 credential file. resolveConnection additionally accepts issuer and mcpUrl with REMEMBER_ISSUER/REMEMBER_MCP_URL precedence. Empty environment connection values are unset. Empty configuration-directory values retain Python's current-directory behavior. Bare keys and Bearer-prefixed keys are accepted.

Signed-key claims are decoded for routing only; the server verifies signatures. The issuer supplies secure metadata and a covered project's engine URL. The first project id stays pinned while deployment mappings refresh after ten minutes or apparent movement. Without a signed key or configured URL, the self-hosted default is http://127.0.0.1:8000.

The shared file is REMEMBER_CONFIG_DIR/credentials.json, otherwise XDG_CONFIG_HOME/remember/credentials.json, otherwise ~/.config/remember/credentials.json. Only required precedence fallthrough reads it. Explicit key and URL settings bypass a stale file. POSIX reads refuse symlinks, nonregular files and files readable by other users; Windows refuses automatic file reads. A file-loaded key is sent only to its recorded, issuer or resolved deployment origin. SecretString, StoredCredentials and Connection redact credential display; getSecretValue() and connection.authorization deliberately access a secret.

Connector-management methods require an engine composition that serves those optional routes. None of the released or candidate profiles checked by this PR serves them; calling them there returns an explicit unsupported HTTP error.

Method reference

Every method takes one named options object and returns a Promise. Optional signal is an AbortSignal. Top-level names are camelCase; nested model fields and result fields retain the API's snake_case. The Python return names below identify the corresponding model contracts; TypeScript results are ordinary objects and arrays, with validated defaults.

MethodCorresponding result
listOperationstuple[ToolDescriptor, ...]
runOperationEnvelope | ContextBundleV2
querySqldict[str, object]
openQueryQueryResultDict
explainQueryQueryResultDict
factsContextEnvelope
combinedContextContextBundleV2
claimsAndSourcesContextEnvelope
resolveEntityEnvelope
explainSqldict[str, object]
describeQuerySpacedict[str, object]
searchQuerySpacelist[dict[str, object]]
listSavedQuerieslist[dict[str, object]]
describeSavedQuerydict[str, object]
runSavedQuerydict[str, object]
callOpenQueryobject
resolveEnvelope
lookupRelationsEnvelope
transcriptRelationEnvelope
lookupObservationsEnvelope
searchClaimsEnvelope
searchChunksEnvelope
adjacentChunksEnvelope
hydrateRelationEnvelope
graphNeighborhoodEnvelope
graphPathEnvelope
graphCitationPathEnvelope
deploymentBuildInfoDeploymentBuildInfo
processingLayersProcessingLayerStates
pipelineReadinessPipelineReadinessReport
waitForReadinessPipelineReadinessReport
ingestIngestedVersion
listDocumentsDocumentPage
searchDocumentsDocumentSearchPage
searchDocumentsRequestDocumentSearchPage
sectionHistory, sectionHistoryRequestSectionHistoryPage
documentReferences, documentReferencesRequestDocumentReferencesPage
setReferencesReferencesSet
referenceGenerationsReferenceGenerations
setEffectivePeriodsEffectivePeriodsSet
clearEffectiveTimeEffectiveTimeCleared
deleteDocumentDocumentDeletion
connectorstuple[ConnectorDescriptor, ...]
addConnectorConnectorDescriptor
pauseConnectorConnectorDescriptor
connectorStatusConnectorDescriptor

close() cancels this client's operations and closes SDK-owned resources. Synchronous and asynchronous disposal are supported. An injected caller-owned transport is never closed by the SDK.

The complete schema-derived model and support-type vocabulary is:

AdjacentChunksRequest, AggregateBucket, AggregateReport, AsOfTemporalScope, AtTemporalScope, CapabilityReadiness, ChangeRecord, ChunkEvidenceResult, ClaimValidPrecision, CoMember, ConnectorCreate, ConnectorDescriptor, ContextBundleV2, Contradiction, CurrentTemporalScope, DeploymentBuildInfo, DeviceAuthorization, DiscoveryHit, DocumentDeletion, DocumentPage, DocumentPeopleMatch, DocumentSearchFilters, DocumentSearchPage, DocumentSearchPerson, DocumentSearchRequest, DocumentSearchResult, DocumentStatusFilter, DocumentSummary, DocumentVersionSummary, EntityCandidate, Envelope, EvidenceResult, EvidenceSpan, EvidenceTotal, FactEvidence, FactResult, FactSupport, Freshness, Grain, GraphEdge, GraphInvocation, GraphNode, GraphPath, HistoryTemporalScope, IdentityRegime, IngestedVersion, IssuedKey, IssuerMetadata, JsonValue, KFreshness, KeyClaims, Negative, NegativeKind, OverlapTemporalScope, PageRef, PendingRevocation, PendingRevocations, PipelineReadinessReport, PipelineStageReadiness, ProcessingLayer, ProcessingLayerStates, QueryErrorCode, QueryResult, RankedItem, ReadinessRequirements, ResolvedProject, ResultColumn, ResultLimits, SavedQuerySummary, ScanRow, SearchRequest, SemanticInvocation, SourceRecord, StoredCredentials, TemporalMatch, TokenResponse, ToolDescriptor, TranscriptEntry, Truncation, Validity, VersionPipelineReadiness. Schema-owned public models have Input variants for inputs; connection and issuer types expose the SDK support contracts. CLI credential-response types are data contracts only and do not add login or key-writing operations to this package.

Ingest and readiness

ingest accepts content: Uint8Array, or source as bytes or a file path. Bytes require filename. File MIME is inferred from the real path before a filename override; explicit mime wins. Lineage sourceKind/sourceRef must be supplied together. sourceModifiedAt, sourceVersionRef and living mode require that pair; sourcePath records upstream location metadata. versionKey is the immutable caller name for an edition. effectiveFrom and optional effectiveUntil declare a half-open UTC period and require a snapshot lineage; use setEffectivePeriods to replace declarations or clearEffectiveTime to leave declared effective time. An empty period set retracts that version's periods while retaining the document's declared effective-time mode.

Readiness polling starts immediately, including after created: false receipts. Defaults are timeoutMs: 1_800_000, pollIntervalMs: 15_000, and requireP3: false. A failed stage has a retry pending; polling continues. A dead_letter stage stops with PipelineDeadLettered and the full report. The readiness deadline covers routing, HTTP and polling waits, retaining the last validated report.

Version history and references

searchClaims, searchChunks, searchDocuments and claimsAndSourcesContext accept a time scope. A time-scoped claims/chunks search uses POST; the ordinary unfiltered search retains GET. Nested scopes use the engine's wire names: { mode: 'at', at: '2026-01-01T00:00:00Z' } or { mode: 'overlap', from: '2026-01-01T00:00:00Z', to: '2026-07-01T00:00:00Z' }. ReadTime instants retain explicit offsets; ingest effective times require UTC.

sectionHistory({ docId, sectionKey }) defaults to the complete history scope. documentReferences accepts exactly one chunkId or docId, with sectionKey only for a document. Prepared request variants accept snake_case DTO fields. setReferences({ docId, versionId, references }) replaces the complete supplied reference set as NDJSON; an empty array clears it. referenceGenerations reads its pending/active/rejected/superseded status. None of these writes is replayed.

Results and validation

Response types such as Envelope, ContextBundleV2, IngestedVersion, DocumentSearchPage and PipelineReadinessReport have all defaulted properties filled. Schema-owned input types use the Input suffix, such as DocumentSearchFiltersInput and ConnectorCreateInput. QueryResultDict is an ordinary object with .rows, .columns and .truncated properties. JsonValue describes JSON values recursively.

The additional version/history/reference models are exported with their matching Input types:

AreaModels
Time scopesReadTime, CurrentReadTime, AtReadTime, OverlapReadTime, HistoryReadTime
Effective periodsEffectivePeriodInput, EffectivePeriodsRequest, DeclaredEffectivePeriod, EffectiveInterval, EffectivePeriodsSet, EffectiveTimeCleared
Document/claim occurrencesMatchingEdition, ScopePending, ClaimOccurrence
Section historySectionHistoryRequest, SectionHistoryPage, SectionHistoryRow, SectionHistorySection, SectionAmendment
Reference inputsReferenceInput, ReferenceTarget, ReferenceKind
Reference generationsReferencesSet, ReferenceGenerations, ReferenceGeneration, ReferenceItemError
Reference readsDocumentReferencesRequest, DocumentReferencesPage, DocumentReference, DocumentReferenceSource, DocumentReferenceTarget, NamedReferenceTarget, ReferenceWindow, DocumentReferencesTooBroad

Nested timestamps are ISO strings; top-level timestamp options accept strings or Date. Explicit nulls are distinct from omitted values where the schema says so. Inputs are not coerced from strings or booleans into numbers. Unsafe JSON integers fail with numeric precision errors before a rounded value is returned. For larger SQL integers, use string parameters and an explicit SQL cast.

Document-filtered or time-scoped searchClaims/searchChunks use POST; unfiltered calls use GET as the Python client does. searchDocumentsRequest omits fields equal to model defaults. Connector methods configure remote deployment adapters; they do not execute npm connector libraries on the client machine.

Transport and errors

Ordinary requests default to timeoutMs: 30_000. Caller cancellation raises AbortError with the signal reason; an HTTP deadline raises RequestTimeoutError; readiness expiry raises TimeoutError with its last report. These are distinct.

Writes are never automatically replayed. A classified read can replay once only after issuer resolution changes its deployment URL. Network failure/421 on a write can refresh the mapping for a later operation, while the original error is surfaced. Timeouts and caller cancellation do not refresh or replay.

The default adapter uses Node HTTP/HTTPS with per-client agents, no automatic redirects/retries and one transmission per invocation. Engine redirects are refused. Issuer/account redirects allow at most three hops on the same origin and preserve their method. Discovered URLs require HTTPS except loopback HTTP. Account paths reject absolute URLs and traversal, including encoded traversal.

A caller-owned client: HttpClient takes relative paths and its own base URL/headers; it cannot be combined with apiKey/baseUrl/project/transport/agents settings. transport: HttpTransport takes absolute URLs and retains SDK routing/headers. Alternatively borrow agents: {http?, https?} for the default single-send adapter. These modes are mutually exclusive. Both injected adapters must send once, honor AbortSignal and return redirects unfollowed. Fetch-standard adapters are unsuitable: they resend reusable requests after HTTP 421.

SDK-owned agents ignore environment proxies, including NODE_USE_ENV_PROXY. Node 22.0 lacks proxyEnv, so explicit injection keeps selection deterministic. Node TLS defaults and NODE_EXTRA_CA_CERTS apply; a caller-owned HTTPS agent can supply ca material, and an operator-configured http.Agent subclass or conforming transport can handle proxies. SSL_CERT_FILE is not read. Idle sockets retire after four seconds; 421 connections are retired before they can serve queued requests. An active response may take longer than four seconds.

timeoutMs is a total operation deadline including routing/upload/body reads, and bounds injected calls too. Raise the 30-second default for slow or large uploads (50 MB at 5 Mbit/s takes about 80 seconds). Timeouts can leave an unknown write outcome and never authorize replay. Close destroys only SDK-owned engine agents and cancels this client's waiters/requests; borrowed resources and shared discovery remain available. The closed facade refuses later calls with AbortError. Pending lookups share only identical transport objects; completed successes may be reused across transports.

MemoryApiError contains statusCode/detail/code, response when available, and optional retryable/requestId diagnostics. RateLimited also has retryAfter in seconds. Hints are carried for callers; the client does not interpret them as permission to retry writes. ProjectResolutionError, StoredKeyRefused, AccountApiUnavailable, IssuerError, NumericPrecisionError and RequestTimeoutError extend MemoryApiError, as does LayerUnavailable (status 409, code layer_unavailable, with the missing layer). InputValidationError and CredentialError are TypeErrors. PipelineDeadLettered, TimeoutError, ConnectorNotFoundError and AbortError are outside MemoryApiError.

The optional /connectors routes are not part of the standard exported engine profile. They require a deployment composing connector ports; otherwise the client propagates that deployment's refusal.

Tool support and separate executable packages

The base package exports ToolDefinition, Permission, memoryTools, tool, renderToolsList, every catalogue name constant, and PROJECT_ARGUMENT. Definitions carry routes, versions, permissions, schemas and annotations. OPEN_QUERY_TOOL_NAMES, OPERATION_TOOL_NAMES and MEMORY_WRITE_TOOL_NAMES identify the source-defined groups. Individual constants include INGEST_TOOL_NAME, PIPELINE_READINESS_TOOL_NAME, DELETE_DOCUMENT_TOOL_NAME, SEARCH_DOCUMENTS_TOOL_NAME and ADJACENT_CHUNKS_TOOL_NAME.

validateArguments checks every memory tool and returns parsed arguments. validateSavedQueryIdentifier checks saved-query names. ToolError, ToolArgumentError, invalidArguments, mapError and errorResult supply a common structured failure shape. ToolError.asDict() renders its envelope. ToolDefinition exposes mutates and annotations. No MCP host settings are loaded. Text/base64 bodies are resolved locally; a path is refused unless a caller supplies a PathBodyResolver. That separate host owns root containment, symlink checks, regular-file checks, size limits and MIME policy.

Credential/routing helpers include configDir, credentialsPath, loadCredentials, environmentIssuer, normalizeKey, resolveProject and clearHostCache. Issuer helpers include KeyClaims, IssuerMetadata, isLoopback, requireSecureUrl, origin, sameOrigin, normalizeIssuer, metadataUrl, sendSameOrigin, fetchIssuerMetadata and clearMetadataCache. NormalizedOrigin describes canonical origin comparison. version is this npm package version; pythonCompatibility identifies its Python source/baseline. signedKeyClaims decodes routing claims without verification. KeyClaims supplies covers/expiresAt; IssuerMetadata supplies checked endpoint lookup.

CLI/MCP hosts and connector adapter packages have separate design, execution, security and release contracts. This client exports their reusable client-side contracts, not backend protocols or a server implementation.

Drift checks

npm run check:generated re-exports the engine API offline and compares committed schemas, source inventories and pinned type generation without changing git. npm run check:parity executes current Python methods and compares source-recorded requests, defaults, results, malformed responses, every catalogue validator and structured error mappings. npm test executes those shared fixtures plus actual HTTP failure/cancellation scenarios.

npm run check:package installs the tarball in independent ESM/CommonJS consumers and typechecks imports. CI runs Linux/Windows and supported Node versions, plus released/candidate live-engine profiles. A new Python method, schema field or semantic validator requires reviewed client/fixture updates. Provider repositories check their issuer schemas against the public provider contract; private cloud DTOs are not copied into the client.

Timeouts and poll intervals must be finite, greater than zero and at most 2,147,483,647 milliseconds (Node's timer limit). Invalid values raise InputValidationError before HTTP. Use pipelineReadiness for a single poll. Connection and configuration-directory environment names are case-insensitive, matching Python. On Windows, argument or environment signed keys without a URL use issuer routing without reading an unavailable credential file. Unsigned keys without a URL refuse a present file and use the localhost default if the file is absent.

General lookup/graph validAt and believedAt strings retain their supplied ISO datetime, including nonzero offsets. TypeScript requires a timezone offset or Z, unlike Python's permissive naive datetime handling; this keeps requests within the published date-time format and avoids ambiguous timestamps. The current engine (v0.17.1+) requires UTC on those HTTP fields and returns 422 for a nonzero offset, just as it does for the Python client. Earlier releases accept offsets at the HTTP boundary; this does not guarantee that their downstream query implementation accepts them. Ingest lineage and schema fields marked UTC continue to require UTC.