Skip to main content
Better Hub provides AI chat capabilities for interacting with GitHub repositories, pull requests, issues, and general GitHub operations.

POST /api/ai/ghost

Create or continue an AI conversation with context-aware GitHub assistance. Supports streaming responses with tool execution.
messages
array
required
Array of conversation messages with role and content
{
  role: 'user' | 'assistant' | 'system',
  content: string,
  parts?: Array<{type: 'text', text: string}>
}
prContext
object
Pull request context for PR-specific assistance
owner
string
required
Repository owner
repo
string
required
Repository name
pullNumber
number
required
Pull request number
prTitle
string
required
Pull request title
prBody
string
Pull request description
baseBranch
string
required
Base branch name
headBranch
string
required
Head branch name
files
array
Array of changed files with patches
mergeConflict
boolean
Whether the PR has merge conflicts
issueContext
object
Issue context for issue-specific assistance
owner
string
required
Repository owner
repo
string
required
Repository name
issueNumber
number
required
Issue number
title
string
required
Issue title
body
string
Issue description
state
string
Issue state (open/closed)
labels
array
Array of label names
pageContext
object
Current page context for better assistance
pathname
string
Current page pathname

Response (Streaming)

Returns a streaming response with AI-generated text and tool execution results.
stream
ReadableStream
Server-sent events stream containing:
  • Text chunks from the AI model
  • Tool execution results
  • Usage statistics
const response = await fetch('/api/ai/ghost', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({
    messages: [
      { role: 'user', content: 'Review this pull request for potential issues' }
    ],
    prContext: {
      owner: 'acme',
      repo: 'app',
      pullNumber: 42,
      prTitle: 'Add user authentication',
      prBody: 'Implements JWT-based authentication',
      baseBranch: 'main',
      headBranch: 'feature/auth',
      files: [
        { filename: 'auth.ts', patch: '...' }
      ]
    }
  })
});

const reader = response.body.getReader();
while (true) {
  const { done, value } = await reader.read();
  if (done) break;
  // Process streaming chunks
}
This endpoint consumes AI credits and is subject to rate limiting. Check /api/rate-limit and /api/billing/spending-limit before making requests.

GET /api/ai/ghost/[id]/stream

Resume an existing AI conversation stream that was interrupted.
id
string
required
Context key for the conversation
resumeAt
number
Stream position to resume from (in bytes)

Response

stream
ReadableStream
Continuation of the existing stream from the specified position
const response = await fetch('/api/ai/ghost/pr-123/stream?resumeAt=2048', {
  method: 'GET'
});

const reader = response.body.getReader();
// Continue reading stream

POST /api/ai/command

Execute AI-powered GitHub commands via natural language (used in command palette).
messages
array
required
Array of conversation messages
pageContext
object
Current page context including:
page
string
Current page type (repo, issue, pr, etc.)
pathname
string
Current URL pathname
entities
array
Entities visible on current page
{
  type: string,
  id: string,
  name: string,
  [key: string]: unknown
}

Response

stream
ReadableStream
Streaming response with command execution results
const response = await fetch('/api/ai/command', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({
    messages: [
      { role: 'user', content: 'Star this repository' }
    ],
    pageContext: {
      page: 'repo',
      pathname: '/repos/vercel/next.js',
      entities: [
        { type: 'repo', id: 'vercel/next.js', name: 'Next.js' }
      ]
    }
  })
});

POST /api/ai/commit-message

Generate AI-powered commit messages from file changes or PR information.
mode
string
Generation mode: "squash" for PR squash commits or omit for single file commits

For Single File Commits

filename
string
required
Name of the changed file
originalContent
string
required
Original file content
newContent
string
required
Modified file content

For PR Squash Commits

prTitle
string
required
Pull request title
prBody
string
Pull request description
prNumber
number
required
Pull request number
commits
array
Array of commit messages to squash (max 30)

Response

message
string
Generated commit message (for single file)
title
string
Generated commit title (for squash)
description
string
Generated commit description (for squash)
const response = await fetch('/api/ai/commit-message', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({
    filename: 'auth.ts',
    originalContent: 'const auth = null;',
    newContent: 'const auth = new AuthService();'
  })
});

const data = await response.json();
// { message: "feat: initialize AuthService in auth.ts" }
This endpoint consumes AI credits. Maximum code length is determined by the model context window.

Chat History Endpoints

GET /api/ai/chat-history

Retrieve chat conversation history.
contextKey
string
Context key for a specific conversation
list
string
Set to "ghost" to list all ghost chat conversations

Response

conversation
object
Conversation metadata
id
string
Conversation ID
userId
string
User ID
chatType
string
Type of chat (ghost, command, etc.)
contextKey
string
Context identifier
title
string
Conversation title
activeStreamId
string
Active stream ID if streaming
createdAt
string
Creation timestamp
updatedAt
string
Last update timestamp
messages
array
Array of conversation messages
const response = await fetch('/api/ai/chat-history?contextKey=pr-123');
const data = await response.json();
/*
{
  conversation: {
    id: "conv_123",
    userId: "user_456",
    chatType: "ghost",
    contextKey: "pr-123",
    title: "Review PR #123",
    createdAt: "2024-01-15T10:00:00Z",
    updatedAt: "2024-01-15T10:05:00Z"
  },
  messages: [
    {
      id: "msg_1",
      role: "user",
      content: "Review this PR",
      createdAt: "2024-01-15T10:00:00Z"
    }
  ]
}
*/

POST /api/ai/chat-history

Save a message to a conversation.
contextKey
string
required
Context key for the conversation
chatType
string
required
Type of chat
message
object
required
Message to save

DELETE /api/ai/chat-history

Delete a conversation.
conversationId
string
required
ID of conversation to delete

Ghost Tab Management

GET /api/ai/ghost-tabs

Get the current state of Ghost chat tabs for the user.

Response

tabs
array
Array of active tabs
activeTabId
string
Currently active tab ID
counter
number
Tab counter for generating new tab IDs

POST /api/ai/ghost-tabs

Manage Ghost chat tabs.
action
string
required
Action to perform: "add", "close", "rename", or "switch"
tabId
string
Tab ID (required for all actions)
label
string
Tab label (required for add and rename)
counter
number
Counter value (required for add)
newDefault
string
New default tab ID (for close action)
const response = await fetch('/api/ai/ghost-tabs', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({
    action: 'add',
    tabId: 'tab-1',
    label: 'New Chat',
    counter: 1
  })
});