React Hooks
The @githosted/sdk/react entrypoint provides TanStack Query hooks for building React UIs on top of githosted repos.
Quickstart
Section titled “Quickstart”import { QueryClient, QueryClientProvider } from "@tanstack/react-query";import { GithostedProvider, useFileTree, useFile,} from "@githosted/sdk/react";
const queryClient = new QueryClient();
function App() { return ( <QueryClientProvider client={queryClient}> <GithostedProvider token="gw_xxx"> <FileBrowser /> </GithostedProvider> </QueryClientProvider> );}
function FileBrowser() { const { data: files } = useFileTree("my-project", "src/"); return ( <ul> {files?.map((f) => ( <li key={f.name}> {f.type === "directory" ? "📁" : "📄"} {f.name} </li> ))} </ul> );}Install
Section titled “Install”npm install @githosted/sdk @tanstack/react-query reactProvider
Section titled “Provider”GithostedProvider requires an outer QueryClientProvider — it does not create its own QueryClient. This avoids fragmented caches and gives you full control over query defaults.
<QueryClientProvider client={queryClient}> <GithostedProvider token="gw_xxx" baseUrl="https://api.githosted.dev"> {children} </GithostedProvider></QueryClientProvider>You can also pass a pre-built Client:
import { Client } from "@githosted/sdk";
const client = new Client({ token: "gw_xxx" });
<GithostedProvider client={client}> {children}</GithostedProvider>Query Hooks
Section titled “Query Hooks”useFileTree(repoRef, path?, options?)
Section titled “useFileTree(repoRef, path?, options?)”List files at a path.
const { data, isLoading } = useFileTree( { id: "rp_xxx" }, // or "my-project" "src/", { ref: "main" },);useFile(repoRef, path, options?)
Section titled “useFile(repoRef, path, options?)”Read a file’s content and metadata. Returns { content, headSha, blobSha }.
const { data: file } = useFile({ id: "rp_xxx" }, "src/main.ts", { ref: "main",});// file?.content, file?.headShauseCommitLog(repoRef, options?)
Section titled “useCommitLog(repoRef, options?)”Get the commit history.
const { data: commits } = useCommitLog({ id: "rp_xxx" }, { limit: 20 });useBranches(repoRef)
Section titled “useBranches(repoRef)”List branches.
const { data: branches } = useBranches({ id: "rp_xxx" });Mutation Hooks
Section titled “Mutation Hooks”useWriteFile(repoRef)
Section titled “useWriteFile(repoRef)”Write a file. Automatically invalidates file tree, file content, commit log, and branch caches on success.
const { mutateAsync: writeFile } = useWriteFile({ id: "rp_xxx" });
const handleSave = async () => { await writeFile({ path: "src/main.ts", content: editedCode, message: "Edit via browser", expectedHead: file?.headSha, });};useDeleteFile(repoRef)
Section titled “useDeleteFile(repoRef)”Delete a file.
const { mutateAsync: deleteFile } = useDeleteFile({ id: "rp_xxx" });await deleteFile({ path: "src/old.ts", message: "Remove old file" });useTransaction(repoRef)
Section titled “useTransaction(repoRef)”Atomic multi-file commit.
const { mutateAsync: commit } = useTransaction({ id: "rp_xxx" });await commit({ message: "Refactor", changes: [ { action: "write", path: "src/new.ts", content: code }, { action: "delete", path: "src/old.ts" }, ],});Repo Identity
Section titled “Repo Identity”All hooks accept a RepoRef — either a slug string or { id: "rp_xxx" }:
useFileTree("my-project", "src/"); // by sluguseFileTree({ id: "rp_8f3k2m1q9t6w4z7c5n2h" }, "src/"); // by stable IDUse stable IDs for apps that persist repo references.
Query Key Scoping
Section titled “Query Key Scoping”All query keys are prefixed with ["githosted", clientScope, repoRef, hookName, ...] where clientScope is derived from the client’s baseUrl + token. This prevents cache bleed between different providers sharing the same QueryClient.
When the token changes, the scope changes and all previous queries are invalidated.
Cache Invalidation
Section titled “Cache Invalidation”Mutation hooks automatically invalidate affected queries:
| After a write… | Invalidated |
|---|---|
| File tree | useFileTree for parent directory |
| File content | useFile for the exact path + ref |
| Commit log | useCommitLog for the repo |
| Branch state | useBranches for the repo |
Error Callbacks
Section titled “Error Callbacks”import { ConnectError, Code } from "@connectrpc/connect";import { RepoBusyError } from "@githosted/sdk/react";
<GithostedProvider token={token} onError={(error) => { // onError receives a plain Error. Check for ConnectError to inspect codes. if (error instanceof ConnectError && error.code === Code.Unauthenticated) { router.navigate("/login"); } }} onRepoBusy={(error, attempt) => { // Called on each auto-retry attempt for repo_busy errors. toast(`Repo busy (${error.operation}), retrying... (attempt ${attempt})`); }}>