Pull requests and sync
To open a session's pull request, send /kosuke:open-pr as a message, or $kosuke:open-pr on a Codex session. The agent commits and pushes the work, writes the title and body, and opens the pull request against the Target Branch. To bring the branch up to date with the Target Branch, send /kosuke:sync-branch the same way. Both run as ordinary turns, so you follow them like any other turn.
Pick the invocation character
The character follows the session's provider. Read model from GET /api/projects/{projectId}/chat-sessions/{sessionId}.
Session model starts with | Send |
|---|---|
anthropic:, zai: or moonshot: | /kosuke:open-pr, /kosuke:sync-branch |
openai: | $kosuke:open-pr, $kosuke:sync-branch |
A session that has not run a turn yet may have no model. It takes the provider of its Assignee's Default Model.
Open a pull request
-
Send the invocation to
POST .../jobs/chat, with any flags after it.curl -s -X POST "https://app.kosuke.ai/api/projects/$PROJECT_ID/chat-sessions/$SESSION_ID/jobs/chat" \-H "Authorization: Bearer $KOSUKE_API_KEY" \-H "Content-Type: application/json" \-d '{"content": "/kosuke:open-pr -r alice,bruno -e https://example.com/checkout-demo.mp4"}' -
Read
deliveryin the answer. Withjob, follow the turn by itschatJobId. Withqueued, a turn was running and the message waits Up next. It starts its own turn when the running one completes, unless that turn fails, is stopped or asks a Clarification, or the session is then Under Review, which pauses Up next. -
Wait for the turn to end, as Messages and turns shows.
-
When it ends
completed, readprUrlfromGET /api/projects/{projectId}/chat-sessions/{sessionId}.
The CLI sends the same message:
kosuke sessions send $PROJECT_ID $SESSION_ID --content "/kosuke:open-pr -d"
From the MCP server, the submit tool picks the character and sends the skill for you.
Flags
Write the flags after the command in the same message.
| Flag | What it does |
|---|---|
-d, --draft | Opens the pull request as a draft. Ignored when a pull request is already open. |
-r <names>, --reviewers <names> | Requests reviewers. Separate names with commas or spaces. The agent matches them loosely against GitHub logins. |
-e <links>, --evidence <links> | Adds an evidence section with these links, such as a recording, a screenshot or a preview URL. |
| Any other text | Extra context for the pull request body. |
Without -d, the pull request opens ready for review, and the session's status becomes under-review. A draft keeps it active. When the session already has an open pull request, /kosuke:open-pr brings it up to date. It rewrites the body and, when you pass -r, the reviewer list.
Outcomes
| The turn ends | What it means | What to do |
|---|---|---|
completed | The pull request is open or up to date. | Read prUrl from the session. |
awaiting_response | The agent needs a decision. It asks which GitHub login a -r name means when several or none match. It also asks which branch to target when the Target Branch changed after the pull request opened. | Send your answer as the next message. |
failed | The turn stopped early. | Read error on the job and prUrl on the session, then send /kosuke:open-pr again. |
cancelled | A member stopped the turn. | Send /kosuke:open-pr again. |
To mark a draft ready for review, set status to under-review with PUT on Chat sessions. Setting it back to active turns the pull request into a draft again. A merge on GitHub moves the session to Completed, and closing the pull request moves it to Archived.
Sync with the Target Branch
A session needs a sync when GET /api/projects/{projectId}/chat-sessions/{sessionId} shows isBehind: true. In the list from GET /api/chat-sessions, a session with an open pull request that has not run /kosuke:ship then carries needsYouReason: behind, unless a more severe reason wins. See Chat sessions.
-
Send
/kosuke:sync-branchtoPOST .../jobs/chat. It needs no flags: the skill syncs with the open pull request's base when there is one, and otherwise with the Target Branch.curl -s -X POST "https://app.kosuke.ai/api/projects/$PROJECT_ID/chat-sessions/$SESSION_ID/jobs/chat" \-H "Authorization: Bearer $KOSUKE_API_KEY" \-H "Content-Type: application/json" \-d '{"content": "/kosuke:sync-branch"}' -
Follow the turn. The agent fetches the branch it syncs with and merges it, rebasing only when you ask or the branch was never published. It resolves conflicts by what each side meant, checks that the project still builds, and re-runs setup and restarts the project's services.
-
If the turn ends
awaiting_response, a conflict needs your call. The Clarification names the file and offers to keep this branch's version, take the Target Branch's, or describe another resolution. Send your choice as the next message. -
When the turn ends
completed, read the reply for what came in and how each conflict was resolved.
Whether the agent pushes the merge follows your Commits preference, set in Your account and preferences. With Automatic, it pushes, and the session stops reading behind. With Manual, the merge commit waits in the sandbox. Push it with POST .../preview/git/push, as Files and commits shows.
Limits
- Either skill sent as a member to an Under Review session resumes it first: the pull request turns back into a draft and the session becomes Active. Mark the pull request ready again when the turn ends. A Cron, another session or a Slack relay gets
400and must setstatustoactivefirst. - A Backlog session has no branch yet. Start it with
POST .../activatebefore you send either skill.
Errors
Both requests go through POST .../jobs/chat and return its errors. The ones you meet most here:
| Status | Code | When |
|---|---|---|
| 400 | BAD_REQUEST | The session is Backlog, Completed or Archived. |
| 400 | SESSION_UNDER_REVIEW | The session is Under Review and the message cannot resume it. The sender is a Cron, another session or a Slack relay, or the session went Under Review while the message was on its way. A member sends again to resume. |
| 402 | CREDIT_LIMIT_REACHED | The workspace is blocked on billing. |
| 409 | SANDBOX_STARTING | The sandbox is still starting. Send again in a few seconds. |
| 409 | SANDBOX_LIMIT_REACHED | Waking the paused sandbox, or starting a missing one, would pass the workspace's concurrent sandbox limit. |
Messages and turns lists the codes a send returns, and Responses and errors has the full table.