Skip to content

Reading and Writing Files

The filesystem API (Level 3) is the primary interface for agents and apps. Read, write, and delete files with simple method calls.

import { Client } from "@githosted/sdk";
const client = new Client();
const repo = client.repo("my-project");
// List files
const files = await repo.ls("src/");
// Read a file
const file = await repo.read("src/main.ts");
console.log(file.content); // string content
console.log(file.headSha); // branch tip at read time
// Write a file
await repo.write("src/main.ts", "const x = 1;", {
message: "Update main.ts",
});

List files and directories at a path.

const entries = await repo.ls("src/");
// [{ name: "main.ts", type: "file" }, { name: "lib", type: "directory" }]
// List root
const root = await repo.ls();
// List at a specific branch
const entries = await repo.ls("src/", { ref: "feature/new-api" });

Read a file’s content and metadata.

const file = await repo.read("src/main.ts");
file.content; // string (UTF-8 decoded)
file.rawContent; // Uint8Array (raw bytes)
file.headSha; // branch tip SHA at read time
file.blobSha; // content-addressable blob hash
// Read from a specific branch
const file = await repo.read("src/main.ts", { ref: "develop" });

headSha is the key to optimistic concurrency — pass it as expectedHead on a subsequent write to detect conflicts.

Write a file, creating a commit on the target branch.

// Simple write
await repo.write("README.md", "# My Project", {
message: "Update readme",
});
// Write to a specific branch
await repo.write("src/main.ts", code, {
message: "Fix bug",
ref: "feature/fix",
});
// Write with optimistic concurrency
const file = await repo.read("src/main.ts");
await repo.write("src/main.ts", modifiedCode, {
message: "Fix bug",
expectedHead: file.headSha,
});

Content can be a string or Uint8Array (for binary files).

Delete a file, creating a commit on the target branch.

await repo.delete("src/old_module.ts", {
message: "Remove deprecated module",
});

Use expectedHead to detect when another writer has modified the branch between your read and write:

const file = await repo.read("config.json");
const config = JSON.parse(file.content);
config.version = "2.0";
try {
await repo.write("config.json", JSON.stringify(config, null, 2), {
message: "Bump version",
expectedHead: file.headSha,
});
} catch (err) {
if (err instanceof StaleHeadError) {
console.log(`Branch moved to ${err.actualHead}, re-read and retry`);
}
}

See Error Handling for more on StaleHeadError.