Skip to main content

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 withSend
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​

  1. 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"}'
  2. Read delivery in the answer. With job, follow the turn by its chatJobId. With queued, 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.

  3. Wait for the turn to end, as Messages and turns shows.

  4. When it ends completed, read prUrl from GET /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.

FlagWhat it does
-d, --draftOpens 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 textExtra 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 endsWhat it meansWhat to do
completedThe pull request is open or up to date.Read prUrl from the session.
awaiting_responseThe 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.
failedThe turn stopped early.Read error on the job and prUrl on the session, then send /kosuke:open-pr again.
cancelledA 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.

  1. Send /kosuke:sync-branch to POST .../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"}'
  2. 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.

  3. 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.

  4. 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 400 and must set status to active first.
  • A Backlog session has no branch yet. Start it with POST .../activate before you send either skill.

Errors​

Both requests go through POST .../jobs/chat and return its errors. The ones you meet most here:

StatusCodeWhen
400BAD_REQUESTThe session is Backlog, Completed or Archived.
400SESSION_UNDER_REVIEWThe 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.
402CREDIT_LIMIT_REACHEDThe workspace is blocked on billing.
409SANDBOX_STARTINGThe sandbox is still starting. Send again in a few seconds.
409SANDBOX_LIMIT_REACHEDWaking 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.

Next steps​