Skip to main content

Output Contract

This page documents the current CLI output behavior as implemented in the repo.

Core Rules

  1. Most commands print pretty-formatted JSON to stdout on success.
  2. kagi search, kagi batch, kagi quick, and kagi assistant support alternate output via format flags, including toon for token-efficient structured context.
  3. Errors are plain text on stderr and exit with status code 1.
  4. Output shapes differ by command. There is no single universal response envelope.

Success Shapes

{
  "data": [
    {
      "t": 0,
      "rank": 1,
      "title": "Result Title",
      "url": "https://example.com",
      "snippet": "Description...",
      "published": "2026-03-16T00:00:00Z"
    }
  ]
}

kagi search --news

The News tab vertical returns a different shape — clusters of articles:
{
  "query": "iran",
  "clusters": [
    {
      "items": [
        {
          "title": "Headline",
          "url": "https://www.example.com/article",
          "source": "example.com",
          "time_relative": "2 hours ago",
          "snippet": "Optional snippet text.",
          "paywall": false,
          "image_url": "https://img.example/lead.jpg"
        }
      ]
    }
  ]
}
time_relative is preserved verbatim from Kagi’s page (the News tab does not expose absolute timestamps). Single-item clusters represent ungrouped articles at the top of the results page.

kagi batch

Default JSON output uses a structured envelope:
{
  "queries": ["rust", "go"],
  "results": [
    {
      "data": [
        {
          "t": 0,
          "rank": 1,
          "title": "Result Title",
          "url": "https://example.com",
          "snippet": "Description...",
          "published": "2026-03-16T00:00:00Z"
        }
      ]
    }
  ]
}

kagi summarize

Public API mode:
{
  "meta": {
    "id": "1",
    "node": "us-east",
    "ms": 10
  },
  "data": {
    "output": "summary text",
    "tokens": 42
  }
}
Subscriber mode:
{
  "meta": {
    "version": "202603091651.stage.c128588",
    "trace": "abc123"
  },
  "data": {
    "thread_id": "thread-1",
    "state": "done",
    "output": "summary text",
    "markdown": "summary text"
  }
}

kagi news

{
  "latest_batch": {
    "id": "batch-123",
    "created_at": "2026-03-16T00:00:00Z"
  },
  "category": {
    "category_id": "tech",
    "category_name": "Technology"
  },
  "stories": [],
  "total_stories": 20,
  "domains": [],
  "read_count": 1234
}
kagi news --list-categories and kagi news --chaos return different JSON shapes with category metadata or chaos metadata.

kagi assistant

{
  "meta": {
    "version": "202603091651.stage.c128588",
    "trace": "trace-123"
  },
  "thread": {
    "id": "thread-1",
    "title": "Greeting",
    "created_at": "2026-03-16T06:19:07Z"
  },
  "message": {
    "id": "msg-1",
    "thread_id": "thread-1",
    "created_at": "2026-03-16T06:19:07Z",
    "state": "done",
    "prompt": "Hello",
    "markdown": "Hi"
  }
}
kagi assistant --stream writes incremental markdown deltas to stdout and flushes after each update. kagi assistant --stream --stream-output json writes the same stream as newline-delimited compact JSON events with an md_delta field plus the current meta, thread, and message snapshot.

kagi assistant custom

list returns an array of assistant summaries:
[
  {
    "id": "assistant-1",
    "name": "Research",
    "invoke_profile": "research",
    "model": "gpt-5-4-nano",
    "bang_trigger": "research",
    "internet_access": true,
    "built_in": false,
    "edit_url": "/assistant/custom-assistants/assistant-1"
  }
]
get, create, and update return assistant details:
{
  "profile_id": "assistant-1",
  "name": "Research",
  "bang_trigger": "research",
  "internet_access": true,
  "selected_lens": "",
  "personalizations": false,
  "base_model": "gpt-5-4-nano",
  "custom_instructions": "Focus on changelogs first.",
  "delete_supported": true
}

kagi lens

[
  {
    "id": "42",
    "name": "Rust Docs",
    "description": "Rust docs only",
    "enabled": true,
    "position": 2,
    "edit_url": "/settings/lenses/edit/42"
  }
]

kagi bang custom

[
  {
    "id": "7",
    "name": "Rust Docs",
    "trigger": "rustdocs",
    "shortcut_menu": true,
    "edit_url": "/settings/custom_bangs/edit/7"
  }
]

kagi redirect

[
  {
    "id": "12",
    "rule": "^gh/(.+)$|https://github.com/$1",
    "enabled": true,
    "edit_url": "/rewrite_rules/edit/12"
  }
]

kagi quick

{
  "meta": {
    "version": "202603171911.stage.707e740",
    "trace": "trace-123"
  },
  "query": "what is rust",
  "lens": null,
  "message": {
    "id": "msg-1",
    "thread_id": "thread-1",
    "created_at": "2026-03-19T00:00:00Z",
    "state": "done",
    "prompt": "what is rust",
    "html": "<p>Rust is a systems programming language.</p>",
    "markdown": "Rust is a systems programming language."
  },
  "references": {
    "markdown": "[^1]: [Rust](https://www.rust-lang.org/) (26%)",
    "items": [
      {
        "index": 1,
        "title": "Rust",
        "domain": "www.rust-lang.org",
        "url": "https://www.rust-lang.org/",
        "contribution_pct": 26
      }
    ]
  },
  "followup_questions": [
    "Why is Rust memory-safe?"
  ]
}

kagi translate

{
  "bootstrap": {
    "method": "reqwest(set-cookie bootstrap)",
    "authenticated": true
  },
  "detected_language": {
    "iso": "fr",
    "label": "French"
  },
  "translation": {
    "translation": "Hello everyone",
    "source_language": "fr",
    "target_language": "en"
  },
  "alternatives": {
    "elements": []
  },
  "text_alignments": {
    "alignments": []
  },
  "translation_suggestions": {
    "suggestions": []
  },
  "word_insights": {
    "insights": []
  },
  "warnings": []
}

kagi ask-page

{
  "meta": {
    "version": "202603171911.stage.707e740",
    "trace": "trace-123"
  },
  "source": {
    "url": "https://rust-lang.org/",
    "question": "What is this page about?"
  },
  "thread": {
    "id": "thread-1",
    "title": "Rust Programming Language Website",
    "created_at": "2026-03-19T17:58:59Z"
  },
  "message": {
    "id": "msg-1",
    "thread_id": "thread-1",
    "state": "done",
    "prompt": "https://rust-lang.org/\nWhat is this page about?",
    "markdown": "This page is about the Rust programming language."
  }
}

kagi fastgpt

{
  "meta": {
    "id": "1",
    "node": "us-east",
    "ms": 10
  },
  "data": {
    "output": "answer text",
    "tokens": 12,
    "references": []
  }
}

kagi enrich

{
  "meta": {
    "id": "1",
    "node": "us-east",
    "ms": 10
  },
  "data": [
    {
      "title": "Result Title",
      "url": "https://example.com",
      "snippet": "Description...",
      "published": "2026-03-16T00:00:00Z"
    }
  ]
}

kagi smallweb

{
  "xml": "<?xml version=\"1.0\"?><rss>...</rss>"
}

Pretty Search Output

kagi search --format pretty renders results like this:
1. Result Title
   https://example.com

   Description...
If the result set is empty, the CLI prints:
No results found.

Pretty Quick Output

kagi quick --format pretty renders:
Quick Answer

Rust is a systems programming language...

References

1. Learn (35%)
   https://www.rust-lang.org/learn

Pretty Assistant Output

kagi assistant --format pretty renders:
Thread: thread-1
Message: msg-1

Rust 1.86 added...

Error Behavior

Errors are plain text on stderr. Typical examples:
Config error: missing credentials: set KAGI_API_KEY or KAGI_SESSION_TOKEN (env), or add [auth] api_key/session_token to .kagi.toml
Auth error: invalid or expired Kagi session token
Network error: request to Kagi timed out

jq Examples

# Search URLs
kagi search "rust" | jq -r '.data[].url'

# FastGPT answer text
kagi fastgpt "What is Rust?" | jq -r '.data.output'

# Assistant markdown reply
kagi assistant "Hello" | jq -r '.message.markdown'

# Quick Answer markdown reply
kagi quick "what is rust" | jq -r '.message.markdown'

# Quick Answer references
kagi quick "what is rust" | jq -r '.references.items[].url'

# Translate text
kagi translate "Bonjour tout le monde" | jq -r '.translation.translation'

# Ask-page markdown reply
kagi ask-page https://rust-lang.org/ "What is this page about?" | jq -r '.message.markdown'

# Assistant thread ids
kagi assistant thread list | jq -r '.threads[].id'

# Assistant thread export markdown
kagi assistant thread export "$THREAD_ID"

# Assistant profile names
kagi assistant custom list | jq -r '.[].name'

# Lens names
kagi lens list | jq -r '.[].name'

# Bang triggers
kagi bang custom list | jq -r '.[].trigger'

# Enabled redirect rules
kagi redirect list | jq -r '.[] | select(.enabled) | .rule'

# Subscriber summary text
kagi summarize --subscriber --url https://example.com | jq -r '.data.output'

# Small Web raw feed
kagi smallweb | jq -r '.xml'