Unix Domain Sockets

Unix domain sockets are the simplest way to run Memory Service next to an agent on the same machine. The service stays off a TCP port, filesystem permissions become part of the access boundary, and the client packages in this repo can switch transports with one config knob. Both REST and gRPC traffic are multiplexed over the same socket automatically.

Local Stack

For a fully local setup, use SQLite for the datastore, SQLite for vector storage, the process-local cache, and a Unix socket listener:

Note: The memory-service CLI is not yet published as a pre-built binary. You can install it from source with Go 1.24+:

go install -tags "sqlite_fts5 sqlite_json" github.com/chirino/memory-service@latest
memory-service serve \
  --db-kind=sqlite \
  --db-url=file:$HOME/.local/share/memory-service/memory.db \
  --vector-kind=sqlite \
  --cache-kind=local \
  --unix-socket=$HOME/.local/run/memory-service/api.sock \
  --unix-socket-auth=local

These options keep the local stack self-contained. db-kind=sqlite and vector-kind=sqlite keep both the primary datastore and vector index in local files instead of requiring Postgres, MongoDB, or Qdrant; cache-kind=local keeps caching in-process instead of requiring Redis or Infinispan; db-url=file:$HOME/.local/share/... stores persistent data in the user’s home directory; and --unix-socket=$HOME/.local/run/... keeps the live socket out of /tmp, where other local users are more likely to discover and probe it.

The server creates the socket parent directory with 0700 permissions and the socket file with 0600 permissions, so only the owning user can connect by default.

With --unix-socket-auth=local, access to that socket is the authentication boundary. REST and gRPC calls do not need bearer tokens or API keys; both are authorized as the current OS username with client ID local-agent. Override those values with --local-user-id and --local-client-id when the application needs stable IDs that differ from the defaults. The local principal receives no admin, auditor, or indexer role unless you explicitly grant one through the normal role configuration.

Security boundary: Any process running as the Unix user that owns the socket can act as this local principal. Use the default --unix-socket-auth=credentials mode if applications running under the same OS account should not trust one another.

Local authentication is rejected unless the main API is exposed exclusively through --unix-socket. A separate TCP management listener may still expose health and metrics endpoints because it does not expose the authenticated API.

The framework guides reuse that same server shape. They only change the client-side configuration.

Verify that the local socket is reachable:

curl -sSf --unix-socket $HOME/.local/run/memory-service/api.sock \
  http://localhost/ready

Example output:

{
  "status": "ok"
}

Framework Knobs

  • Python LangChain and LangGraph: MEMORY_SERVICE_UNIX_SOCKET=$HOME/.local/run/memory-service/api.sock
  • TypeScript / Vercel AI: MEMORY_SERVICE_UNIX_SOCKET=$HOME/.local/run/memory-service/api.sock
  • Spring Boot: memory-service.client.url=unix://${HOME}/.local/run/memory-service/api.sock
  • Quarkus: memory-service.client.url=unix://${HOME}/.local/run/memory-service/api.sock

Browser code still cannot connect directly to a Unix domain socket. Keep UDS between the Memory Service process and the server-side agent app.