v1.0.0 — iOS ready, Android coming

Native SMB
for React Native

@cetapod/react-native-smb

Connect to NAS, file servers, and Windows shares from your mobile app. Powered by libsmb2 and Nitro Modules — with a task-first API built for real transfers.

npm install @cetapod/react-native-smb react-native-nitro-modules
//Media SMB3
//Documents SMB2
//Backups SMB3
downloadFile · 65%
SMBv2/v3 protocol
iOS 12+ supported
Nitro JSI native bridge
LGPL-2.1 license

Built for real file operations

Not a thin wrapper — a full SMB client with connection pooling, pipelined transfers, and a task model designed for mobile UX.

SmbTask per operation

Every call returns a task — await .result(), watch with .subscribe(), or abort with .cancel(). Mix all three freely.

result · subscribe · cancel

4-slot connection pool

Up to four parallel SMB sessions. Slot 0 is reserved for interactive ops — list, rename, move — so UI never blocks behind bulk transfers.

interactive-priority slot 0

8-chunk pipelining

Within each transfer, up to eight SMB2 READ/WRITE requests in flight on the same connection. Credit-based pipelining for maximum throughput.

kMaxInFlight = 8

React hooks

useSubscribe mirrors task subscriptions. useTransfers powers a transfer tray — track every download and upload in your UI.

useSubscribe · useTransfers

Typed errors

SmbError and SmbTaskError with structured codes. Know exactly why a connection failed or a transfer was interrupted.

SmbError · SmbTaskError

libsmb2 + Nitro

Battle-tested C SMB stack exposed through Nitro's JSI bridge. Static types from TypeScript to C++ — no bridge serialization overhead.

native performance

Real apps that talk to file servers

Whether you're building a consumer NAS app or an enterprise file tool, the task-first API and connection pool keep UI responsive during heavy I/O.

NAS & file browsers

Browse shares, preview files, and manage folders on Synology, QNAP, Windows, or Samba — with list and metadata ops prioritized on slot 0.

Media & photo apps

Stream or download large assets from network shares. Pipelined transfers and useTransfers give you tray UI with live progress and cancel.

Enterprise document access

Authenticate with domain credentials, read ACLs via getSecurityDescriptor, and integrate with existing SMB infrastructure on iOS.

Backup & sync utilities

Upload and download in parallel across pool slots. Batch deletes with SmbTask.settleAll and deterministic error handling per file.

Connection pool & pipeline

Parallelism at two levels — across tasks via the pool, within transfers via chunk pipelining.

SmbConnectionPool(4) live
slot 0
listDirectory
interactive only
slot 1
slot 2
slot 3
SmbFileIO — 8-chunk pipeline (single transfer)
1 2 3 4 5 6 7 8

Interactive-priority scheduling

Slot 0 accepts only interactive operators — shallow list, path info, rename, move. Bulk metadata work uses slots 1–3. When slot 0 is busy, interactive ops overflow to general slots rather than queuing behind downloads.

Independent sessions, not multichannel

Each pool slot is a full smb2_context with its own TCP socket. The server sees N separate client connections. Application-level scheduling on top of what libsmb2 provides.

This pool One session per slot · N connections · Slot 0 for UI
SMB3 multichannel One session · N channels · Requires server support

Diagnostics built in

getPoolInfo() and subscribePoolInfo() expose slot state, task IDs, and operator kinds. The example app includes a PoolDebugPanel for real-time inspection.

Read full architecture

A few lines to connect

Install, connect to a share, list files, download with progress.

App.tsx
import { SMB, SmbCredentials } from '@cetapod/react-native-smb';

const smb = SMB();
const creds: SmbCredentials = {
  username: 'user',
  password: 'pass',
};

await smb.connect('smb://192.168.1.100/Media', creds).result();
const entries = await smb.listDirectory('/', false).result();

const task = smb.downloadFile('/video.mp4', '/local/video.mp4');
task.subscribe((snap) => console.log(snap.progress));
await task.result();
transfer.ts
const task = smb.downloadFile(remote, local);

// Live getters after subscribe()
const unsub = task.subscribe((snap) => {
  console.log(
    snap.progress,
    snap.bytesPerSecond,
    snap.status,
  );
});

// Or subscribe without callback — read task.progress
task.subscribe();
console.log(task.progress, task.status);

// User aborts
task.cancel();
unsub();
TransferTray.tsx
import {
  useTransfers,
  useTransferActions,
  useSubscribe,
} from '@cetapod/react-native-smb';

function TransferTray() {
  const transfers = useTransfers();
  const { cancel, clear } = useTransferActions();

  return transfers.map((t) => (
    <Row key={t.id} progress={t.progress} />
  ));
}

function TaskBar({ task }) {
  const { progress } = useSubscribe(task);
  return <Bar value={progress} />;
}
batch.ts
import { SmbTask } from '@cetapod/react-native-smb';

// Delete multiple files — collect all outcomes
const tasks = files.map((f) =>
  smb.deleteItem(f.path)
);

const results = await SmbTask.settleAll(tasks);
// Like Promise.allSettled over .result()

for (const r of results) {
  if (r.status === 'fulfilled') {
    console.log('deleted', r.value);
  }
}

Everything you need

Deep dives into the task model, API surface, and connection pool internals.

View all documentation

Requirements

Works with modern React Native and Nitro Modules.

Platform / dependency Version Status
React Native >= 0.76 Supported
React >= 19 Supported
react-native-nitro-modules >= 0.22, < 1.0 Required
iOS 12+ Supported
Android Coming soon
SMB protocol v2 / v3 Supported

Ready to connect?

Install from npm, run the example app, and start building NAS-aware mobile experiences today.