Metadata-Version: 2.5
Name: strands-github-storage
Version: 0.1.0
Summary: GitHub-repository Storage backend for Strands Agents — persists keys as versioned, diffable files in a repo.
Project-URL: Homepage, https://github.com/maisieyanz/strands-github-storage
Project-URL: Documentation, https://github.com/maisieyanz/strands-github-storage#readme
Project-URL: Repository, https://github.com/maisieyanz/strands-github-storage
Project-URL: Issues, https://github.com/maisieyanz/strands-github-storage/issues
Author-email: Maisie Yan <maisiey78@gmail.com>
License: Apache-2.0
License-File: LICENSE
Keywords: agents,ai,github,storage,strands
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: Apache Software License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Requires-Python: >=3.10
Requires-Dist: pygithub>=2.0.0
Requires-Dist: strands-agents>=1.0.0
Provides-Extra: dev
Requires-Dist: mypy<2.0.0,>=1.15.0; extra == 'dev'
Requires-Dist: pytest-asyncio<1.0.0,>=0.25.0; extra == 'dev'
Requires-Dist: pytest<9.0.0,>=8.0.0; extra == 'dev'
Requires-Dist: ruff<1.0.0,>=0.11.0; extra == 'dev'
Description-Content-Type: text/markdown

<div align="center">
  <h1>strands-github-storage (Python)</h1>
  <p>A GitHub-repository <code>Storage</code> backend for <a href="https://strandsagents.com">Strands Agents</a>.</p>
</div>

Persists each key as a file in a GitHub repository, at the key's path on a branch. Because the store
*is* a git repo, its contents are browsable in the GitHub UI, diffable per change, and versioned in
history. Implements the SDK's `Storage` interface, so it works anywhere a `Storage` is accepted —
session snapshots and context offloading.

## Install

```bash
pip install strands-github-storage
```

`strands-agents` and `PyGithub` are installed as dependencies.

## Usage

```python
import asyncio
from strands_github_storage import GithubStorage

storage = GithubStorage(
    owner="myorg",
    repo="agent-memory",
    branch="main",          # optional, defaults to "main"
    token="ghp_...",        # required for writes and private repos
)

async def main() -> None:
    await storage.write("facts/note.md", b"remember this")
    data = await storage.read("facts/note.md")   # bytes | None
    keys = await storage.list("facts/")          # ["facts/note.md"]
    await storage.delete("facts/note.md")

asyncio.run(main())
```

### With a session manager

```python
from strands import Agent
from strands.session import SessionManager
from strands_github_storage import GithubStorage

storage = GithubStorage(owner="myorg", repo="agent-sessions", token=token)
agent = Agent(session_manager=SessionManager(storage=storage))
```

## Configuration

| Parameter | Required | Description |
|-----------|----------|-------------|
| `owner` | yes | Repository owner (user or organization login). |
| `repo` | yes | Repository name. |
| `branch` | no | Branch to read from and commit to. Defaults to `main`. |
| `token` | for writes | GitHub token. Needed for any write and for reading private repos. |
| `github` | no | A pre-configured PyGithub `Github` client, as an alternative to `token`. |

## Behavior and limits

- **One commit per operation.** Each `write` and `delete` is its own commit (`update <key>` /
  `delete <key>`). A burst of writes produces a burst of commits.
- **Single writer per branch.** Commits advance the branch ref without a compare-and-swap retry, so a
  concurrent writer that moves the branch head surfaces GitHub's non-fast-forward rejection as a
  `StorageError` rather than being retried.
- **`read` is limited to files under the GitHub contents API's inline-response ceiling** (~1 MB).
  Markdown memory is far below this.
- **`list` fails loud on truncation.** GitHub's git-tree API caps very large trees and does not
  paginate; rather than return a silent partial listing, `list` raises a `StorageError`.

## Development

```bash
pip install -e ".[dev]"
pytest
ruff check src tests
mypy src
```

## License

Apache-2.0
