Skip to content

Instantly share code, notes, and snippets.

@SaseQ
Last active September 1, 2025 01:42
Show Gist options
  • Save SaseQ/c2a20a38b11276537ec5332d1f7a5e53 to your computer and use it in GitHub Desktop.
Save SaseQ/c2a20a38b11276537ec5332d1f7a5e53 to your computer and use it in GitHub Desktop.
Atlassian Rovo Dev CLI transformer for Claude Code Router
{
"transformers": [
{
"path": "$HOME/.claude-code-router/plugins/rovo-cli.js",
"options": {
"email": "ROVO_DEV_EMAIL",
"api_token": "ROVO_DEV_API_TOKEN"
}
}
],
"Providers": [
{
"name": "rovo-cli",
"api_base_url": "https://api.atlassian.com/rovodev/v2/proxy/ai/v1/openai/v1/chat/completions",
"api_key": "sk-xxx",
"models": ["gpt-5-2025-08-07"],
"transformer": {
"use": ["rovo-cli"]
}
}
],
"Router": {
"default": "rovo-cli,gpt-5-2025-08-07"
}
}
const os = require("os");
const path = require("path");
const fs = require("fs/promises");
class RovoCLITransformer {
name = "rovo-cli";
constructor(options) {
this.options = options;
}
async transformRequestIn(request, provider) {
const body = typeof request === "string" ? JSON.parse(request) : { ...request };
if (Object.prototype.hasOwnProperty.call(body, "max_tokens")) {
if (!Object.prototype.hasOwnProperty.call(body, "max_completion_tokens")) {
body.max_completion_tokens = body.max_tokens;
}
delete body.max_tokens;
}
if (body.params && typeof body.params === "object") {
if (Object.prototype.hasOwnProperty.call(body.params, "max_tokens")) {
if (!Object.prototype.hasOwnProperty.call(body.params, "max_completion_tokens")) {
body.params.max_completion_tokens = body.params.max_tokens;
}
delete body.params.max_tokens;
}
}
const toolsToAdd = await this.getDefaultRovoTools();
const existingTools = Array.isArray(body.tools) ? body.tools : [];
const byName = new Map();
for (const t of existingTools) {
const key = t?.function?.name || JSON.stringify(t);
byName.set(key, t);
}
for (const t of toolsToAdd) {
const key = t?.function?.name || JSON.stringify(t);
if (!byName.has(key)) byName.set(key, t);
}
body.tools = Array.from(byName.values());
const email = this.options?.email;
const api_token = this.options?.api_token;
const basicToken = Buffer.from(`${email}:${api_token}`, "utf-8").toString("base64");
return {
body,
config: {
headers: {
Authorization: `Basic ${basicToken}`,
},
},
};
}
getDefaultRovoTools() {
return [
{
"type": "function",
"function": {
"name": "open_files_legacy",
"description": "IGNORE THE TOOL. Kept for legacy. Open one or more files in the workspace. Supports text, image, and PDF documents.\n",
"parameters": {
"type": "object",
"properties": {
"file_paths": {
"type": "array",
"items": {"type": "string"},
"description": "A list of file paths to open."
}
},
"required": ["file_paths"]
}
}
},
{
"type": "function",
"function": {
"name": "create_file_legacy",
"description": "IGNORE THE TOOL. Kept for legacy. Create a file in the workspace.\n",
"parameters": {
"type": "object",
"properties": {
"file_path": {"type": "string"}
},
"required": ["file_path"]
}
}
},
{
"type": "function",
"function": {
"name": "expand_code_chunks_legacy",
"description": "IGNORE THE TOOL. Kept for legacy. Expand line ranges or code chunks within a file and return the expanded content.\n\nCode can be expanded by specifying line ranges or by searching for code symbols in the code, separating levels of\nhierarchy with slashes.\n\nExample patterns:\n- \"MyClass\": Selects the class definition and any references to MyClass.\n- \"my_function\": Selects the function definition and any uses of my_function.\n- \"def my_function\": Selects only the function definition for my_function.\n- \"MyClass/my_method\": Selects the method my_method within MyClass using slash separator.",
"parameters": {
"type": "object",
"properties": {
"file_path": {"type": "string"}
},
"required": ["file_path"]
}
}
}
];
}
}
module.exports = RovoCLITransformer;
@SaseQ
Copy link
Author

SaseQ commented Aug 15, 2025

@dav1lex Just fill in the email and api_token, leave the api_key as it is.

Go to your Atlassian profile, select Create API token, and create an unscoped API token.

@dav1lex
Copy link

dav1lex commented Aug 15, 2025

@SaseQ Jestem na windowsie,config tak wygląda ale nie działa, czy widzisz gdzie jest błąd? Tak samo z googlem, nie działa. Pobrałem nowy gemini-cli z repo, ale coś po prostu tu nie gra. config:
{ "LOG": false, "LOG_LEVEL": "info", "CLAUDE_PATH": "", "HOST": "127.0.0.1", "PORT": 3456, "APIKEY": "", "API_TIMEOUT_MS": "600000", "PROXY_URL": "", "transformers": [ { "name": "rovo-cli", "path": "C:\\Users\\admin\\.claude-code-router\\plugins\\rovo-cli.js", "options": { "email": "[email protected]", "api_token": "token without scope" } } ], "Providers": [ { "name": "rovo-cli", "api_base_url": "https://api.atlassian.com/rovodev/v2/proxy/ai/v1/openai/v1/chat/completions", "api_key": "api key", "models": [ "gpt-5-2025-08-07" ], "transformer": { "use": [ "rovo-cli" ], "gpt-5-2025-08-07": { "use": [ "rovo-cli" ] } } } ], "StatusLine": { "enabled": false, "currentStyle": "default", "default": { "modules": [] }, "powerline": { "modules": [] } }, "Router": { "default": "rovo-cli,gpt-5-2025-08-07", "background": "", "think": "", "longContext": "", "longContextThreshold": 60000, "webSearch": "" }, "stream": false }

@SaseQ
Copy link
Author

SaseQ commented Aug 15, 2025

@dav1lex Napisze po angielsku jakby ktoś kiedyś miał ten sam problem.
Copy configuration from top of this page, change only the transformers: path, email, and api_token sections, do not change anything else, and try testing it this way.

@dav1lex
Copy link

dav1lex commented Aug 15, 2025

@SaseQ OK figured it out and works well, thank you

@StarTrai1
Copy link

@SaseQ If I want to use the Claude4 ,what should I change the api_base_url to?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment