## 1. Project Overview & Quickstart (tursodatabase/turso)

## File: bindings/rust/README.md

# turso

The next evolution of SQLite: A high-performance, SQLite-compatible database library for Rust

## Features

- **SQLite Compatible**: Similar interface to rusqlite with familiar API apart from using async Rust
- **High Performance**: Built with Rust for maximum speed and efficiency  
- **Async/Await Support**: Native async operations with tokio support
- **In-Process**: No network overhead, runs directly in your application
- **Cross-Platform**: Supports Linux, macOS, and Windows
- **Transaction Support**: Full ACID transactions with rollback support
- **Prepared Statements**: Optimized query execution with parameter binding
- **Cloud Sync**: Sync with Turso Cloud using `Builder::new_remote()` (optional `sync` feature)

## Installation

Add this to your `Cargo.toml`:

```toml
[dependencies]
turso = "0.4.3"
tokio = { version = "1.0", features = ["full"] }
```

For cloud sync capabilities, enable the `sync` feature:

```toml
[dependencies]
turso = { version = "0.4.3", features = ["sync"] }
tokio = { version = "1.0", features = ["full"] }
```

## Quick Start

### In-Memory Database

```rust
use turso::Builder;

#[tokio::main]
async fn main() -> turso::Result<()> {
    // Create an in-memory database
    let db = Builder::new_local(":memory:").build().await?;
    let conn = db.connect()?;

    // Create a table
    conn.execute(
        "CREATE TABLE users (id INTEGER PRIMARY KEY, name TEXT, email TEXT)",
        ()
    ).await?;

    // Insert data
    conn.execute(
        "INSERT INTO users (name, email) VALUES (?1, ?2)",
        ["Alice", "alice@example.com"]
    ).await?;

    conn.execute(
        "INSERT INTO users (name, email) VALUES (?1, ?2)", 
        ["Bob", "bob@example.com"]
    ).await?;

    // Query data
    let mut rows = conn.query("SELECT * FROM users", ()).await?;
    
    while let Some(row) = rows.next().await? {
        let id = row.get_value(0)?;
        let name = row.get_value(1)?;
        let email = row.get_value(2)?;
        println!("User: {} - {} ({})", 
            id.as_integer().unwrap_or(&0), 
            name.as_text().unwrap_or(&"".to_string()), 
            email.as_text().unwrap_or(&"".to_string())
        );
    }

    Ok(())
}
```

### File-Based Database

```rust
use turso::Builder;

#[tokio::main] 
async fn main() -> turso::Result<()> {
    // Create or open a database file
    let db = Builder::new_local("my-database.db").build().await?;
    let conn = db.connect()?;

    // Create a table
    conn.execute(
        r#"CREATE TABLE IF NOT EXISTS posts (
            id INTEGER PRIMARY KEY AUTOINCREMENT,
            title TEXT NOT NULL,
            content TEXT,
            created_at DATETIME DEFAULT CURRENT_TIMESTAMP
        )"#,
        ()
    ).await?;

    // Insert a post
    let rows_affected = conn.execute(
        "INSERT INTO posts (title, content) VALUES (?1, ?2)",
        ["Hello World", "This is my first blog post!"]
    ).await?;

    println!("Inserted {} rows", rows_affected);

    Ok(())
}
```

### Synced Database

Sync your local database with Turso Cloud:

```rust
use turso::sync::Builder;

#[tokio::main]
async fn main() -> turso::Result<()> {
    // Create a synced database
    let db = Builder::new_remote("local.db")
        .with_remote_url("libsql://your-database.turso.io")
        .with_auth_token("your-token")
        .build()
        .await?;

    let conn = db.connect().await?;

    // Create a table and insert data
    conn.execute(
        "CREATE TABLE IF NOT EXISTS notes (id INTEGER PRIMARY KEY, content TEXT)",
        ()
    ).await?;

    conn.execute(
        "INSERT INTO notes (content) VALUES (?1)",
        ["My first synced note"]
    ).await?;

    // Push local changes to remote
    db.push().await?;

    // Pull remote changes to local
    db.pull().await?;

    Ok(())
}
```

## API Reference

### Builder

Create a new database:

```rust
let db = Builder::new_local(":memory:").build().await?;
let db = Builder::new_local("data.db").build().await?;
```

### Connection

Execute queries and statements:

```rust
// Execute SQL directly
let rows_affected = conn.execute("INSERT INTO users (name) VALUES (?1)", ["Alice"]).await?;

// Query for multiple rows
let mut rows = conn.query("SELECT * FROM users WHERE age > ?1", [18]).await?;

// Prepare statements for reuse
let mut stmt = conn.prepare("SELECT * FROM users WHERE id = ?1").await?;
let mut rows = stmt.query([42]).await?;

// Execute prepared statements
let rows_affected = stmt.execute(["Alice"]).await?;
```

### Working with Results

```rust
use futures_util::TryStreamExt;

let mut rows = conn.query("SELECT name, email FROM users", ()).await?;

while let Some(row) = rows.try_next().await? {
    let name = row.get_value(0)?.as_text().unwrap_or(&"".to_string());
    let email = row.get_value(1)?.as_text().unwrap_or(&"".to_string());
    println!("{}: {}", name, email);
}
```

### Sync API Reference

#### sync::Builder

Create a synced database that synchronizes with Turso Cloud:

```rust
use turso::sync::Builder;

let db = Builder::new_remote("local.db")       // Local database path (or ":memory:")
    .with_remote_url("libsql://db.turso.io")   // Remote URL (https://, http://, or libsql://)
    .with_auth_token("your-token")              // Authorization token
    .bootstrap_if_empty(true)                   // Download schema on first sync (default: true)
    .with_remote_encryption("base64-encoded-key", RemoteEncryptionCipher::Aes256Gcm) // Optional remote encryption
    .build()
    .await?;
```

#### sync::Database

Operations for synced databases:

```rust
// Push local changes to remote
db.push().await?;

// Pull remote changes (returns true if changes were applied)
let had_changes = db.pull().await?;

// Force WAL checkpoint
db.checkpoint().await?;

// Get sync statistics
let stats = db.stats().await?;
println!("Received: {} bytes", stats.network_received_bytes);
println!("Sent: {} bytes", stats.network_sent_bytes);
println!("WAL size: {} bytes", stats.main_wal_size);
```

## License

MIT

## Support

- [GitHub Issues](https://github.com/tursodatabase/turso/issues)
- [Discord Community](https://tur.so/discord)

---

## File: bindings/react-native/README.md

# Turso Sync React Native SDK

React Native bindings for Turso embedded replicas - sync your local SQLite database with Turso cloud.

## Installation

```bash
npm install @tursodatabase/sync-react-native
```

### iOS

```bash
cd ios && pod install
```

### Android

Requires `minSdkVersion` 21+ in `android/build.gradle`.

## Quick Start

```typescript
import { Database, getDbPath } from '@tursodatabase/sync-react-native';

// Get platform-specific writable path
const dbPath = getDbPath('myapp.db');

// Create database with sync
const db = new Database({
  path: dbPath,
  url: 'libsql://your-db.turso.io',
  authToken: 'your-auth-token',
});

// Connect (bootstraps from remote if empty)
await db.connect();

// Query local replica (fast)
const users = await db.all('SELECT * FROM users');

// Make local changes
await db.run('INSERT INTO users (name) VALUES (?)', ['Alice']);

// Sync with remote
await db.push();  // Push local changes
await db.pull();  // Pull remote changes

// Close when done
await db.close();
```

## Local-Only Database

```typescript
const db = new Database({ path: getDbPath('local.db') });
await db.connect();

await db.exec('CREATE TABLE IF NOT EXISTS users (id INTEGER PRIMARY KEY, name TEXT)');
await db.run('INSERT INTO users (name) VALUES (?)', ['Bob']);
const user = await db.get('SELECT * FROM users WHERE id = ?', [1]);

await db.close();
```

## Encrypted Remote Database

```typescript
const db = new Database({
  path: getDbPath('encrypted.db'),
  url: 'libsql://your-db.turso.io',
  authToken: 'your-auth-token',
  remoteEncryption: {
    cipher: 'aes256gcm',
    key: 'base64-encoded-key',
  },
});
```

## API

### Database Methods

| Method | Description |
|--------|-------------|
| `connect()` | Open/bootstrap the database |
| `exec(sql)` | Execute SQL (no results) |
| `run(sql, params?)` | Execute SQL, return `{ changes, lastInsertRowid }` |
| `get(sql, params?)` | Query single row |
| `all(sql, params?)` | Query all rows |
| `prepare(sql)` | Create prepared statement |
| `close()` | Close database |

### Sync Methods (when `url` is provided)

| Method | Description |
|--------|-------------|
| `push()` | Push local changes to remote |
| `pull()` | Pull remote changes to local |
| `sync()` | Push then pull |
| `stats()` | Get sync statistics |

### Transactions

```typescript
await db.transaction(async () => {
  await db.run('INSERT INTO users (name) VALUES (?)', ['Alice']);
  await db.run('INSERT INTO users (name) VALUES (?)', ['Bob']);
  // Commits on success, rolls back on error
});
```
## License

This project is licensed under the [MIT license](https://github.com/tursodatabase/turso/blob/main/LICENSE.md).

## Links

- [Turso Documentation](https://docs.turso.tech)
- [GitHub](https://github.com/tursodatabase/turso)
- [npm](https://www.npmjs.com/package/@tursodatabase/sync-react-native)

---

## File: bindings/python/README.md

---

## About

Turso Database runs in production today at multiple organizations. It has not yet reached 1.0, so as with any database we recommend keeping backups — see the [FAQ](https://github.com/tursodatabase/turso#faq) for where the project stands.

## Features

- **SQLite compatible:** SQLite query language and file format support ([status](https://github.com/tursodatabase/turso/blob/main/COMPAT.md)).
- **In-process**: No network overhead, runs directly in your Python process
- **Cross-platform**: Supports Linux, macOS, Windows
- **Remote partial sync**: Bootstrap from a remote database, pull remote changes, and push local changes when online &mdash; all while enjoying a fully operational database offline.
- **Asyncio support**: Built-in integration with asyncio to ensure queries won’t block your event loop

## Installation

```bash
uv pip install pyturso
```

## Database driver

A minimal DB‑API 2.0 example using an in‑memory database:

```python
import turso

# Standard DB-API usage
conn = turso.connect(":memory:")
cur = conn.cursor()

cur.execute("CREATE TABLE users (id INTEGER PRIMARY KEY, username TEXT)")
cur.execute("INSERT INTO users VALUES (1, 'alice'), (2, 'bob')")

cur.execute("SELECT * FROM users ORDER BY id")
rows = cur.fetchall()
print(rows)  # [(1, 'alice'), (2, 'bob')]

conn.close()
```

## Database driver (asyncio)

Non-blocking access with asyncio:

```python
import asyncio
import turso.aio

async def main():
    # Connect and use as an async context manager
    async with turso.aio.connect(":memory:") as conn:
        # Executes multiple statements
        await conn.executescript("""
            CREATE TABLE t (id INTEGER PRIMARY KEY, name TEXT);
            INSERT INTO t(name) VALUES ('alice'), ('bob');
        """)

        # Use a cursor for parameterized queries
        cur = conn.cursor()
        await cur.execute("SELECT COUNT(*) FROM t WHERE name LIKE ?", ("a%",))
        count = (await cur.fetchone())[0]
        print(count)  # 1

        # JSON and generate_series also available
        cur = conn.cursor()
        await cur.execute("SELECT SUM(value) FROM generate_series(1, 10)")
        print((await cur.fetchone())[0])  # 55

asyncio.run(main())
```

## Synchronization driver

Use a remote Turso database while working locally. You can bootstrap local state from the remote, pull remote changes, and push local commits.

Note: You need a Turso remote URL. See the Turso docs for provisioning and authentication.

```python
import turso.sync

# Connect a local database to a remote Turso database
conn = turso.sync.connect(
    ":memory:",                          # local db path (or a file path)
    remote_url="https://<db>.<region>.turso.io"  # your remote URL
)

# Read data (fetched from remote if not present locally yet)
rows = conn.execute("SELECT * FROM t").fetchall()
print(rows)

# Pull new changes from remote into local
changed = conn.pull()
print("Pulled:", changed)  # True if there were new remote changes

# Make local changes
conn.execute("INSERT INTO t VALUES ('push works')")
conn.commit()

# Push local commits to remote
conn.push()

# Optional: inspect and manage sync state
stats = conn.stats()
print("Network received (bytes):", stats.network_received_bytes)
conn.checkpoint()  # compact local WAL after many writes

conn.close()
```

Partial bootstrap to reduce initial network cost:

```python
import turso.sync

conn = turso.sync.connect(
    "local.db",
    remote_url="https://<db>.<region>.turso.io",
    # fetch first 128 KiB upfront
    partial_sync_experimental=turso.sync.PartialSyncOpts(
      bootstrap_strategy=turso.sync.PartialSyncPrefixBootstrap(length=128 * 1024),
    ),
)
```

## Synchronization driver (asyncio)

The same sync primitives, but fully async:

```python
import asyncio

async def main():
    conn = await turso.aio.sync.connect(":memory:", remote_url="https://<db>.<region>.turso.io")

    # Read data
    rows = await (await conn.execute("SELECT * FROM t")).fetchall()
    print(rows)

    # Pull and push
    await conn.pull()
    await conn.execute("INSERT INTO t VALUES ('hello from asyncio')")
    await conn.commit()
    await conn.push()

    # Stats and maintenance
    stats = await conn.stats()
    print("Main WAL size:", stats.main_wal_size)
    await conn.checkpoint()

    await conn.close()

asyncio.run(main())
```

## License

This project is licensed under the [MIT license](../../LICENSE.md).

## Support

- [GitHub Issues](https://github.com/tursodatabase/turso/issues)
- [Documentation](https://docs.turso.tech)
- [Discord Community](https://tur.so/discord)

---

## File: bindings/javascript/docs/API.md

# class Database

The `Database` class represents a connection that can prepare and execute SQL statements.

## Methods

### new Database(path, [options]) ⇒ Database

Creates a new database connection.

| Param   | Type                | Description               |
| ------- | ------------------- | ------------------------- |
| path    | `string` | Path to the database file |
| options | `object` | Options.                  |

The `path` parameter points to the SQLite database file to open. If the file pointed to by `path` does not exists, it will be created.
To open an in-memory database, please pass `:memory:` as the `path` parameter.

Supported `options` fields include:

- `timeout`: busy timeout in milliseconds
- `defaultQueryTimeout`: default maximum query execution time in milliseconds before interruption

Per-query timeout override is available via `queryOptions`, for example:

- `db.exec("SELECT 1", { queryTimeout: 100 })`
- `stmt.get(undefined, { queryTimeout: 100 })`

The function returns a `Database` object.

### prepare(sql) ⇒ Statement

Prepares a SQL statement for execution.

| Param | Type                | Description                          |
| ----- | ------------------- | ------------------------------------ |
| sql   | `string` | The SQL statement string to prepare. |

The function returns a `Statement` object.

### run(sql[, ...bindParameters][, queryOptions]) ⇒ object

Convenience wrapper that prepares `sql` and executes `Statement.run`. Returns the same info object as `Statement.run` (`changes` and `lastInsertRowid`). The internally prepared statement is finalized before the call returns.

| Param          | Type                | Description                                                          |
| -------------- | ------------------- | -------------------------------------------------------------------- |
| sql            | `string` | The SQL statement string.                                            |
| bindParameters | `any`    | Optional positional or named bind parameters.                        |
| queryOptions   | `object` | Optional per-query overrides (for example, `{ queryTimeout: 100 }`). |

**Note:** This is an extension in libSQL and not available in `better-sqlite3`.

### get(sql[, ...bindParameters][, queryOptions]) ⇒ row

Convenience wrapper that prepares `sql` and executes `Statement.get`. Returns the first row, or `undefined` if no row matched. The internally prepared statement is finalized before the call returns.

| Param          | Type                | Description                                                          |
| -------------- | ------------------- | -------------------------------------------------------------------- |
| sql            | `string` | The SQL statement string.                                            |
| bindParameters | `any`    | Optional positional or named bind parameters.                        |
| queryOptions   | `object` | Optional per-query overrides (for example, `{ queryTimeout: 100 }`). |

**Note:** This is an extension in libSQL and not available in `better-sqlite3`.

### all(sql[, ...bindParameters][, queryOptions]) ⇒ array of rows

Convenience wrapper that prepares `sql` and executes `Statement.all`. Returns all matching rows as an array. The internally prepared statement is finalized before the call returns.

| Param          | Type                | Description                                                          |
| -------------- | ------------------- | -------------------------------------------------------------------- |
| sql            | `string` | The SQL statement string.                                            |
| bindParameters | `any`    | Optional positional or named bind parameters.                        |
| queryOptions   | `object` | Optional per-query overrides (for example, `{ queryTimeout: 100 }`). |

**Note:** This is an extension in libSQL and not available in `better-sqlite3`.

### iterate(sql[, ...bindParameters][, queryOptions]) ⇒ async iterator

Convenience wrapper that prepares `sql` and executes `Statement.iterate`. Returns an async iterator over the resulting rows. The internally prepared statement is finalized when the iterator is exhausted or closed.

| Param          | Type                | Description                                                          |
| -------------- | ------------------- | -------------------------------------------------------------------- |
| sql            | `string` | The SQL statement string.                                            |
| bindParameters | `any`    | Optional positional or named bind parameters.                        |
| queryOptions   | `object` | Optional per-query overrides (for example, `{ queryTimeout: 100 }`). |

**Note:** This is an extension in libSQL and not available in `better-sqlite3`.

### transaction(function) ⇒ function

Returns a function that runs the given function in a transaction.

| Param    | Type                  | Description                           |
| -------- | --------------------- | ------------------------------------- |
| function | `function` | The function to run in a transaction. |

### pragma(string, [options]) ⇒ results

Executes the given PRAGMA and returns its results.

| Param    | Type                  | Description           |
| -------- | --------------------- | ----------------------|
| source   | `string`   | Pragma to be executed |
| options  | `object`   | Options.              |

Most PRAGMA return a single value, the `simple: boolean` option is provided to return the first column of the first row.

```js
db.pragma('cache_size = 32000');
console.log(db.pragma('cache_size', { simple: true })); // => 32000
```

### backup(destination, [options]) ⇒ promise

This function is currently not supported.

### serialize([options]) ⇒ Buffer

This function is currently not supported.

### function(name, [options], function) ⇒ this

This function is currently not supported.

### aggregate(name, options) ⇒ this

This function is currently not supported.

### table(name, definition) ⇒ this

This function is currently not supported.

### loadExtension(path, [entryPoint]) ⇒ this

Loads a SQLite3 extension.

| Param | Type                | Description                             |
| ----- | ------------------- | --------------------------------------- |
| path  | `string` | The path to the extension to be loaded. |

### exec(sql) ⇒ this

Executes a SQL statement.

| Param | Type                | Description                          |
| ----- | ------------------- | ------------------------------------ |
| sql   | `string` | The SQL statement string to execute. |

This can execute strings that contain multiple SQL statements.

### interrupt() ⇒ this

Cancel ongoing operations and make them return at earliest opportunity.

**Note:** This is an extension in libSQL and not available in `better-sqlite3`.

This function is currently not supported.

### close() ⇒ this

Closes the database connection.

# class Statement

## Methods

### run([...bindParameters]) ⇒ object

Executes the SQL statement and (currently) returns an array with results.

**Note:** It should return an info object.

| Param          | Type                          | Description                                      |
| -------------- | ----------------------------- | ------------------------------------------------ |
| bindParameters | `array of objects` | The bind parameters for executing the statement. |

The returned info object contains two properties: `changes` that describes the number of modified rows and `info.lastInsertRowid` that represents the `rowid` of the last inserted row.

This function is currently not supported.

### get([...bindParameters]) ⇒ row

Executes the SQL statement and returns the first row.

| Param          | Type                          | Description                                      |
| -------------- | ----------------------------- | ------------------------------------------------ |
| bindParameters | `array of objects` | The bind parameters for executing the statement. |

### all([...bindParameters]) ⇒ array of rows

Executes the SQL statement and returns an array of the resulting rows.

| Param          | Type                          | Description                                      |
| -------------- | ----------------------------- | ------------------------------------------------ |
| bindParameters | `array of objects` | The bind parameters for executing the statement. |

### iterate([...bindParameters]) ⇒ iterator

Executes the SQL statement and returns an iterator to the resulting rows.

| Param          | Type                          | Description                                      |
| -------------- | ----------------------------- | ------------------------------------------------ |
| bindParameters | `array of objects` | The bind parameters for executing the statement. |

### pluck([toggleState]) ⇒ this

Makes the prepared statement only return the value of the first column of any rows that it retrieves.

| Param     | Type                 | Description                                                                            |
| --------- | -------------------- | -------------------------------------------------------------------------------------- |
| pluckMode | `boolean` | Enable of disable pluck mode. If you don't pass the paramenter, pluck mode is enabled. |

```js
stmt.pluck(); // plucking ON
stmt.pluck(true); // plucking ON
stmt.pluck(false); // plucking OFF
```

> NOTE: When plucking is turned on, raw mode is turned off (they are mutually exclusive options).

### expand([toggleState]) ⇒ this

This function is currently not supported.

### raw([rawMode]) ⇒ this

Makes the prepared statement return rows as arrays instead of objects.

| Param   | Type                 | Description                                                                       |
| ------- | -------------------- | --------------------------------------------------------------------------------- |
| rawMode | `boolean` | Enable or disable raw mode. If you don't pass the parameter, raw mode is enabled. |

This function enables or disables raw mode. Prepared statements return objects by default, but if raw mode is enabled, the functions return arrays instead.

```js
stmt.raw(); // raw mode ON
stmt.raw(true); // raw mode ON
stmt.raw(false); // raw mode OFF
```

> NOTE: When raw mode is turned on, plucking is turned off (they are mutually exclusive options).

### columns() ⇒ array of objects

Returns the columns in the result set returned by this prepared statement.

This function is currently not supported.

### bind([...bindParameters]) ⇒ this

| Param          | Type                          | Description                                      |
| -------------- | ----------------------------- | ------------------------------------------------ |
| bindParameters | `array of objects` | The bind parameters for executing the statement. |

Binds **permanently** the given parameters to the statement. After a statement's parameters are bound this way, you may no longer provide it with execution-specific (temporary) bound parameters.

---

## File: bindings/javascript/packages/wasm-common/README.md

## About

This package is the Turso embedded database common JS library which is shared between final builds for Node and Browser.

Do not use this package directly - instead you must use `@tursodatabase/database` or `@tursodatabase/database-wasm`.

Turso Database runs in production today at multiple organizations. It has not yet reached 1.0, so as with any database we recommend keeping backups — see the [FAQ](https://github.com/tursodatabase/turso#faq) for where the project stands.

---

## File: bindings/javascript/packages/wasm/README.md

---

## About

This package is the Turso embedded database library for JavaScript in Browser.

Turso Database runs in production today at multiple organizations. It has not yet reached 1.0, so as with any database we recommend keeping backups — see the [FAQ](https://github.com/tursodatabase/turso#faq) for where the project stands.

## Features

- **SQLite compatible:** SQLite query language and file format support ([status](https://github.com/tursodatabase/turso/blob/main/COMPAT.md)).
- **In-process**: No network overhead, runs directly in your Node.js process
- **TypeScript support**: Full TypeScript definitions included

## Installation

```bash
npm install @tursodatabase/database-wasm
```

## Getting Started

### In-Memory Database

```javascript
import { connect } from '@tursodatabase/database-wasm';

// Create an in-memory database
const db = await connect(':memory:');

// Create a table
await db.exec('CREATE TABLE users (id INTEGER PRIMARY KEY, name TEXT, email TEXT)');

// Insert data
const insert = db.prepare('INSERT INTO users (name, email) VALUES (?, ?)');
await insert.run('Alice', 'alice@example.com');
await insert.run('Bob', 'bob@example.com');

// Query data
const users = await db.prepare('SELECT * FROM users').all();
console.log(users);
// Output: [
//   { id: 1, name: 'Alice', email: 'alice@example.com' },
//   { id: 2, name: 'Bob', email: 'bob@example.com' }
// ]
```

### File-Based Database

```javascript
import { connect } from '@tursodatabase/database-wasm';

// Create or open a database file
const db = await connect('my-database.db');

// Create a table
await db.exec(`
  CREATE TABLE IF NOT EXISTS posts (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    title TEXT NOT NULL,
    content TEXT,
    created_at DATETIME DEFAULT CURRENT_TIMESTAMP
  )
`);

// Insert a post
const insertPost = db.prepare('INSERT INTO posts (title, content) VALUES (?, ?)');
const result = await insertPost.run('Hello World', 'This is my first blog post!');

console.log(`Inserted post with ID: ${result.lastInsertRowid}`);
```

### Transactions

```javascript
import { connect } from '@tursodatabase/database-wasm';

const db = await connect('transactions.db');

// Using transactions for atomic operations
const transaction = db.transactionAsync(async (txn, users) => {
  const insert = await txn.prepare('INSERT INTO users (name, email) VALUES (?, ?)');
  for (const user of users) {
    await insert.run(user.name, user.email);
  }
});

// Execute transaction
await transaction([
  { name: 'Alice', email: 'alice@example.com' },
  { name: 'Bob', email: 'bob@example.com' }
]);
```

## API Reference

For complete API documentation, see [JavaScript API Reference](https://github.com/tursodatabase/turso/blob/main/docs/javascript-api-reference.md).

## Related Packages

* The [@tursodatabase/serverless](https://www.npmjs.com/package/@tursodatabase/serverless) package provides a serverless driver with the same API.
* The [@tursodatabase/sync](https://www.npmjs.com/package/@tursodatabase/sync) package provides bidirectional sync between a local Turso database and Turso Cloud. 

## License

This project is licensed under the [MIT license](https://github.com/tursodatabase/turso/blob/main/LICENSE.md).

## Support

- [GitHub Issues](https://github.com/tursodatabase/turso/issues)
- [Documentation](https://docs.turso.tech)
- [Discord Community](https://tur.so/discord)

---

## File: bindings/javascript/packages/native/README.md

---

## About

This package is the Turso embedded database library for JavaScript in Node.

Turso Database runs in production today at multiple organizations. It has not yet reached 1.0, so as with any database we recommend keeping backups — see the [FAQ](https://github.com/tursodatabase/turso#faq) for where the project stands.

## Features

- **SQLite compatible:** SQLite query language and file format support ([status](https://github.com/tursodatabase/turso/blob/main/COMPAT.md)).
- **In-process**: No network overhead, runs directly in your Node.js process
- **TypeScript support**: Full TypeScript definitions included
- **Cross-platform**: Supports Linux (x86 and arm64), macOS, Windows (browser is supported in the separate package `@tursodatabase/database-wasm` package)

## Installation

```bash
npm install @tursodatabase/database
```

## Getting Started

### In-Memory Database

```javascript
import { connect } from '@tursodatabase/database';

// Create an in-memory database
const db = await connect(':memory:');

// Create a table
await db.exec('CREATE TABLE users (id INTEGER PRIMARY KEY, name TEXT, email TEXT)');

// Insert data
const insert = db.prepare('INSERT INTO users (name, email) VALUES (?, ?)');
await insert.run('Alice', 'alice@example.com');
await insert.run('Bob', 'bob@example.com');

// Query data
const users = await db.prepare('SELECT * FROM users').all();
console.log(users);
// Output: [
//   { id: 1, name: 'Alice', email: 'alice@example.com' },
//   { id: 2, name: 'Bob', email: 'bob@example.com' }
// ]
```

### File-Based Database

```javascript
import { connect } from '@tursodatabase/database';

// Create or open a database file
const db = await connect('my-database.db');

// Create a table
await db.exec(`
  CREATE TABLE IF NOT EXISTS posts (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    title TEXT NOT NULL,
    content TEXT,
    created_at DATETIME DEFAULT CURRENT_TIMESTAMP
  )
`);

// Insert a post
const insertPost = db.prepare('INSERT INTO posts (title, content) VALUES (?, ?)');
const result = await insertPost.run('Hello World', 'This is my first blog post!');

console.log(`Inserted post with ID: ${result.lastInsertRowid}`);
```

### Transactions

```javascript
import { connect } from '@tursodatabase/database';

const db = await connect('transactions.db');

// Using transactions for atomic operations
const transaction = db.transactionAsync(async (txn, users) => {
  const insert = await txn.prepare('INSERT INTO users (name, email) VALUES (?, ?)');
  for (const user of users) {
    await insert.run(user.name, user.email);
  }
});

// Execute transaction
await transaction([
  { name: 'Alice', email: 'alice@example.com' },
  { name: 'Bob', email: 'bob@example.com' }
]);
```

## API Reference

For complete API documentation, see [JavaScript API Reference](https://github.com/tursodatabase/turso/blob/main/docs/javascript-api-reference.md).

## Related Packages

* The [@tursodatabase/serverless](https://www.npmjs.com/package/@tursodatabase/serverless) package provides a serverless driver with the same API.
* The [@tursodatabase/sync](https://www.npmjs.com/package/@tursodatabase/sync) package provides bidirectional sync between a local Turso database and Turso Cloud. 

## License

This project is licensed under the [MIT license](https://github.com/tursodatabase/turso/blob/main/LICENSE.md)

## Support

- [GitHub Issues](https://github.com/tursodatabase/turso/issues)
- [Documentation](https://docs.turso.tech)
- [Discord Community](https://tur.so/discord)

---

## File: bindings/javascript/packages/common/README.md

## About

This package is the Turso embedded database common JS library which is shared between final builds for Node and Browser.

Do not use this package directly - instead you must use `@tursodatabase/database` or `@tursodatabase/database-wasm`.

Turso Database runs in production today at multiple organizations. It has not yet reached 1.0, so as with any database we recommend keeping backups — see the [FAQ](https://github.com/tursodatabase/turso#faq) for where the project stands.

---

## File: bindings/javascript/sync/packages/wasm/README.md

---

## About

This package is the Turso embedded database library for JavaScript in Browser.

Turso Database runs in production today at multiple organizations. It has not yet reached 1.0, so as with any database we recommend keeping backups — see the [FAQ](https://github.com/tursodatabase/turso#faq) for where the project stands.

## Features

- **SQLite compatible:** SQLite query language and file format support ([status](https://github.com/tursodatabase/turso/blob/main/COMPAT.md)).
- **In-process**: No network overhead, runs directly in your Node.js process
- **TypeScript support**: Full TypeScript definitions included

## Installation

```bash
npm install @tursodatabase/database-wasm
```

## Getting Started

### In-Memory Database

```javascript
import { connect } from '@tursodatabase/database-wasm';

// Create an in-memory database
const db = await connect(':memory:');

// Create a table
await db.exec('CREATE TABLE users (id INTEGER PRIMARY KEY, name TEXT, email TEXT)');

// Insert data
const insert = db.prepare('INSERT INTO users (name, email) VALUES (?, ?)');
await insert.run('Alice', 'alice@example.com');
await insert.run('Bob', 'bob@example.com');

// Query data
const users = await db.prepare('SELECT * FROM users').all();
console.log(users);
// Output: [
//   { id: 1, name: 'Alice', email: 'alice@example.com' },
//   { id: 2, name: 'Bob', email: 'bob@example.com' }
// ]
```

### File-Based Database

```javascript
import { connect } from '@tursodatabase/database-wasm';

// Create or open a database file
const db = await connect('my-database.db');

// Create a table
await db.exec(`
  CREATE TABLE IF NOT EXISTS posts (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    title TEXT NOT NULL,
    content TEXT,
    created_at DATETIME DEFAULT CURRENT_TIMESTAMP
  )
`);

// Insert a post
const insertPost = db.prepare('INSERT INTO posts (title, content) VALUES (?, ?)');
const result = await insertPost.run('Hello World', 'This is my first blog post!');

console.log(`Inserted post with ID: ${result.lastInsertRowid}`);
```

### Transactions

```javascript
import { connect } from '@tursodatabase/database-wasm';

const db = await connect('transactions.db');

// Using transactions for atomic operations
const transaction = db.transactionAsync(async (txn, users) => {
  const insert = await txn.prepare('INSERT INTO users (name, email) VALUES (?, ?)');
  for (const user of users) {
    await insert.run(user.name, user.email);
  }
});

// Execute transaction
await transaction([
  { name: 'Alice', email: 'alice@example.com' },
  { name: 'Bob', email: 'bob@example.com' }
]);
```

## API Reference

For complete API documentation, see [JavaScript API Reference](https://github.com/tursodatabase/turso/blob/main/docs/javascript-api-reference.md).

## Related Packages

* The [@tursodatabase/serverless](https://www.npmjs.com/package/@tursodatabase/serverless) package provides a serverless driver with the same API.
* The [@tursodatabase/sync](https://www.npmjs.com/package/@tursodatabase/sync) package provides bidirectional sync between a local Turso database and Turso Cloud. 

## License

This project is licensed under the [MIT license](https://github.com/tursodatabase/turso/blob/main/LICENSE.md).

## Support

- [GitHub Issues](https://github.com/tursodatabase/turso/issues)
- [Documentation](https://docs.turso.tech)
- [Discord Community](https://tur.so/discord)

---

## File: bindings/javascript/sync/packages/native/README.md

---

## About

This package is the Turso embedded database library for JavaScript in Node.

Turso Database runs in production today at multiple organizations. It has not yet reached 1.0, so as with any database we recommend keeping backups — see the [FAQ](https://github.com/tursodatabase/turso#faq) for where the project stands.

## Features

- **SQLite compatible:** SQLite query language and file format support ([status](https://github.com/tursodatabase/turso/blob/main/COMPAT.md)).
- **In-process**: No network overhead, runs directly in your Node.js process
- **TypeScript support**: Full TypeScript definitions included
- **Cross-platform**: Supports Linux (x86 and arm64), macOS, Windows (browser is supported in the separate package `@tursodatabase/database-wasm` package)

## Installation

```bash
npm install @tursodatabase/database
```

## Getting Started

### In-Memory Database

```javascript
import { connect } from '@tursodatabase/database';

// Create an in-memory database
const db = await connect(':memory:');

// Create a table
await db.exec('CREATE TABLE users (id INTEGER PRIMARY KEY, name TEXT, email TEXT)');

// Insert data
const insert = db.prepare('INSERT INTO users (name, email) VALUES (?, ?)');
await insert.run('Alice', 'alice@example.com');
await insert.run('Bob', 'bob@example.com');

// Query data
const users = await db.prepare('SELECT * FROM users').all();
console.log(users);
// Output: [
//   { id: 1, name: 'Alice', email: 'alice@example.com' },
//   { id: 2, name: 'Bob', email: 'bob@example.com' }
// ]
```

### File-Based Database

```javascript
import { connect } from '@tursodatabase/database';

// Create or open a database file
const db = await connect('my-database.db');

// Create a table
await db.exec(`
  CREATE TABLE IF NOT EXISTS posts (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    title TEXT NOT NULL,
    content TEXT,
    created_at DATETIME DEFAULT CURRENT_TIMESTAMP
  )
`);

// Insert a post
const insertPost = db.prepare('INSERT INTO posts (title, content) VALUES (?, ?)');
const result = await insertPost.run('Hello World', 'This is my first blog post!');

console.log(`Inserted post with ID: ${result.lastInsertRowid}`);
```

### Transactions

```javascript
import { connect } from '@tursodatabase/database';

const db = await connect('transactions.db');

// Using transactions for atomic operations
const transaction = db.transactionAsync(async (txn, users) => {
  const insert = await txn.prepare('INSERT INTO users (name, email) VALUES (?, ?)');
  for (const user of users) {
    await insert.run(user.name, user.email);
  }
});

// Execute transaction
await transaction([
  { name: 'Alice', email: 'alice@example.com' },
  { name: 'Bob', email: 'bob@example.com' }
]);
```

## API Reference

For complete API documentation, see [JavaScript API Reference](https://github.com/tursodatabase/turso/blob/main/docs/javascript-api-reference.md).

## Related Packages

* The [@tursodatabase/serverless](https://www.npmjs.com/package/@tursodatabase/serverless) package provides a serverless driver with the same API.
* The [@tursodatabase/sync](https://www.npmjs.com/package/@tursodatabase/sync) package provides bidirectional sync between a local Turso database and Turso Cloud. 

## License

This project is licensed under the [MIT license](https://github.com/tursodatabase/turso/blob/main/LICENSE.md).

## Support

- [GitHub Issues](https://github.com/tursodatabase/turso/issues)
- [Documentation](https://docs.turso.tech)
- [Discord Community](https://tur.so/discord)

---

## File: bindings/javascript/sync/packages/common/README.md

## About

This package is the Turso Sync common JS library which is shared between final builds for Node and Browser.

Do not use this package directly - instead you must use `@tursodatabase/sync` or `@tursodatabase/sync-wasm`.

Turso Database runs in production today at multiple organizations. It has not yet reached 1.0, so as with any database we recommend keeping backups — see the [FAQ](https://github.com/tursodatabase/turso#faq) for where the project stands.

---

## File: bindings/javascript/sync/README.md

---

## About

This package is for syncing local Turso databases to the Turso Cloud and back.

Turso Database runs in production today at multiple organizations. It has not yet reached 1.0, so as with any database we recommend keeping backups — see the [FAQ](https://github.com/tursodatabase/turso#faq) for where the project stands.

## Installation

```bash
npm install @tursodatabase/sync
```

## Getting Started

To sync a database hosted at [Turso Cloud](https://turso.tech):

```js
import { connect } from '@tursodatabase/sync';

const db = await connect({
    path: 'local.db',                // path used as a prefix for local files created by sync-engine
    url: 'https://<db>.turso.io',    // URL of the remote database: turso db show <db>
    authToken: '...',                // auth token issued from the Turso Cloud: turso db tokens create <db>
    clientName: 'turso-sync-example' // arbitrary client name
});

// db has same functions as Database class from @tursodatabase/database package but adds few more methods for sync:
await db.pull(); // pull changes from the remote
await db.push(); // push changes to the remote
await db.sync(); // pull & push changes
```

## Related Packages

* The [@tursodatabase/database](https://www.npmjs.com/package/@tursodatabase/database) package provides the Turso in-memory database, compatible with SQLite.
* The [@tursodatabase/serverless](https://www.npmjs.com/package/@tursodatabase/serverless) package provides a serverless driver with the same API.

## License

This project is licensed under the [MIT license](https://github.com/tursodatabase/turso/blob/main/LICENSE.md).

## Support

- [GitHub Issues](https://github.com/tursodatabase/turso/issues)
- [Documentation](https://docs.turso.tech)
- [Discord Community](https://tur.so/discord)

## 2. Official Technical Reference & Guides (tursodatabase/turso-docs)

## File: agentfs/guides/auditing.mdx

---
title: Audit Filesystem Changes
sidebarTitle: Audit Filesystem Changes
---

AgentFS records every file operation and tool call, giving you complete visibility into agent behavior. This is essential for debugging, compliance, and understanding how agents work.

## Viewing the Timeline

See a chronological list of tool calls:

```bash
agentfs timeline my-session
```

Output:
```
ID   TOOL                 STATUS       DURATION STARTED
4    execute_code         pending            -- 2024-01-05 09:44:20
3    api_call             error           300ms 2024-01-05 09:44:15
2    read_file            success          50ms 2024-01-05 09:44:10
1    web_search           success        1200ms 2024-01-05 09:43:45
```

### Filtering Results

Show only specific tool types:
```bash
agentfs timeline my-session --filter web_search
```

Show only errors:
```bash
agentfs timeline my-session --status error
```

Limit number of entries:
```bash
agentfs timeline my-session --limit 20
```

### JSON Output

For programmatic analysis:
```bash
agentfs timeline my-session --format json
```

```json
[
  {
    "id": 1,
    "name": "web_search",
    "status": "success",
    "started_at": 1704447825,
    "completed_at": 1704447826,
    "duration_ms": 1200,
    "parameters": {"query": "AI agents"},
    "result": {"results": ["result1", "result2"]}
  }
]
```

## Inspecting Files

List all files in a session:
```bash
agentfs fs ls my-session
```

Output:
```
d artifacts
f config.json
f output.txt
```

List a subdirectory:
```bash
agentfs fs ls my-session /artifacts
```

Read file contents:
```bash
agentfs fs cat my-session /output.txt
```

## Viewing Changes (Diff)

See what changed compared to the original filesystem:

```bash
agentfs diff my-session
```

This shows:
- New files created
- Modified files
- Deleted files

## Querying with SQL

Since AgentFS uses SQLite, you can run arbitrary queries:

<Tabs>
  <Tab title="Turso">
    ```bash
    tursodb .agentfs/my-session.db
    ```
  </Tab>
  <Tab title="SQLite">
    ```bash
    sqlite3 .agentfs/my-session.db
    ```
  </Tab>
</Tabs>

Example queries:

```sql
-- Find all tool calls that took longer than 1 second
SELECT name, duration_ms
FROM toolcalls
WHERE duration_ms > 1000;

-- Count tool usage by type
SELECT name, COUNT(*) as count
FROM toolcalls
GROUP BY name
ORDER BY count DESC;

-- Find files modified in the last hour
SELECT path, mtime
FROM fs_inode
WHERE mtime > strftime('%s', 'now', '-1 hour');

-- Get total bytes written
SELECT SUM(size) as total_bytes
FROM fs_inode
WHERE mode & 0170000 = 0100000;  -- regular files only
```

## Use Cases

### Debugging Agent Failures

When an agent fails, use the timeline to understand what happened:

```bash
# See recent activity
agentfs timeline my-session --limit 20

# Focus on errors
agentfs timeline my-session --status error

# Check what files were created/modified
agentfs fs ls my-session
```

### Performance Analysis

Find slow operations:

```sql
SELECT name, AVG(duration_ms) as avg_ms, COUNT(*) as count
FROM toolcalls
GROUP BY name
ORDER BY avg_ms DESC;
```

### Compliance Auditing

Export a complete record of agent activity:

```bash
agentfs timeline my-session --format json > audit-log.json
```

## Next Steps

<CardGroup cols={2}>
  <Card title="Overlay Filesystem" icon="layer-group" href="/agentfs/guides/overlay">
    Understanding copy-on-write
  </Card>
  <Card title="Syncing" icon="cloud" href="/agentfs/guides/sync">
    Sync sessions to Turso Cloud
  </Card>
</CardGroup>

---

## File: agentfs/guides/mcp.mdx

---
title: MCP Server Integration
sidebarTitle: MCP Server Integration
---

AgentFS can run as an [MCP (Model Context Protocol)](https://modelcontextprotocol.io/) server, exposing filesystem and key-value operations to AI assistants like Claude Desktop.

## Starting the MCP Server

```bash
agentfs serve mcp my-agent
```

This starts an MCP server that exposes AgentFS tools over stdio.

## Available Tools

### Filesystem Tools

| Tool | Description |
|------|-------------|
| `read_file` | Read file contents |
| `write_file` | Write file contents |
| `readdir` | List directory contents |
| `mkdir` | Create directory |
| `remove` | Remove file or directory |
| `rename` | Rename file or directory |
| `stat` | Get file metadata |
| `access` | Check file access permissions |

### Key-Value Tools

| Tool | Description |
|------|-------------|
| `kv_get` | Get value by key |
| `kv_set` | Set key-value pair |
| `kv_delete` | Delete key |
| `kv_list` | List all keys |

## Limiting Exposed Tools

For security, you can limit which tools are available:

```bash
# Read-only mode
agentfs serve mcp my-agent --tools read_file,readdir,stat,kv_get,kv_list

# Filesystem only
agentfs serve mcp my-agent --tools read_file,write_file,readdir,mkdir,remove

# Key-value only
agentfs serve mcp my-agent --tools kv_get,kv_set,kv_delete,kv_list
```

## Security Considerations

<Warning>
The MCP server gives AI assistants direct access to the AgentFS filesystem. Consider these security practices:

- **Limit tools** - Only expose tools the assistant needs
- **Use overlays** - Create overlay filesystems instead of giving access to real directories
- **Review the agent database** - Check `.agentfs/*.db` periodically
</Warning>

## Debugging

Check if the MCP server is working:

```bash
# Run manually to see output
agentfs serve mcp my-agent

# Check if the database exists
ls -la .agentfs/my-agent.db
```

## Next Steps

<CardGroup cols={2}>
  <Card title="NFS Server" icon="network-wired" href="/agentfs/guides/nfs">
    Remote access via NFS
  </Card>
  <Card title="Copy-on-Write Overlays" icon="layer-group" href="/agentfs/guides/overlay">
    How isolation works
  </Card>
</CardGroup>

---

## File: agentfs/guides/nfs.mdx

---
title: NFS Server Access
sidebarTitle: NFS Server Access
---

AgentFS can expose filesystems over NFS, enabling remote access from other machines, containers, or virtual machines.

## Starting the NFS Server

```bash
agentfs serve nfs my-agent
```

By default, this listens on `127.0.0.1:11111`.

### Binding to All Interfaces

To allow remote access:

```bash
agentfs serve nfs my-agent --bind 0.0.0.0 --port 2049
```

<Warning>
Exposing NFS on `0.0.0.0` makes the filesystem accessible to anyone who can reach your machine. Use firewall rules or a VPN for production deployments.
</Warning>

## Mounting the Filesystem

### From the Same Machine

```bash
mkdir /mnt/agentfs
mount -t nfs -o vers=3,tcp,port=11111,mountport=11111,nolock 127.0.0.1:/ /mnt/agentfs
```

### From a Remote Machine

```bash
mount -t nfs -o vers=3,tcp,port=2049,mountport=2049,nolock server-ip:/ /mnt/agentfs
```

### Mount Options Explained

| Option | Description |
|--------|-------------|
| `vers=3` | Use NFSv3 protocol |
| `tcp` | Use TCP transport |
| `port=11111` | NFS server port |
| `mountport=11111` | Mount protocol port |
| `nolock` | Disable file locking (single-user) |

## Unmounting

```bash
umount /mnt/agentfs
```

If the mount is busy:

```bash
umount -f /mnt/agentfs  # Force unmount
# or
umount -l /mnt/agentfs  # Lazy unmount
```

## Next Steps

<CardGroup cols={2}>
  <Card title="MCP Server" icon="plug" href="/agentfs/guides/mcp">
    Expose AgentFS via MCP
  </Card>
  <Card title="Sync with Turso Cloud" icon="cloud" href="/agentfs/guides/sync">
    Back up and share agent state
  </Card>
</CardGroup>

---

## File: agentfs/guides/overlay.mdx

---
title: Copy-on-Write Overlays
sidebarTitle: Copy-on-Write Overlays
---

AgentFS uses an overlay filesystem to provide copy-on-write isolation. This lets agents freely modify files while keeping your original data safe.

## How Overlay Works

An overlay filesystem combines two layers:

```
┌────────────────────────────────────┐
│         Merged View (what you see) │
├────────────────────────────────────┤
│  Delta Layer (AgentFS database)    │  ← Writes go here
├────────────────────────────────────┤
│  Base Layer (original directory)   │  ← Read-only
└────────────────────────────────────┘
```

**Reading a file:**
1. Check delta layer first
2. If not found, read from base layer

**Writing a file:**
1. Copy file to delta layer (if from base)
2. Write changes to delta layer
3. Base layer is never modified

**Deleting a file:**
1. Create a "whiteout" marker in delta layer
2. File appears deleted in merged view
3. Original file in base layer is untouched

## Creating an Overlay Filesystem

### With `agentfs run`

The simplest way - automatically creates an overlay over your current directory:

```bash
cd /path/to/project
agentfs run /bin/bash
```

### With `agentfs init --base`

Create an overlay explicitly:

```bash
agentfs init my-overlay --base /path/to/project
```

Then mount it:

```bash
agentfs mount my-overlay ./workspace
```

Or run a command in it:

```bash
agentfs run --session my-overlay /bin/bash
```

## Viewing Changes

See what's different from the base:

```bash
agentfs diff my-overlay
```

## Practical Examples

### Safe Refactoring

Let an agent refactor your code without risk:

```bash
cd my-project
agentfs run --session refactor python3 refactor_agent.py

# Review what changed
agentfs diff refactor

# Happy? Apply changes manually or via script
# Not happy? Just delete the session
rm .agentfs/refactor.db
```

### Testing Destructive Operations

Try something dangerous safely:

```bash
agentfs run --session test /bin/bash
$ rm -rf src/  # Yikes!
$ exit

# Original files are fine
ls src/  # Still there!

# Only the overlay was affected
agentfs fs ls test  # Shows the deletion
```

### Parallel Experiments

Run multiple experiments on the same codebase:

```bash
# Experiment A
agentfs run --session exp-a python3 approach_a.py

# Experiment B (same base, different changes)
agentfs run --session exp-b python3 approach_b.py

# Compare results
agentfs diff exp-a
agentfs diff exp-b
```

## Storage Efficiency

The overlay only stores:
- **Modified files** - Full copy after first write
- **New files** - Stored entirely in delta
- **Deleted files** - Small whiteout marker

Original files are never duplicated. A 10GB project with 1MB of changes only uses ~1MB in the delta layer.

## Technical Details

### File Operations

| Operation | Behavior |
|-----------|----------|
| Read existing file | Pass through to base |
| Write existing file | Copy to delta, then write |
| Create new file | Write directly to delta |
| Delete file | Create whiteout in delta |
| Rename file | Delete old + create new |

### Whiteouts

When you delete a base file, AgentFS creates a "whiteout" - a marker that hides the file:

```sql
-- Whiteouts in the database
SELECT * FROM fs_inode WHERE whiteout = 1;
```

### Database Schema

The delta layer is stored in SQLite:

```sql
-- Files and directories
CREATE TABLE fs_inode (
    ino INTEGER PRIMARY KEY,
    parent_ino INTEGER,
    name TEXT,
    mode INTEGER,
    size INTEGER,
    ...
    whiteout INTEGER DEFAULT 0
);

-- File contents
CREATE TABLE fs_block (
    ino INTEGER,
    block_num INTEGER,
    data BLOB
);
```

See the [AgentFS Specification](https://github.com/tursodatabase/agentfs/blob/main/SPEC.md) for the complete schema.

## Next Steps

<CardGroup cols={2}>
  <Card title="Sessions" icon="clock" href="/agentfs/guides/sessions">
    Share state between agents
  </Card>
  <Card title="Syncing" icon="cloud" href="/agentfs/guides/sync">
    Sync overlays to Turso Cloud
  </Card>
</CardGroup>

---

## File: agentfs/guides/sandbox.mdx

---
title: Agentic Coding
sidebarTitle: Agentic Coding
---

AgentFS lets you run AI coding agents like Claude Code, Codex, and OpenCode in a sandboxed environment where file changes are isolated from your original source tree.

## Supported Agents

| Agent | Command |
|-------|---------|
| [Claude Code](https://code.claude.com/docs/en/overview) | `agentfs run claude` |
| [Codex](https://openai.com/codex/) | `agentfs run codex` |
| [OpenCode](https://opencode.ai/) | `agentfs run opencode` |
| Any CLI tool | `agentfs run <command>` |

## Workflow

Here's a typical agentic coding workflow. This example uses Claude Code, but the workflow is the same with OpenCode, Codex, and others.

### Step 1: Clone the Repository

Clone the git repository to a host directory. Keep this source tree clean from build artifacts. When there's a merge to main, pull to this repository to keep it up-to-date.

```bash
git clone https://github.com/tursodatabase/agentfs.git
cd agentfs
```

### Step 2: Start an AgentFS Session

Use `agentfs run` with the `--session` flag to start a session. Pick a name that can eventually become your git branch name.

<Tabs>
  <Tab title="Claude Code">
    ```bash
    agentfs run --session fix-bug-123 claude
    ```
  </Tab>
  <Tab title="Codex">
    ```bash
    agentfs run --session fix-bug-123 codex
    ```
  </Tab>
  <Tab title="OpenCode">
    ```bash
    agentfs run --session fix-bug-123 opencode
    ```
  </Tab>
</Tabs>

The agent now runs in a copy-on-write environment. Your original source tree remains untouched while the agent works.

### Step 3 (Optional): Manual Investigation

If the agent does something unusual, open another terminal and join the same session to investigate:

```bash
agentfs run --session fix-bug-123 bash
```

The filesystem is shared between the shell and the agent. You can browse files, run tests, or check what's happening while the agent works.

### Step 4: Push to Branch

Once the agent has completed the work, ask it to create a branch, commit the code, and push:

> "Create a branch called fix-bug-123, commit these changes, and push to origin"

You can then create a PR manually from the pushed branch.

## Why This Workflow?

- **Clean source tree** - Your original clone stays pristine and easy to update from upstream
- **Isolated changes** - Each task gets its own session, preventing cross-contamination
- **Easy investigation** - Join any session to see what's happening in real-time
- **Standard git flow** - Push branches and create PRs as usual

## Next Steps

<CardGroup cols={2}>
  <Card title="Multi-Agent Sessions" icon="clock" href="/agentfs/guides/sessions">
    Share state between agents and terminals
  </Card>
  <Card title="Auditing" icon="magnifying-glass" href="/agentfs/guides/auditing">
    Inspect what an agent did with diff and timeline
  </Card>
</CardGroup>

---

## File: agentfs/guides/sessions.mdx

---
title: Shared Agent Sessions
sidebarTitle: Shared Agent Sessions
---

Named sessions let you share a filesystem between multiple agents, terminals, or runs. All participants see the same copy-on-write view of your project.

## Creating a Session

Use `--session` to create a named session:

```bash
agentfs run --session my-project /bin/bash
```

This creates a session called `my-project`. All changes are stored in `.agentfs/my-project.db`.

## Resuming a Session

Run the same command to resume where you left off:

```bash
# First run - make some changes
agentfs run --session my-project /bin/bash
$ echo "hello" > test.txt
$ exit

# Second run - changes are still there
agentfs run --session my-project /bin/bash
$ cat test.txt
hello
```

## Multi-Terminal Collaboration

Multiple terminals can share the same session simultaneously:

```bash
# Terminal 1
agentfs run --session shared-work /bin/bash

# Terminal 2 - joins the same filesystem
agentfs run --session shared-work python3 agent.py

# Terminal 3 - also sees the same files
agentfs run --session shared-work vim
```

All terminals share the same copy-on-write filesystem. Changes made in one terminal are immediately visible in others.

## Use Cases

### Iterative Development

Work on a task across multiple sessions:

```bash
# Morning session
agentfs run --session feature-x /bin/bash
# ... work on the feature, then exit for lunch

# Afternoon session - continue where you left off
agentfs run --session feature-x /bin/bash
```

### Safe Experimentation

Create a session, try something risky, then decide whether to keep it:

```bash
agentfs run --session experiment /bin/bash
# ... try some changes

# Option A: Happy with changes
agentfs diff experiment  # Review
# Apply changes to real filesystem (manually or via script)

# Option B: Discard everything
rm .agentfs/experiment.db
```

### Agent Supervision

Run an agent and monitor its work from another terminal:

```bash
# Terminal 1: Run the agent
agentfs run --session agent-task python3 agent.py

# Terminal 2: Watch what it's doing
agentfs run --session agent-task /bin/bash
$ watch ls -la  # See files being created
$ tail -f agent.log  # Monitor logs
```

## Managing Sessions

List files in a session:
```bash
agentfs fs ls my-session
```

View session changes:
```bash
agentfs diff my-session
```

Delete a session:
```bash
rm .agentfs/my-session.db
```

## Session Storage

Sessions are stored as SQLite databases in `.agentfs/`:

```
.agentfs/
├── my-project.db
├── experiment.db
└── shared-work.db
```

Each database contains:
- All modified files
- Deleted file markers (whiteouts)
- Tool call audit log
- Key-value store data

## Next Steps

<CardGroup cols={2}>
  <Card title="Auditing" icon="list" href="/agentfs/guides/auditing">
    Inspect what happened in a session
  </Card>
  <Card title="Overlay Filesystem" icon="layer-group" href="/agentfs/guides/overlay">
    How copy-on-write works
  </Card>
</CardGroup>

---

## File: agentfs/guides/sync.mdx

---
title: Sync with Turso Cloud
sidebarTitle: Sync with Turso Cloud
---

AgentFS can sync with [Turso Cloud](https://turso.tech), enabling backup, collaboration, and distributed agent deployments.

## Setting Up Sync

### 1. Create a Turso Database

If you don't have a Turso account, [sign up](https://turso.tech) first.

Create a database for your agent:

```bash
turso db create my-agent-db
```

Get the database URL:

```bash
turso db show my-agent-db --url
# Output: libsql://my-agent-db-username.turso.io
```

### 2. Initialize with Sync

Create a new agent filesystem with sync enabled:

```bash
agentfs init my-agent --sync-remote-url libsql://my-agent-db-username.turso.io
```

Or add sync to an existing agent:

```bash
# Edit the database to add sync configuration
# (Feature coming soon)
```

## Sync Commands

### Pull Remote Changes

Download changes from Turso Cloud:

```bash
agentfs sync my-agent pull
```

### Push Local Changes

Upload local changes to Turso Cloud:

```bash
agentfs sync my-agent push
```

### View Sync Status

Check sync statistics:

```bash
agentfs sync my-agent stats
```

### Create Checkpoint

Force a sync checkpoint:

```bash
agentfs sync my-agent checkpoint
```

## Use Cases

### Backup and Recovery

Automatically back up agent state:

```bash
# After important work
agentfs sync my-agent push

# On a new machine
agentfs init my-agent --sync-remote-url libsql://...
agentfs sync my-agent pull
```

### Multi-Machine Agents

Run agents on multiple machines with shared state:

```bash
# Machine A
agentfs run --session shared-agent python3 agent.py
agentfs sync shared-agent push

# Machine B
agentfs sync shared-agent pull
agentfs run --session shared-agent python3 agent.py
```

## Partial Sync

For large filesystems, use partial sync to only fetch what's needed:

```bash
agentfs init my-agent \
  --sync-remote-url libsql://... \
  --sync-partial-prefetch \
  --sync-partial-segment-size 1000
```

### Partial Sync Options

| Option | Description |
|--------|-------------|
| `--sync-partial-prefetch` | Enable prefetching |
| `--sync-partial-segment-size` | Segment size for partial sync |
| `--sync-partial-bootstrap-query` | Custom bootstrap query |
| `--sync-partial-bootstrap-length` | Bootstrap prefix length |

## Authentication

Sync requires a Turso auth token. Set it via environment variable:

```bash
export TURSO_AUTH_TOKEN=$(turso db tokens create my-agent-db)
```

Or create a long-lived token:

```bash
turso db tokens create my-agent-db --expiration none
```

## Conflict Resolution

AgentFS uses last-write-wins for conflicts. If the same file is modified on multiple machines:

1. Push from Machine A succeeds
2. Push from Machine B fails (conflict)
3. Machine B must pull first, then push

## Next Steps

<CardGroup cols={2}>
  <Card title="Turso Cloud" icon="cloud" href="https://turso.tech">
    Learn more about Turso Cloud
  </Card>
  <Card title="NFS Server" icon="network-wired" href="/agentfs/guides/nfs">
    Remote access via NFS
  </Card>
</CardGroup>

---

## File: guides/agent-databases.mdx

---
title: Agent Databases
---


Looking for a complete agent state management solution? Check out [AgentFS](/agentfs/introduction) - our specialized SDK designed specifically for AI agents, offering filesystem operations, key-value storage, and automatic tool call tracking in a single database file.


AI agents need databases to store context, track state, and maintain memory across executions. Turso Database offers two powerful approaches:

- **Embedded Databases** for local-first agent processing, and

- **Turso Sync** for distributed agent coordination with cloud persistence.

## Embedded Databases (Local-First)

Use embedded databases for agents that process data locally within a single workflow, need offline-capable access, or work with temporary data without sharing state with other agents.

Local data pipelines, on-device processing of sensitive data, development/testing workflows, and single-agent analysis tasks.

```javascript
import { connect } from "@tursodatabase/database";

// Create a local embedded database for this agent
const db = await connect("agent-workflow.db");

// Agent can now store and query data locally
const stmt = db.prepare(`
  CREATE TABLE IF NOT EXISTS steps (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    action TEXT NOT NULL,
    result TEXT,
    timestamp DATETIME DEFAULT CURRENT_TIMESTAMP
  )
`);
stmt.run();

// Track agent workflow steps
db.prepare("INSERT INTO steps (action, result) VALUES (?, ?)").run(
  "fetch_data",
  "success",
);
```

Benefit from zero network latency, full offline capability, complete data privacy, and simple single-file deployment.



Data is isolated to this agent instance with no built-in multi-agent collaboration or cross-session persistence (unless you manage the file yourself).



## Turso Sync (Cloud-Connected)

Use Turso Sync for agents that need persistent memory across sessions, coordinate with other agents, or require cloud-backed durability for long-running workflows.

💡 Conversational agents with session memory, multi-agent coordination systems, long-running workflows with recovery needs, and agents reporting to central systems.

```javascript
import { connect } from "@tursodatabase/database";

// Connect to a synced database (embedded locally, synced to Turso Cloud)
const db = await connect({
  path: "agent-memory.db",
  url: "https://your-database.turso.io",
  authToken: "your-auth-token",
  sync: "full", // Bidirectional sync
});

// Agent can access data from previous sessions or other agents
const previousContext = db
  .prepare("SELECT * FROM conversation_history WHERE session_id = ?")
  .all("session-123");

// New data is automatically synced to cloud and other agent instances
db.prepare("INSERT INTO agent_actions (agent_id, action) VALUES (?, ?)").run(
  "agent-1",
  "processed_document",
);

// Manually trigger sync if needed
await db.sync();
```

💡 Persistent memory across restarts, multi-agent coordination via shared state, cloud backup and durability, with fast local reads and background sync.



**Sync modes:** `sync` (bidirectional), `pull` (cloud → agent), `push` (agent → cloud).



## Multi-Agent Architectures

### Pattern 1: Isolated Agent Databases

Each agent gets its own embedded database. Best for independent agents with no shared state.

```javascript
// Agent 1
const agent1DB = await connect("agent-1.db");

// Agent 2
const agent2DB = await connect("agent-2.db");
```



Independent agents performing separate tasks with no coordination needs and maximum isolation.



### Pattern 2: Shared Database with Sync

Multiple agents connect to the same synced database. Best for coordinated agent systems.

```javascript
// Agent 1 connects and writes tasks
const agent1DB = await connect({
  path: "agent-1-local.db",
  url: "https://shared-tasks.turso.io",
  authToken: process.env.TURSO_TOKEN,
  sync: "full",
});

agent1DB.prepare("INSERT INTO tasks (status) VALUES (?)").run("pending");

// Agent 2 connects to same database and reads tasks
const agent2DB = await connect({
  path: "agent-2-local.db",
  url: "https://shared-tasks.turso.io", // Same database
  authToken: process.env.TURSO_TOKEN,
  sync: "full",
});

const pendingTasks = agent2DB
  .prepare("SELECT * FROM tasks WHERE status = ?")
  .all("pending");
```

💡 Agents coordinating work through shared task queues or a common knowledge base.

### Pattern 3: Hub-and-Spoke

A central synced database with agents pushing results and pulling new tasks.

```javascript
// Worker agents push results only
const workerDB = await connect({
  path: "worker-local.db",
  url: "https://hub.turso.io",
  authToken: process.env.WORKER_TOKEN,
  sync: "push", // Only push results to cloud
});

// Coordinator agent pulls from all workers
const coordinatorDB = await connect({
  path: "coordinator-local.db",
  url: "https://hub.turso.io",
  authToken: process.env.COORDINATOR_TOKEN,
  sync: "pull", // Only pull data from cloud
});
```

💡 Many worker agents feeding results to a central coordinator for monitoring or aggregation with unidirectional data flow.

## Database-Per-Agent Pattern

For systems managing many agents, you can create individual databases for each agent using the [Platform API](https://docs.turso.tech/api-reference):

```javascript
import { createClient } from "@tursodatabase/api";

const turso = createClient({
  token: process.env.TURSO_PLATFORM_API_TOKEN,
  org: process.env.TURSO_ORG_NAME,
});

// Create a dedicated database for each agent
async function provisionAgentDatabase(agentId) {
  const database = await turso.databases.create(`agent-${agentId}`, {
    group: "default",
  });

  console.log(`Database created for agent ${agentId}: ${database.Name}`);
  return database;
}
```



Complete isolation between agents, independent scaling per agent, improved security (compromised agent only affects one database), and easy cleanup when agents are retired.



## Examples

Explore these examples to see agent database patterns in action:

- [sync-node](https://github.com/tursodatabase/turso/blob/main/examples/javascript/sync-node) — Node.js with bidirectional sync to Turso Cloud
- [sync-wasm-vite](https://github.com/tursodatabase/turso/blob/main/examples/javascript/sync-wasm-vite) — Browser (WASM) with bidirectional sync to Turso Cloud
- [database-node](https://github.com/tursodatabase/turso/blob/main/examples/javascript/database-node) — Node.js, local file database (no sync)
- [database-wasm-vite](https://github.com/tursodatabase/turso/blob/main/examples/javascript/database-wasm-vite) — Browser (WASM), local database in the browser

---

## File: guides/ai-memory.mdx

---
title: AI Memory
---

AI agents start every session from scratch. A persistent memory system lets agents store lessons and retrieve relevant context via vector search. Turso's embedded database with built-in vector functions makes this possible in a single local file.

This guide covers the schema and queries for building a memory system with vector similarity search.

## Schema

At its simplest, a memory system needs just two tables: one for memories and one for tracking which memories were used in which tasks.

```sql
CREATE TABLE IF NOT EXISTS memories (
    id              TEXT PRIMARY KEY,
    content         TEXT NOT NULL,
    embedding       F8_BLOB(384),
    category        TEXT NOT NULL,
    created_at      INTEGER NOT NULL,
    last_retrieved  INTEGER,
    retrieval_count INTEGER DEFAULT 0,
    source_task     TEXT
);

CREATE TABLE IF NOT EXISTS tasks (
    id               TEXT PRIMARY KEY,
    description      TEXT,
    embedding        F8_BLOB(384),
    started_at       INTEGER,
    finished_at      INTEGER
);
```

- **`memories`** stores each lesson with its vector embedding and a category (e.g. `correction`, `insight`, `user`, `discovery`). The embedding is a 384-dimensional int8-quantized vector (`F8_BLOB(384)`).
- **`tasks`** records each task the agent worked on, linking task descriptions to their embeddings for retrieval.

## Connecting

```javascript
import { connect } from "@tursodatabase/database";

const db = await connect(".memory/agent.db");
await db.exec(SCHEMA);
```

## Storing a memory

When the agent learns something — a correction, a user preference, an insight — store it with an embedding. Use `vector8()` to convert a JSON float array into an int8-quantized vector:

```sql
INSERT INTO memories (id, content, embedding, category, created_at, source_task)
VALUES (?, ?, vector8(?), ?, ?, ?);
```

The parameter for `vector8()` is a JSON-stringified float array (e.g. 384 dimensions from a model like `all-MiniLM-L6-v2`). Turso handles the quantization internally:

```javascript
db.prepare(`
  INSERT INTO memories (id, content, embedding, category, created_at)
  VALUES (?, ?, vector8(?), ?, ?)
`).run(id, content, JSON.stringify(Array.from(embedding)), "correction", Date.now());
```

## Retrieving relevant memories

When a new task starts, find the most relevant memories using Turso's `vector_distance_cos()` function:

```sql
SELECT id, content, category, created_at, retrieval_count,
       vector_distance_cos(embedding, vector8(?)) AS distance
FROM memories
WHERE embedding IS NOT NULL
ORDER BY distance ASC
LIMIT ?;
```



`vector_distance_cos()` returns cosine **distance** (0 = identical, 2 = opposite). Lower is better. To convert to similarity: `1.0 - distance`.



After retrieval, update the memory's metadata:

```sql
UPDATE memories SET last_retrieved = ?, retrieval_count = retrieval_count + 1
WHERE id = ?;
```

## Correcting wrong memories

When a memory turns out to be wrong, delete it and store a corrected version:

```sql
DELETE FROM memories WHERE id = ?;

INSERT INTO memories (id, content, embedding, category, created_at)
VALUES (?, ?, vector8(?), 'correction', ?);
```

## Task tracking

Record tasks to understand what the agent has been working on:

```sql
-- Start a task
INSERT INTO tasks (id, description, embedding, started_at)
VALUES (?, ?, vector8(?), ?);

-- Complete a task
UPDATE tasks SET finished_at = ? WHERE id = ?;
```

## Purging old memories

Remove memories that have been around a long time but are never retrieved:

```sql
DELETE FROM memories
WHERE retrieval_count = 0 AND created_at < ?;
```

## Key design points

- **Vector search** uses Turso's `vector8()` and `vector_distance_cos()` for cosine similarity directly in SQL. Int8 quantization reduces storage by 75% compared to float32 with minimal impact on search quality.
- For small per-project datasets, a full table scan with `ORDER BY distance LIMIT k` is fast enough without a vector index.
- Everything runs in a single embedded database file with no external services.

## Going further

The schema above is deliberately minimal. In practice you will want to experiment with strategies for keeping the memory store useful as it grows. Some ideas:

- **Weighted memories** — add a `weight REAL` column and boost or penalize memories based on whether the agent found them useful after retrieval. Use an exponential moving average to update weights over time.
- **Time decay** — multiply a recency factor into the retrieval ranking so that stale memories rank lower. For example: `(1.0 - distance) * POWER(0.95, days_since_last_retrieved)`.
- **Garbage collection** — periodically remove memories with low weight and high retrieval count (retrieved often, never useful), or memories that have never been retrieved after a threshold period.
- **Task scoring** — track outcome metrics (tokens used, errors, corrections) per task and use them to compute a credit signal for the memories that were retrieved during that task.
- **Retrieval attribution** — add a join table `(memory_id, task_id, similarity, credit)` to record exactly which memories were used in each task and how they were rated.

<Warning>

There is no single best approach — the right strategy depends on your agent's workload, how often memories are created, and how aggressively you want to prune. Start simple and iterate.

</Warning>

## Example

[memelord](https://github.com/glommer/memelord) is an MCP server and hooks system that implements this pattern with reinforcement learning and weight decay as a persistent memory layer for AI coding agents.

---

## File: guides/code-indexing.mdx

---
title: Code Indexing
---

AI coding agents work better when they can search a codebase semantically ("find the authentication logic") rather than just by filename or grep. A code index backed by Turso can combine full-text search over identifiers with vector similarity search over embeddings, all in a single embedded database.

This guide covers the schema and queries for building a code indexer with both FTS and vector search.

## Schema

```sql
CREATE TABLE IF NOT EXISTS codebases (
    id          INTEGER PRIMARY KEY AUTOINCREMENT,
    root_path   TEXT NOT NULL UNIQUE,
    name        TEXT NOT NULL DEFAULT '',
    indexed_at  INTEGER NOT NULL DEFAULT 0
);

CREATE TABLE IF NOT EXISTS chunks (
    id              INTEGER PRIMARY KEY AUTOINCREMENT,
    codebase_id     INTEGER NOT NULL REFERENCES codebases(id),
    file_path       TEXT NOT NULL,
    chunk_key       TEXT NOT NULL UNIQUE,
    language        TEXT NOT NULL,
    kind            TEXT NOT NULL,
    name            TEXT NOT NULL DEFAULT '',
    signature       TEXT NOT NULL DEFAULT '',
    snippet         TEXT NOT NULL,
    start_line      INTEGER NOT NULL,
    end_line        INTEGER NOT NULL,
    file_hash       TEXT NOT NULL,
    indexed_at      INTEGER NOT NULL,
    embedding       F8_BLOB(384),
    embedding_model TEXT DEFAULT ''
);

CREATE TABLE IF NOT EXISTS indexed_files (
    id          INTEGER PRIMARY KEY AUTOINCREMENT,
    codebase_id INTEGER NOT NULL REFERENCES codebases(id),
    file_path   TEXT NOT NULL,
    file_hash   TEXT NOT NULL,
    chunk_count INTEGER NOT NULL DEFAULT 0,
    indexed_at  INTEGER NOT NULL,
    UNIQUE(codebase_id, file_path)
);
```

### How it fits together

- **`codebases`** registers each project root. A single database can index multiple codebases.
- **`chunks`** stores individual semantic units extracted from source files — functions, structs, classes, impl blocks, etc. Each chunk has a `name`, `signature`, code `snippet`, line range, and optionally a vector `embedding`. The `chunk_key` is a unique identifier (e.g. `file_path::kind::name`) for upsert operations.
- **`indexed_files`** tracks which files have been indexed and their content hashes, enabling incremental re-indexing — only changed files are re-processed.

## Connecting

The FTS index features require an experimental flag at connection time:

```javascript
import { connect } from "@tursodatabase/database";

const db = await connect(".index/code.db", {
  experimental: ["index_method"],
});
await db.exec(SCHEMA);
```



The `experimental: ["index_method"]` flag enables Turso's `USING fts` index syntax and the `fts_match()` / `fts_score()` functions.



## Indexing files

### Upserting chunks

When a file is parsed, upsert its chunks. Setting `embedding = NULL` on conflict forces re-embedding when content changes:

```sql
INSERT INTO chunks (codebase_id, file_path, chunk_key, language, kind, name,
                    signature, snippet, start_line, end_line, file_hash, indexed_at)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
ON CONFLICT(chunk_key) DO UPDATE SET
  language = excluded.language,
  kind = excluded.kind,
  name = excluded.name,
  signature = excluded.signature,
  snippet = excluded.snippet,
  start_line = excluded.start_line,
  end_line = excluded.end_line,
  file_hash = excluded.file_hash,
  indexed_at = excluded.indexed_at,
  embedding = NULL,
  embedding_model = '';
```

### Tracking indexed files

```sql
INSERT INTO indexed_files (codebase_id, file_path, file_hash, chunk_count, indexed_at)
VALUES (?, ?, ?, ?, ?)
ON CONFLICT(codebase_id, file_path) DO UPDATE SET
  file_hash = excluded.file_hash,
  chunk_count = excluded.chunk_count,
  indexed_at = excluded.indexed_at;
```

### Skipping unchanged files

Before parsing a file, check if it has changed:

```sql
SELECT file_hash FROM indexed_files WHERE codebase_id = ? AND file_path = ?;
```

If the hash matches, skip it entirely.

## Storing embeddings

Embeddings can be stored as int8-quantized vectors using Turso's `vector8()` function, which reduces storage from 1,536 bytes (float32, 384 dims) to 395 bytes:

```sql
UPDATE chunks SET embedding = vector8(?), embedding_model = ? WHERE chunk_key = ?;
```

The parameter for `vector8()` is a JSON-stringified float array. Turso handles the quantization internally.

Find chunks that need embedding:

```sql
SELECT chunk_key, name, signature, file_path, kind, snippet
FROM chunks
WHERE codebase_id = ? AND (embedding IS NULL OR embedding_model != ?)
LIMIT ?;
```

## Full-text search

Turso provides an FTS index with weighted BM25 scoring that is separate from SQLite's `fts5` virtual tables.

### Creating the FTS index

Create an FTS table per codebase and populate it from the chunks:

```sql
-- Create the FTS table
CREATE TABLE IF NOT EXISTS fts_1 (
    chunk_id    INTEGER NOT NULL REFERENCES chunks(id) ON DELETE CASCADE,
    name        TEXT NOT NULL DEFAULT '',
    signature   TEXT NOT NULL DEFAULT ''
);

-- Populate from chunks
INSERT INTO fts_1 (chunk_id, name, signature)
SELECT id, name, signature FROM chunks WHERE codebase_id = 1;

-- Create the FTS index with weighted columns
CREATE INDEX IF NOT EXISTS idx_fts_1 ON fts_1
    USING fts (name, signature)
    WITH (
        tokenizer = 'default',
        weights = 'name=5.0,signature=3.0'
    );
```

The `weights` parameter controls BM25 scoring — here, matches in the function/type `name` are weighted 5x and `signature` matches 3x.

### Searching with FTS

```sql
SELECT chunk_id, fts_score(name, signature, ?1) AS score
FROM fts_1
WHERE fts_match(name, signature, ?1)
ORDER BY score DESC
LIMIT ?;
```

Then fetch the full chunk data:

```sql
SELECT chunk_key, file_path, name, kind, signature, snippet, start_line, end_line
FROM chunks WHERE id = ?;
```

## Vector search

For semantic/natural language queries, use vector cosine distance:

```sql
SELECT chunk_key, file_path, name, kind, signature, snippet, start_line, end_line,
       vector_distance_cos(embedding, vector8(?)) AS distance
FROM chunks
WHERE embedding IS NOT NULL
ORDER BY distance ASC
LIMIT ?;
```

The score is `1 - distance` (cosine similarity from cosine distance).

## Hybrid search

For the best results, combine both approaches using Reciprocal Rank Fusion (RRF). Run the FTS and vector queries separately, then merge results in application code:

```javascript
// Run both searches
const ftsResults = await ftsSearch(query, limit);
const vecResults = await vectorSearch(queryEmbedding, limit);

// Reciprocal Rank Fusion
const k = 60; // RRF constant
const scores = new Map();

ftsResults.forEach((r, i) => {
  const key = r.chunk_key;
  scores.set(key, (scores.get(key) || 0) + 1 / (k + i + 1));
});

vecResults.forEach((r, i) => {
  const key = r.chunk_key;
  scores.set(key, (scores.get(key) || 0) + 1 / (k + i + 1));
});

// Sort by combined score
const merged = [...scores.entries()]
  .sort((a, b) => b[1] - a[1])
  .slice(0, limit);
```

## Removing stale files

When files are deleted from the codebase, clean up their chunks and records:

```sql
DELETE FROM chunks WHERE codebase_id = ? AND file_path = ?;
DELETE FROM indexed_files WHERE codebase_id = ? AND file_path = ?;
```

After removing stale data, rebuild the FTS table to keep the index consistent:

```sql
DROP TABLE IF EXISTS fts_1;
-- Then recreate and repopulate as shown above
```

## Key design points

- **Incremental indexing** via file hashes means only changed files are re-parsed and re-embedded, making updates fast even on large codebases.
- **Two search modes** — FTS for identifier/keyword lookup and vector search for semantic/natural language queries — cover different use cases. Hybrid search combines both.
- **Weighted FTS** (`name=5.0, signature=3.0`) biases results toward function and type names, which is what developers usually search for.
- **Int8 quantized vectors** via `vector8()` reduce storage by 75% compared to float32 with minimal impact on search quality.
- Everything runs in a single embedded database file with no external services.

## Example

[codemogger](https://github.com/glommer/codemogger) is an MCP server that implements this pattern as a code indexer for AI coding agents.

---

## File: guides/content-caching.mdx

---
title: Content Caching
---

Tools and agents frequently re-read files they have already seen, wasting tokens and time. A content-addressed cache backed by an embedded Turso database can detect unchanged files and return diffs instead of full content, dramatically reducing redundant I/O.

This guide walks through the schema and queries needed to build a file content cache with per-session tracking.

## Schema

The cache uses four tables: one for file versions, one for per-session read pointers, and two for statistics.

```sql
CREATE TABLE IF NOT EXISTS file_versions (
  path        TEXT NOT NULL,
  hash        TEXT NOT NULL,
  content     TEXT NOT NULL,
  lines       INTEGER NOT NULL,
  created_at  INTEGER NOT NULL,
  PRIMARY KEY (path, hash)
);

CREATE TABLE IF NOT EXISTS session_reads (
  session_id  TEXT NOT NULL,
  path        TEXT NOT NULL,
  hash        TEXT NOT NULL,
  read_at     INTEGER NOT NULL,
  PRIMARY KEY (session_id, path)
);

CREATE TABLE IF NOT EXISTS stats (
  key   TEXT PRIMARY KEY,
  value INTEGER NOT NULL DEFAULT 0
);

CREATE TABLE IF NOT EXISTS session_stats (
  session_id  TEXT NOT NULL,
  key         TEXT NOT NULL,
  value       INTEGER NOT NULL DEFAULT 0,
  PRIMARY KEY (session_id, key)
);

INSERT OR IGNORE INTO stats (key, value) VALUES ('tokens_saved', 0);
```

### How it fits together

- **`file_versions`** is a content-addressed store. The composite primary key `(path, hash)` means the same file can have multiple versions stored simultaneously. When a file changes and then changes back (e.g. a branch switch), the old version is already cached.
- **`session_reads`** tracks which version of each file a given session last saw. This is keyed by `(session_id, path)` so each session independently tracks its own read state.
- **`stats`** and **`session_stats`** track cumulative token savings globally and per session.

## Connecting

```javascript
import { connect } from "@tursodatabase/database";

const db = await connect(".cache/content.db");
await db.exec(SCHEMA); // The CREATE TABLE statements above
```

## Storing a file version

When a file is read for the first time (or has changed), store its content keyed by a hash. `INSERT OR IGNORE` makes this a no-op if the same version already exists:

```sql
INSERT OR IGNORE INTO file_versions (path, hash, content, lines, created_at)
VALUES (?, ?, ?, ?, ?);
```

The hash should be computed from the file content (e.g. a truncated SHA-256). This makes storage content-addressed — identical content is never stored twice for the same path.

## Tracking reads per session

Each session needs to know what it last saw for a given file. On first read, record the session's read pointer:

```sql
INSERT OR REPLACE INTO session_reads (session_id, path, hash, read_at)
VALUES (?, ?, ?, ?);
```

On subsequent reads, check what the session last saw:

```sql
SELECT hash FROM session_reads WHERE session_id = ? AND path = ?;
```

If the stored hash matches the current file hash, the file is unchanged — return a short confirmation instead of the full content. If the hash differs, fetch the old content to compute a diff:

```sql
SELECT content FROM file_versions WHERE path = ? AND hash = ?;
```

Then update the session's read pointer to the new hash:

```sql
UPDATE session_reads SET hash = ?, read_at = ? WHERE session_id = ? AND path = ?;
```

## Tracking token savings

Use an atomic counter for global statistics and an upsert for per-session tracking:

```sql
-- Global counter
UPDATE stats SET value = value + ? WHERE key = 'tokens_saved';

-- Per-session counter (upsert)
INSERT INTO session_stats (session_id, key, value)
VALUES (?, 'tokens_saved', ?)
ON CONFLICT(session_id, key) DO UPDATE SET value = value + ?;
```

## Querying statistics

```sql
-- Number of distinct files cached
SELECT COUNT(DISTINCT path) as file_count FROM file_versions;

-- Global tokens saved
SELECT value FROM stats WHERE key = 'tokens_saved';

-- Tokens saved in the current session
SELECT value FROM session_stats WHERE session_id = ? AND key = 'tokens_saved';
```

## Cleanup

When a file is deleted from disk, remove all its versions and read pointers:

```sql
DELETE FROM file_versions WHERE path = ?;
DELETE FROM session_reads WHERE path = ?;
```

To clear the entire cache:

```sql
DELETE FROM file_versions;
DELETE FROM session_reads;
DELETE FROM session_stats;
UPDATE stats SET value = 0;
```

## Key design points

- **Content-addressed storage** means branch switches are handled naturally. If you switch from `main` to a feature branch and back, the original file versions are still in the cache.
- **Session isolation** ensures that each consumer independently tracks what it has seen. Session B gets full file content even if Session A already cached it.
- **Hash-based change detection** at read time means there is no polling or file watching required for correctness.
- An embedded Turso database keeps everything in a single file with zero network overhead.

## Example

[cachebro](https://github.com/glommer/cachebro) is an MCP server that implements this pattern as a drop-in file reading cache for AI coding agents.

---

## File: guides/secrets-vault.mdx

---
title: Secrets Vault
---

AI coding agents regularly need real credentials — an API token to call GitHub as you, a key to hit your billing provider, a token to deploy. The path of least resistance is to paste the secret into the chat, but then the value lives in the model's context, the transcript, and your provider's logs forever. A secrets vault backed by an encrypted Turso database lets an agent *use* a secret without ever seeing its value: the secret is injected into a child process, the command runs, and the output is scrubbed before the agent sees it.

This guide covers the schema, the encrypted connection, and the queries for a local secrets vault that an agent can use but never read.

## Schema

The vault uses two tables: one for the secrets themselves, one for an append-only audit log.

```sql
CREATE TABLE IF NOT EXISTS secrets (
  name         TEXT PRIMARY KEY,
  value        TEXT NOT NULL,
  provider     TEXT,
  account      TEXT,
  environment  TEXT,
  access       TEXT,
  tags         TEXT NOT NULL DEFAULT '',
  description  TEXT,
  created_at   TEXT NOT NULL,
  last_used_at TEXT
);

CREATE TABLE IF NOT EXISTS audit_log (
  id         INTEGER PRIMARY KEY AUTOINCREMENT,
  ts         TEXT NOT NULL,
  secrets    TEXT NOT NULL,
  command    TEXT NOT NULL,
  cwd        TEXT NOT NULL,
  exit_code  INTEGER,
  outcome    TEXT NOT NULL
);
```

### How it fits together

- **`secrets`** stores each credential keyed by `name`. The `value` column holds the secret itself and is only ever read to inject into a child process, never returned to the agent. The metadata columns (`provider`, `account`, `environment`, `access`, `tags`) describe a secret without revealing it, so an agent can reason about "the production database token" by its attributes.
- **`audit_log`** is an append-only record of every use: which secrets were injected, the command, the working directory, the exit code, and the outcome (`ran` or `denied`).

## Connecting

The vault is a single encrypted database file. Turso encrypts every page at rest when you pass a key at connection time, and `multiprocess_wal` lets several processes (a couple of agent sessions plus a CLI) open the same file safely:

```javascript
import { connect } from "@tursodatabase/database";

const db = await connect("vault.db", {
  encryption: { cipher: "aes256gcm", hexkey },
  experimental: ["multiprocess_wal"],
});
await db.exec(SCHEMA); // The CREATE TABLE statements above
```



`hexkey` is a 64-character hex string. Where it comes from is up to you. You can derive it from a passphrase with scrypt (and never store it), unwrap it from the OS keychain, or fetch it from a cloud KMS. Turso only needs the key at `connect()` time; the storage layer is identical regardless of the source.



## Storing a secret

Upsert by `name` so rotating a value keeps the existing metadata:

```sql
INSERT INTO secrets (name, value, provider, account, environment, access, tags, description, created_at)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
ON CONFLICT(name) DO UPDATE SET
  value       = excluded.value,
  provider    = COALESCE(excluded.provider, secrets.provider),
  account     = COALESCE(excluded.account, secrets.account),
  environment = COALESCE(excluded.environment, secrets.environment),
  access      = COALESCE(excluded.access, secrets.access),
  description = COALESCE(excluded.description, secrets.description);
```

## Listing without exposing values

The query an agent is allowed to run simply never selects the `value` column:

```sql
SELECT name, provider, account, environment, access, tags, description, created_at, last_used_at
FROM secrets ORDER BY name;
```

This returns secret names and attributes — enough for an agent to pick the right credential — while the value never leaves the database.

## Using a secret

To actually use a secret, read its value, inject it into a child process as an environment variable, run the command, and scrub the value out of the output before returning it:

```sql
SELECT value FROM secrets WHERE name = ?;
```

The injection and scrubbing happen in application code, not the database:

```javascript
const { value } = await db.prepare(
  "SELECT value FROM secrets WHERE name = ?"
).get([name]);

const result = await runCommand(command, {
  env: { ...process.env, [name]: value },
});

// Replace every occurrence of the value before the agent sees the output
const safe = result.stdout.replaceAll(value, "***");
```

<Warning>

Scrubbing captured output is not a sandbox. A command that can read a secret can always leak it on purpose (write it to a file, send it over the network). What the vault guarantees is narrower and still useful: the *model* never receives the value, and a careless `echo $TOKEN` gets redacted. The secret only ever lives in the encrypted file and the short-lived process that used it.

</Warning>

## Auditing every use

Record each access as a row, and update the secret's `last_used_at`:

```sql
INSERT INTO audit_log (ts, secrets, command, cwd, exit_code, outcome)
VALUES (?, ?, ?, ?, ?, ?);

UPDATE secrets SET last_used_at = ? WHERE name = ?;
```

"Who used the production key, when, and for what" is then an ordinary query:

```sql
SELECT ts, secrets, command, cwd, exit_code, outcome
FROM audit_log ORDER BY id DESC LIMIT ?;
```

## Key design points

- **Encrypted at rest, for free.** Turso handles whole-database encryption (AES-256-GCM, or one of the faster AEGIS ciphers). The vault never touches a cipher or manages page encryption — it derives a key and hands it to `connect()`.
- **No coordinating daemon.** `multiprocess_wal` lets each agent session and CLI invocation open the same encrypted file directly, so the database is the shared state instead of a long-running server you have to keep alive.
- **The value never appears in a list.** Listing is a `SELECT` that omits the `value` column; the agent sees names and attributes only.
- **Fail closed.** An unknown secret name aborts before the command runs, rather than executing with a missing credential.
- **Auditing is just a table.** Every use is an `INSERT`; reporting on it is a `SELECT` you can export or alert on.

## Example

[keymaxxer](https://github.com/glommer/keymaxxer) is an MCP server that implements this pattern as an encrypted secrets vault for AI coding agents.