# `Jido.Storage.File`
[🔗](https://github.com/agentjido/jido/blob/v2.3.0/lib/jido/storage/file.ex#L1)

File-based storage adapter for Jido.

Provides persistent storage for agent checkpoints and thread journals using
a directory-based layout. Suitable for simple production deployments.

## Usage

    defmodule MyApp.Jido do
      use Jido,
        otp_app: :my_app,
        storage: {Jido.Storage.File, path: "priv/jido/storage"}
    end

## Options

- `:path` - Base directory path (required). Created if it doesn't exist.

## Directory Layout

    base_path/
    ├── checkpoints/
    │   └── {key_hash}.term       # Serialized checkpoint
    └── threads/
        └── {thread_id}/
            ├── meta.term          # {rev, created_at, updated_at, metadata}
            └── entries.log        # Length-prefixed binary frames

## Concurrency

Uses `:global.trans/3` for thread-level locking to ensure safe concurrent access.

# `key`

```elixir
@type key() :: term()
```

# `opts`

```elixir
@type opts() :: keyword()
```

# `append_thread`

```elixir
@spec append_thread(String.t(), [Jido.Thread.Entry.t()], opts()) ::
  {:ok, Jido.Thread.t()} | {:error, term()}
```

Append entries to a thread with optimistic concurrency.

Options:
- `:expected_rev` - Expected current revision. Fails with `{:error, :conflict}`
  if the current revision doesn't match.

Uses a global lock to ensure safe concurrent access.

# `delete_checkpoint`

```elixir
@spec delete_checkpoint(key(), opts()) :: :ok | {:error, term()}
```

Delete a checkpoint.

Returns `:ok` even if the file doesn't exist.

# `delete_thread`

```elixir
@spec delete_thread(String.t(), opts()) :: :ok | {:error, term()}
```

Delete a thread and all its data.

Removes the entire thread directory.

# `get_checkpoint`

```elixir
@spec get_checkpoint(key(), opts()) :: {:ok, term()} | :not_found | {:error, term()}
```

Retrieve a checkpoint by key.

Returns `{:ok, data}` if found, `:not_found` if the file doesn't exist,
or `{:error, reason}` on failure.

# `load_thread`

```elixir
@spec load_thread(String.t(), opts()) ::
  {:ok, Jido.Thread.t()} | :not_found | {:error, term()}
```

Load a thread from disk.

Reads the meta file and entries log, reconstructing a `%Jido.Thread{}`.
Returns `:not_found` if the thread directory doesn't exist.

# `put_checkpoint`

```elixir
@spec put_checkpoint(key(), term(), opts()) :: :ok | {:error, term()}
```

Store a checkpoint with atomic write semantics.

Writes to a temporary file first, then renames for atomicity.

