Files and commits
Read and edit files in a chat session's sandbox and read its git state. The sandbox must be running, so wake it first with GET /api/projects/{projectId}/preview?sessionId=. A write changes the working tree only. Ask the agent to review and include your edits in its next turn. In a Collaboration project, the agent commits and pushes its changes at the end of every turn. Review the diff, then use Open PR when the work is ready. Open PR sends $kosuke:open-pr on a chat session whose Model runs on OpenAI and /kosuke:open-pr on any other. While the session has no Model, or its sandbox lacks the kosuke plugin, it sends a plain message.
| Method | Path | Description |
|---|---|---|
| GET | /api/projects/{projectId}/chat-sessions/{sessionId}/preview/files | List the files in the session's sandbox. Empty when the sandbox is not running. |
| GET | /api/projects/{projectId}/chat-sessions/{sessionId}/preview/files/content?path= | Read one file from the session's sandbox. |
| PUT | /api/projects/{projectId}/chat-sessions/{sessionId}/preview/files/content | Write one file in the session's sandbox. Refused while a turn is running, and for binary content. |
| GET | /api/projects/{projectId}/chat-sessions/{sessionId}/preview/git-state | Read whether the session's sandbox has uncommitted changes, unpushed commits, or commits ahead of its base branch. |
Read the file tree
GET .../preview/files lists the project's files in the sandbox.
curl -s "https://app.kosuke.ai/api/projects/$PROJECT_ID/chat-sessions/$SESSION_ID/preview/files" \
-H "Authorization: Bearer $KOSUKE_API_KEY"
{
"data": {
"files": [
{
"name": "src",
"type": "directory",
"path": "src",
"children": [
{ "name": "page.tsx", "type": "file", "path": "src/page.tsx", "size": 1843, "lastModified": "2026-09-30T09:14:02.511Z" }
]
}
]
}
}
Paths are relative to the project root. The tree leaves out the folders node_modules, .git, .next, dist, build, coverage, .turbo, .cache, __pycache__, venv and .venv, and the files .DS_Store and Thumbs.db. When the sandbox is not running, files is empty. The CLI command is kosuke sessions files list <projectId> <sessionId>.
Read a file
GET .../preview/files/content returns one file's text.
| Parameter | What it does |
|---|---|
path | Required. The file's path, relative to the project root. |
kosuke sessions files get $PROJECT_ID $SESSION_ID --path src/page.tsx
The answer is { "data": { "content": "..." } }. A path that does not exist, or that leads outside the project, answers 404.
Write a file
PUT .../preview/files/content replaces the content of a file that exists. To add a new file, ask the agent in a message.
| Field | Type | What it does |
|---|---|---|
path | string, up to 2,048 characters | Required. The file's path, relative to the project root. |
content | string, up to 1,048,576 characters | Required. The whole new content. Text only. |
clientId | uuid | Required. A UUID you generate, for example with uuidgen. |
curl -s -X PUT "https://app.kosuke.ai/api/projects/$PROJECT_ID/chat-sessions/$SESSION_ID/preview/files/content" \
-H "Authorization: Bearer $KOSUKE_API_KEY" \
-H "Content-Type: application/json" \
-d "{\"path\": \"README.md\", \"content\": \"# Storefront\\n\", \"clientId\": \"$(uuidgen)\"}"
{ "data": { "path": "README.md", "updatedAt": "2026-09-30T09:31:47.220Z" } }
Members with the session open see the change at once. The change is not committed. A write while a turn runs answers 409 with JOB_ACTIVE, and binary content answers 400. The CLI command is kosuke sessions files set <projectId> <sessionId> --path <path> --content <text> --client-id <uuid>.
Read the git state
GET .../preview/git-state reports the state of the working tree and branch.
{
"data": {
"available": true,
"hasUncommittedChanges": true,
"hasUnpushedCommits": false,
"hasCommitsAheadOfBase": true
}
}
| Field | What it means |
|---|---|
available | false when the sandbox is not running. The other fields are then false too. |
hasUncommittedChanges | The working tree has changes nobody committed. |
hasUnpushedCommits | The branch has commits that are not on GitHub yet. |
hasCommitsAheadOfBase | The branch has commits its pull request's base branch does not have, or the Target Branch before a pull request is open. |
Reading the git state never wakes a sandbox. The CLI command is kosuke sessions git state get <projectId> <sessionId>.
Errors
| Status | Code | When |
|---|---|---|
| 400 | VALIDATION_ERROR | A field is missing, too long, or clientId is not a UUID. |
| 400 | BAD_REQUEST | A read has no path, the sandbox is not running for a read or a write, the content is binary, or the write failed. The message says which. |
| 402 | CREDIT_LIMIT_REACHED | The workspace is blocked on billing. |
| 404 | NOT_FOUND | The project, session or file does not exist. |
| 409 | JOB_ACTIVE | A turn is running. Write again once it ends. |
| 503 | SERVICE_UNAVAILABLE | The sandbox could not list the files, read the file or read the git state. Retry. |
Responses and errors has the full table.