Runlog docs

Start building

A plan buys a weekly allowance, sized for steady work.

Start

Working directory

A folder on your machine becomes a project that stays current. The loop is three calls: ask what the key opens and what is never read, compare against what the project already holds, then push only the files whose content actually moved. Content addressing is what makes the second run cost nothing — an unchanged file is never re-read and never re-sent. Credentials are refused by shape rather than by folder, so a key that lands in a synced directory is left on disk instead of being indexed.

GET/v1/api/workspace/describeAPI key

Describe the binding

Ask which project this key opens, what reads as code, and what is never read.

Read this at run time rather than carrying your own copy. The skip lists and the per-file ceiling move with the reading pipeline, and a client that hardcodes them starts pushing bytes the server refuses.

`secretShapes` names the credential shapes no lane stores unasked. Skip them locally; a client that sends one anyway is refused per file rather than per push.

Request · curl
curl -X GET "https://runlogai.com/runlogapi/api/workspace/describe" \
  -H "Authorization: Bearer $RUNLOG_API_KEY" \
  -H "X-Project-Id: p7Kd2mQx"
Response · 200
{
  "codeExtensions": [
    ".go",
    ".ts",
    ".py"
  ],
  "maxFileBytes": 2097152,
  "projectId": "p7Kd2mQx",
  "projectName": "Checkout",
  "secretShapes": [
    "private-key",
    "cloud-credential"
  ],
  "skippedDirectories": [
    "node_modules",
    ".git"
  ],
  "skippedExtensions": [
    ".lock"
  ],
  "skippedNames": [
    ".DS_Store"
  ],
  "version": 1
}

Errors

StatuserrorWhen
401unauthorizedNo valid API key on the request.
GET/v1/api/workspace/manifestAPI key

List what the project holds

List every file this working directory already put in the project, under its content address.

Compare `contentId` against the same content address computed locally. Equal means the file is already read, and sending it again would cost money to learn nothing.

Request · curl
curl -X GET "https://runlogai.com/runlogapi/api/workspace/manifest" \
  -H "Authorization: Bearer $RUNLOG_API_KEY" \
  -H "X-Project-Id: p7Kd2mQx"
Response · 200
{
  "files": [
    {
      "contentId": "9dRk2mVt7QzLpXe4Nb1CsHgYo6JwFu3Ai0",
      "path": "cmd/main.go"
    }
  ],
  "version": 1
}

Errors

StatuserrorWhen
401unauthorizedNo valid API key on the request.
POST/v1/api/workspace/syncAPI key

Push what changed

Send one batch of changed files and learn which of them landed.

A refusal is per file and never stops the rest of the push, so one unreadable file cannot cost you the batch. Every refusal names its path and says why in the words the person who ran the command reads.

`includeSecret` is you naming one exact path to read anyway. It is per path rather than a mode, so nothing sends a whole folder of credentials by setting one flag.

A push lands on any plan, credits or none. A file the reading pipeline cannot afford stops as a transient error, and the next project open queues it again.

Body

FieldTypeRequiredDescription
itemsobject[]requiredThe files to send.
items[].pathstringrequiredPath relative to the folder root.
items[].contentTypestringoptionalDefaults from the path's extension.
items[].contentstringrequiredThe file's bytes, base64.
items[].includeSecretbooleanoptionalRead this one path despite its shape.
Request · curl
curl -X POST "https://runlogai.com/runlogapi/api/workspace/sync" \
  -H "Authorization: Bearer $RUNLOG_API_KEY" \
  -H "X-Project-Id: p7Kd2mQx" \
  -H "Content-Type: application/json" \
  -d '{
  "items": [
    {
      "content": "cGFja2FnZSBtYWluCg==",
      "contentType": "text/x-go",
      "path": "cmd/main.go"
    }
  ],
  "version": 1
}'
Response · 200
{
  "indexed": [
    "cmd/main.go"
  ],
  "refused": [
    {
      "path": ".env",
      "reason": "This looks like a credential, so it was left alone."
    }
  ],
  "version": 1
}

Errors

StatuserrorWhen
401unauthorizedNo valid API key on the request.
POST/v1/api/workspace/reconcileAPI key

Drop what is gone

Tell the project which paths no longer exist on disk, so what it holds matches the folder.

Deletion is a separate call from the push on purpose: a client that crashed mid-scan must not be able to empty a project by reporting the files it had not reached yet as gone.

Body

FieldTypeRequiredDescription
pathsstringrequiredThe paths that are gone, relative to root.
Request · curl
curl -X POST "https://runlogai.com/runlogapi/api/workspace/reconcile" \
  -H "Authorization: Bearer $RUNLOG_API_KEY" \
  -H "X-Project-Id: p7Kd2mQx" \
  -H "Content-Type: application/json" \
  -d '{
  "paths": [
    "cmd/old.go"
  ],
  "version": 1
}'
Response · 200
{
  "refused": [],
  "removed": [
    "cmd/old.go"
  ],
  "version": 1
}

Errors

StatuserrorWhen
401unauthorizedNo valid API key on the request.
POST/v1/projects/{projectId}/workspace-actionsSession

Run a command in your folder

Run one command line in a folder you linked, from the thread in view; its output streams into that thread.

The desktop app lands the project's changes in the folder first (the ordered pass), then posts the line, so the command runs over files that are current. The line runs through your shell on your computer, screened like a turn's own run: a force push or a destructive reset is refused with the reason.

Path parameters

FieldTypeRequiredDescription
projectIdstringrequiredThe project the folder is linked to.

Body

FieldTypeRequiredDescription
bindingIdstringrequiredThe folder's binding, as the project lists it.
runIdstringrequiredThe thread the output lands in.
action.commandstringrequiredThe command line.
Request · curl
curl -X POST "https://runlogai.com/runlogapi/projects/p7Kd2mQx/workspace-actions" \
  -H "Authorization: Bearer $RUNLOG_SESSION_TOKEN" \
  -H "X-Project-Id: p7Kd2mQx" \
  -H "Content-Type: application/json" \
  -d '{
  "action": {
    "command": "go test ./..."
  },
  "bindingId": "b_7f3k",
  "runId": "run_01"
}'
Response · 200
{
  "answer": {
    "status": "pending"
  },
  "callId": "c_9x2"
}

Errors

StatuserrorWhen
403git push --force overwrites history others may holdthe line is one Runlog never runs
404this folder is not one you linked to the projectthe binding is another member's or gone