Managing codebases
A codebase is a reusable starting workspace for a run. Use one when the agent should modify an existing project instead of starting from an empty directory.
Scope separates the codebase's mutable identity from its immutable revisions:
- The codebase stores its name, slug, description, source type, and Git settings.
- Each revision is a numbered snapshot such as
my-service@r3. - A request resolves its codebase selection to one exact revision ID before it is queued.
This keeps a run reproducible even when the Git branch moves or a newer archive is uploaded later.
Choose a source type
Section titled “Choose a source type”| Source type | Use it for | How revisions are created |
|---|---|---|
| Git repository | A repository hosted on GitHub | Scope resolves a branch, tag, or commit and snapshots the exact commit. |
| Uploaded archive | Source supplied as .tar.gz, .tgz, .tar, or .zip | Each upload becomes an immutable normalized snapshot. |
Git sources use owner/repo format. Uploaded archives are limited to
1 MB by the current ingress configuration.
Create a codebase
Section titled “Create a codebase”From the Portal
Section titled “From the Portal”- Open Codebases and select Create Codebase.
- Choose Git repository or Uploaded archive.
- Enter a name. You can keep the generated slug or edit it.
- For Git, enter the GitHub repository and optionally a default branch. For an archive, select the archive file.
- Select Create codebase.
Scope immediately tries to create the first revision:
- A Git codebase resolves its default branch. If GitHub resolution fails, the codebase still exists and you can select Resolve latest later.
- An archive codebase and its first revision are created together. If the archive cannot be processed, Scope rolls the codebase back.
From the CLI
Section titled “From the CLI”Create a Git codebase:
scope codebase create \ --name "Inventory service" \ --source-type git \ --source contoso/inventory \ --default-branch mainCreate an archive codebase:
scope codebase create \ --name "Inventory fixture" \ --source-type archive \ --archive ./inventory-fixture.tar.gzCodebase creation and listing use the active project. Use the CLI's
--project option when you need to target a different project.
From the REST API
Section titled “From the REST API”Create a Git codebase:
curl --request POST \ --url 'https://your-scope.example.com/api/v1/codebases?projectId=your-project-id' \ --header 'Content-Type: application/json' \ --data '{ "name": "Inventory service", "sourceType": "git", "source": "contoso/inventory", "defaultBranch": "main"}'const url = 'https://your-scope.example.com/api/v1/codebases?projectId=your-project-id';const options = { method: 'POST', headers: {'Content-Type': 'application/json'}, body: '{"name":"Inventory service","sourceType":"git","source":"contoso/inventory","defaultBranch":"main"}'};
try { const response = await fetch(url, options); const data = await response.json(); console.log(data);} catch (error) { console.error(error);}import requests
url = "https://your-scope.example.com/api/v1/codebases"
querystring = {"projectId":"your-project-id"}
payload = { "name": "Inventory service", "sourceType": "git", "source": "contoso/inventory", "defaultBranch": "main"}headers = {"Content-Type": "application/json"}
response = requests.post(url, json=payload, headers=headers, params=querystring)
print(response.json())package main
import ( "fmt" "strings" "net/http" "io")
func main() {
url := "https://your-scope.example.com/api/v1/codebases?projectId=your-project-id"
payload := strings.NewReader("{\n \"name\": \"Inventory service\",\n \"sourceType\": \"git\",\n \"source\": \"contoso/inventory\",\n \"defaultBranch\": \"main\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close() body, _ := io.ReadAll(res.Body)
fmt.Println(res) fmt.Println(string(body))
}OkHttpClient client = new OkHttpClient();
MediaType mediaType = MediaType.parse("application/json");RequestBody body = RequestBody.create(mediaType, "{\n \"name\": \"Inventory service\",\n \"sourceType\": \"git\",\n \"source\": \"contoso/inventory\",\n \"defaultBranch\": \"main\"\n}");Request request = new Request.Builder() .url("https://your-scope.example.com/api/v1/codebases?projectId=your-project-id") .post(body) .addHeader("Content-Type", "application/json") .build();
Response response = client.newCall(request).execute();using System.Net.Http.Headers;var client = new HttpClient();var request = new HttpRequestMessage{ Method = HttpMethod.Post, RequestUri = new Uri("https://your-scope.example.com/api/v1/codebases?projectId=your-project-id"), Content = new StringContent("{\n \"name\": \"Inventory service\",\n \"sourceType\": \"git\",\n \"source\": \"contoso/inventory\",\n \"defaultBranch\": \"main\"\n}") { Headers = { ContentType = new MediaTypeHeaderValue("application/json") } }};using (var response = await client.SendAsync(request)){ response.EnsureSuccessStatusCode(); var body = await response.Content.ReadAsStringAsync(); Console.WriteLine(body);}Archive creation uses multipart/form-data with the metadata fields
and a file field named archive. See the
Codebases API reference for the generated request
schema.
Create and inspect revisions
Section titled “Create and inspect revisions”Revisions are immutable and numbered sequentially. Open a codebase in
the Portal to inspect its commit or archive provenance, file count,
size, content hash, and revision ID. You can also download the
normalized .tar.gz snapshot.
Git revisions
Section titled “Git revisions”Select Resolve latest to snapshot the default branch, or Resolve ref… to resolve a branch, tag, or commit SHA.
CLI equivalents:
scope codebase resolve your-codebase-idscope codebase resolve your-codebase-id --ref release/2026-10scope codebase revisions your-codebase-idAPI equivalent:
curl --request POST \ --url https://your-scope.example.com/api/v1/codebases/your-codebase-id/revisions \ --header 'Content-Type: application/json' \ --data '{ "requestedRef": "release/2026-10" }'const url = 'https://your-scope.example.com/api/v1/codebases/your-codebase-id/revisions';const options = { method: 'POST', headers: {'Content-Type': 'application/json'}, body: '{"requestedRef":"release/2026-10"}'};
try { const response = await fetch(url, options); const data = await response.json(); console.log(data);} catch (error) { console.error(error);}import requests
url = "https://your-scope.example.com/api/v1/codebases/your-codebase-id/revisions"
payload = { "requestedRef": "release/2026-10" }headers = {"Content-Type": "application/json"}
response = requests.post(url, json=payload, headers=headers)
print(response.json())package main
import ( "fmt" "strings" "net/http" "io")
func main() {
url := "https://your-scope.example.com/api/v1/codebases/your-codebase-id/revisions"
payload := strings.NewReader("{ \"requestedRef\": \"release/2026-10\" }")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close() body, _ := io.ReadAll(res.Body)
fmt.Println(res) fmt.Println(string(body))
}OkHttpClient client = new OkHttpClient();
MediaType mediaType = MediaType.parse("application/json");RequestBody body = RequestBody.create(mediaType, "{ \"requestedRef\": \"release/2026-10\" }");Request request = new Request.Builder() .url("https://your-scope.example.com/api/v1/codebases/your-codebase-id/revisions") .post(body) .addHeader("Content-Type", "application/json") .build();
Response response = client.newCall(request).execute();using System.Net.Http.Headers;var client = new HttpClient();var request = new HttpRequestMessage{ Method = HttpMethod.Post, RequestUri = new Uri("https://your-scope.example.com/api/v1/codebases/your-codebase-id/revisions"), Content = new StringContent("{ \"requestedRef\": \"release/2026-10\" }") { Headers = { ContentType = new MediaTypeHeaderValue("application/json") } }};using (var response = await client.SendAsync(request)){ response.EnsureSuccessStatusCode(); var body = await response.Content.ReadAsStringAsync(); Console.WriteLine(body);}If the resolved commit is unchanged from the latest revision, Scope reuses that revision instead of creating a duplicate.
Archive revisions
Section titled “Archive revisions”In the Portal, select Upload new revision. From the CLI:
scope codebase upload your-codebase-id ./inventory-fixture-v2.zipIf the uploaded content is identical to the latest revision, Scope reuses the existing revision.
Select a codebase for a run
Section titled “Select a codebase for a run”You can select codebases in three forms:
| Value | Behavior |
|---|---|
inventory-service | Use the latest archive revision, or resolve the Git codebase's default branch at submission time. |
inventory-service@r3 | Pin revision 3. |
| Revision UUID | Pin the exact revision by its internal ID. |
Portal
Section titled “Portal”On New Run, select Add codebase, then choose the codebase or a specific revision. Scope stores the resolved revision ID on the request before queueing it.
Use --codebase with scope run submit:
scope run submit \ -m "Add input validation to the inventory API." \ -w coder-acp-copilot \ -c validates_request_body \ --codebase inventory-service@r3REST API
Section titled “REST API”Pass a slug, numbered ref, or revision ID in codebase:
curl --request POST \ --url 'https://your-scope.example.com/api/v1/requests?projectId=your-project-id' \ --header 'Content-Type: application/json' \ --data '{ "scenario": { "task": "Add input validation to the inventory API.", "criteria": ["validates_request_body"] }, "workerType": "coder-acp-copilot", "codebase": "inventory-service@r3"}'const url = 'https://your-scope.example.com/api/v1/requests?projectId=your-project-id';const options = { method: 'POST', headers: {'Content-Type': 'application/json'}, body: '{"scenario":{"task":"Add input validation to the inventory API.","criteria":["validates_request_body"]},"workerType":"coder-acp-copilot","codebase":"inventory-service@r3"}'};
try { const response = await fetch(url, options); const data = await response.json(); console.log(data);} catch (error) { console.error(error);}import requests
url = "https://your-scope.example.com/api/v1/requests"
querystring = {"projectId":"your-project-id"}
payload = { "scenario": { "task": "Add input validation to the inventory API.", "criteria": ["validates_request_body"] }, "workerType": "coder-acp-copilot", "codebase": "inventory-service@r3"}headers = {"Content-Type": "application/json"}
response = requests.post(url, json=payload, headers=headers, params=querystring)
print(response.json())package main
import ( "fmt" "strings" "net/http" "io")
func main() {
url := "https://your-scope.example.com/api/v1/requests?projectId=your-project-id"
payload := strings.NewReader("{\n \"scenario\": {\n \"task\": \"Add input validation to the inventory API.\",\n \"criteria\": [\"validates_request_body\"]\n },\n \"workerType\": \"coder-acp-copilot\",\n \"codebase\": \"inventory-service@r3\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close() body, _ := io.ReadAll(res.Body)
fmt.Println(res) fmt.Println(string(body))
}OkHttpClient client = new OkHttpClient();
MediaType mediaType = MediaType.parse("application/json");RequestBody body = RequestBody.create(mediaType, "{\n \"scenario\": {\n \"task\": \"Add input validation to the inventory API.\",\n \"criteria\": [\"validates_request_body\"]\n },\n \"workerType\": \"coder-acp-copilot\",\n \"codebase\": \"inventory-service@r3\"\n}");Request request = new Request.Builder() .url("https://your-scope.example.com/api/v1/requests?projectId=your-project-id") .post(body) .addHeader("Content-Type", "application/json") .build();
Response response = client.newCall(request).execute();using System.Net.Http.Headers;var client = new HttpClient();var request = new HttpRequestMessage{ Method = HttpMethod.Post, RequestUri = new Uri("https://your-scope.example.com/api/v1/requests?projectId=your-project-id"), Content = new StringContent("{\n \"scenario\": {\n \"task\": \"Add input validation to the inventory API.\",\n \"criteria\": [\"validates_request_body\"]\n },\n \"workerType\": \"coder-acp-copilot\",\n \"codebase\": \"inventory-service@r3\"\n}") { Headers = { ContentType = new MediaTypeHeaderValue("application/json") } }};using (var response = await client.SendAsync(request)){ response.EnsureSuccessStatusCode(); var body = await response.Content.ReadAsStringAsync(); Console.WriteLine(body);}You can also pass an already resolved revision UUID as
codebaseRevisionId.
What the worker receives
Section titled “What the worker receives”Before the agent starts, Scope downloads the selected revision and
extracts it into the workspace root. Skills and AGENTS.md content
are applied after the codebase, so they can add instructions alongside
the seeded project.
Codebase seeding is required when a revision is attached. If Scope cannot fetch or extract it, the run fails rather than silently starting from an empty workspace.
Downloaded run archives include the exact starting snapshot as
codebase.tar.gz, and run.yaml records its revision and provenance.
Delete a codebase
Section titled “Delete a codebase”Deleting a codebase is a soft delete. It disappears from lists and can no longer be selected for new requests, but its revisions remain available to historical and in-flight runs.
From the CLI:
scope codebase delete your-codebase-idReproducibility tips
Section titled “Reproducibility tips”- Use a numbered ref such as
inventory-service@r3in CI and published benchmarks. - Use a bare Git slug when you intentionally want the branch's current commit at submission time.
- Review the resolved commit SHA or content hash on the codebase detail page before comparing runs.
- Keep task prompts independent of repository setup. Select the codebase on the request instead of telling the agent to clone it.