Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions .gitleaks.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,14 @@ useDefault = true
description = "Exclude test files and build artifacts containing intentional fake secrets"
paths = [
'''src/utils/__tests__/sanitize\.test\.ts$''',
'''src/providers/plugins/azure-openai/__tests__/''',
'''dist/''',
'''\.idea/''',
'''\.mcp\.json'''
]
# Ignore well-known no-entropy test placeholder strings that appear in diffs
# when replacing old fixture values. These are not real secrets.
stopwords = [
"test-api-key-1234567890",
"PLACEHOLDER-KEY-FOR-TESTING-ONLY"
]
21 changes: 16 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
[![TypeScript](https://img.shields.io/badge/TypeScript-5.3%2B-blue.svg)](https://www.typescriptlang.org/)
[![License](https://img.shields.io/badge/License-Apache_2.0-blue.svg)](https://opensource.org/licenses/Apache-2.0)

> **Unified AI Coding Assistant CLI** - Manage Claude Code, OpenAI Codex, GitHub Copilot CLI, Google Gemini, OpenCode, Pi, Kimi Code, and custom AI agents from one powerful command-line interface. Multi-provider support (CodeMie SSO, Bearer Auth, LiteLLM, AWS Bedrock, Ollama, Anthropic Subscription, Moonshot Subscription). Built-in native agent with file operations, command execution, planning mode, and plugins. Cross-platform support for Windows, Linux, and macOS.
> **Unified AI Coding Assistant CLI** - Manage Claude Code, OpenAI Codex, GitHub Copilot CLI, Google Gemini, OpenCode, Pi, Kimi Code, and custom AI agents from one powerful command-line interface. Multi-provider support (CodeMie SSO, Bearer Auth, LiteLLM, Azure OpenAI, AWS Bedrock, Ollama, Anthropic Subscription, Moonshot Subscription). Built-in native agent with file operations, command execution, planning mode, and plugins. Cross-platform support for Windows, Linux, and macOS.

---

Expand All @@ -23,7 +23,7 @@
CodeMie CLI is the all-in-one AI coding assistant for developers.

- ✨ **One CLI, Multiple AI Agents** - Switch between Claude Code, OpenAI Codex, GitHub Copilot CLI, Gemini, OpenCode, Pi, Kimi Code, and built-in agent.
- 🔄 **Multi-Provider Support** - CodeMie SSO, Bearer Authorization, LiteLLM, AWS Bedrock, Ollama, Anthropic Subscription, and Moonshot Subscription.
- 🔄 **Multi-Provider Support** - CodeMie SSO, Bearer Authorization, LiteLLM, Azure OpenAI, AWS Bedrock, Ollama, Anthropic Subscription, and Moonshot Subscription.
- 🚀 **Built-in Agent** - `codemie-code` ships with the CLI: file operations, command execution, planning mode, and native plugins.
- 🖥️ **Cross-Platform** - Full support for Windows, Linux, and macOS with platform-specific optimizations.
- 🔗 **MCP Proxy** - Connect to remote MCP servers with automatic OAuth authorization.
Expand Down Expand Up @@ -197,7 +197,7 @@ codemie-code --plugin-dir ./my-plugins # load native plugins
codemie-code --debug # debug logging
```

Providers: CodeMie SSO, Bearer Auth, LiteLLM, AWS Bedrock, Ollama.
Providers: CodeMie SSO, Bearer Auth, LiteLLM, Azure OpenAI, AWS Bedrock, Ollama.

### External Agents

Expand Down Expand Up @@ -260,7 +260,7 @@ Supported managed path for this release:
- **Uninstall:** `codemie uninstall copilot`
- **Launch:** `codemie-copilot`
- **One-shot task:** `codemie-copilot --task "Explain this service"`
- **Supported providers:** CodeMie SSO and LiteLLM
- **Supported providers:** CodeMie SSO, LiteLLM, and Azure OpenAI (classic Chat Completions)

Requirements and behavior:

Expand Down Expand Up @@ -326,13 +326,24 @@ A profile binds an agent to a provider. Run `codemie setup` to create one, or `c
| CodeMie SSO | enterprise SSO | Enterprise default — centralized model management, proxy routing, analytics |
| Bearer Authorization | JWT via CLI or env var | CI, service accounts, self-hosted gateways |
| LiteLLM | API key | Universal gateway to 100+ LLM providers (OpenAI, Azure, Vertex, …) |
| Azure OpenAI | API key + endpoint | OpenAI-compatible classic Chat Completions clients |
| AWS Bedrock | AWS access key + secret | Claude, Llama, Mistral & more via Amazon Bedrock |
| Ollama | none | Local open-source models, offline work |
| Anthropic Subscription | native Claude Code login | Bring your own Claude subscription |
| Moonshot Subscription | native Kimi Code login | Bring your own Moonshot subscription (Kimi Code) |

See [Authentication](docs/AUTHENTICATION.md) and [Configuration](docs/CONFIGURATION.md) for setup details.

### Azure for Protocol-Specific Agents

The `azure-openai` provider is intentionally not supported directly by `codemie-claude`,
`codemie-claude-acp`, `codemie-codex`, or `codemie-gemini`. These agents use different
client protocols: Anthropic Messages, OpenAI Responses, and Gemini's native API.

To use Azure-backed models with these agents, run LiteLLM as an externally managed gateway.
Configure LiteLLM to expose the protocol expected by the client and route the request to the
Azure deployment. CodeMie stores the LiteLLM URL and key but does not install or run LiteLLM.

### CodeMie Assistants as Claude Skills or Subagents

CodeMie can connect assistants available in your CodeMie account directly into Claude Code. Register them as Claude subagents and call them with `@slug`, or register them as Claude skills and invoke them with `/slug`.
Expand Down Expand Up @@ -474,7 +485,7 @@ codemie-pi --resume <session-id> # open a specific session
| **Required packages** | `pi-mcp-adapter` (Pi ships without built-in MCP), `pi-subagents`, `superpowers` — installed at setup. |
| **Session analytics** | An injected extension records tokens, tools, and models per session and syncs at session end; visible in `codemie analytics`. |

Providers: CodeMie SSO, Bearer Auth, LiteLLM.
Providers: CodeMie SSO, Bearer Auth, LiteLLM, Azure OpenAI (classic Chat Completions).

## Claude Code Statusline

Expand Down
17 changes: 11 additions & 6 deletions docs/AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,10 @@ Anthropic's official CLI with advanced code understanding.
- Interactive conversations
- Non-interactive mode with `-p` flag

**Provider compatibility:**
- LiteLLM, AI/Run SSO, AWS Bedrock, Bearer Auth, Anthropic Subscription, and Ollama are supported.
- Direct Azure OpenAI is not supported; use an external LiteLLM gateway for Azure-backed Claude models.

**Usage:**
```bash
codemie-claude # Interactive mode
Expand All @@ -70,7 +74,8 @@ ACP (Agent Communication Protocol) is a stdio-based JSON-RPC protocol that enabl

**Requirements:**
- Node.js 20.0.0 or higher
- Supported providers: LiteLLM, AI/Run SSO, or direct Anthropic API access
- Supported providers: LiteLLM, AI/Run SSO, AWS Bedrock, Bearer Auth, Anthropic Subscription, or Ollama
- Direct Azure OpenAI is not supported; use an external LiteLLM gateway for Azure-backed models
- IDE with ACP support (Zed, JetBrains, Emacs, etc.)

**Features:**
Expand Down Expand Up @@ -133,9 +138,9 @@ Google's Gemini AI coding assistant with advanced code understanding.
**Installation:** `codemie install gemini`

**Requirements:**
- **Requires a valid Google Gemini API key** from https://aistudio.google.com/apikey
- **Direct API access requires a valid Google Gemini API key** from https://aistudio.google.com/apikey
- **Requires Gemini-compatible models only** (gemini-2.5-flash, gemini-2.5-pro, etc.)
- LiteLLM or AI-Run SSO API keys will **not** work with Gemini CLI
- **Direct Azure OpenAI is not supported**; use an external LiteLLM gateway for Azure-backed Gemini models

**Setup:**
```bash
Expand Down Expand Up @@ -174,7 +179,7 @@ GitHub Copilot CLI managed by CodeMie for CodeMie-routed SSO and LiteLLM session
**Requirements:**
- Node.js 20.0.0 or higher
- An authenticated CodeMie profile (`codemie setup`)
- Supported providers: **AI/Run SSO** or **LiteLLM**
- Supported providers: **AI/Run SSO**, **LiteLLM**, or **Azure OpenAI** (classic Chat Completions)

**Managed-mode behavior:**
- Launch with `codemie-copilot`
Expand Down Expand Up @@ -214,7 +219,7 @@ Open-source AI coding assistant with comprehensive session analytics.

**Requirements:**
- Node.js 20.0.0 or higher
- Supported providers: LiteLLM, AI/Run SSO, or direct API access
- Supported providers: LiteLLM, AI/Run SSO, Azure OpenAI (classic Chat Completions), or direct API access
- OpenCode CLI installed globally (`opencode-ai` npm package)

**Features:**
Expand Down Expand Up @@ -283,7 +288,7 @@ OpenWiki (https://github.com/langchain-ai/openwiki) — an agent that writes and
**Requirements:**
- Node.js 22.0.0 or higher (OpenWiki upstream requirement)
- An authenticated CodeMie profile (`codemie setup`)
- Supported providers: **AI/Run SSO**, **Bearer Auth (JWT)**, **LiteLLM**, **Ollama**, **Moonshot subscription**
- Supported providers: **AI/Run SSO**, **Bearer Auth (JWT)**, **LiteLLM**, **Ollama**, **Moonshot subscription**, or **Azure OpenAI** (classic Chat Completions)

**How CodeMie runs it:**
OpenWiki reads its model access from `OPENWIKI_PROVIDER=openai-compatible` plus `OPENAI_COMPATIBLE_BASE_URL`/`OPENAI_COMPATIBLE_API_KEY`/`OPENWIKI_MODEL_ID`. The CodeMie adapter maps the active profile onto those variables: SSO/JWT profiles go through the local CodeMie proxy (authentication and `X-CodeMie-*` attribution headers are injected there), other providers forward their configured base URL and key. The profile model becomes `OPENWIKI_MODEL_ID`.
Expand Down
2 changes: 1 addition & 1 deletion docs/COMMANDS.md
Original file line number Diff line number Diff line change
Expand Up @@ -601,7 +601,7 @@ codemie profile refresh # Refresh SSO credentials
**Profile List Details:**
The `codemie profile` command displays comprehensive information for each profile:
- Profile name and active status
- Provider (ai-run-sso, openai, azure, bedrock, litellm, gemini)
- Provider (ai-run-sso, openai, azure-openai, bedrock, litellm, gemini)
- Base URL
- Model
- Timeout settings
Expand Down
31 changes: 27 additions & 4 deletions docs/CONFIGURATION.md
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,16 @@ Profiles are stored in `~/.codemie/codemie-cli.config.json`:
"apiKey": "sk-***",
"model": "gpt-4.1",
"timeout": 300
},
"azure-openai": {
"name": "azure-openai",
"provider": "azure-openai",
"baseUrl": "https://resource.openai.azure.com",
"apiKey": "azure-key-***",
"model": "gpt-5.6-luna-2026-07-09",
"azureApiVersion": "2025-04-01-preview",
"azureDeployment": "gpt-5.6-luna-2026-07-09",
"timeout": 300
}
}
}
Expand All @@ -112,11 +122,21 @@ Profiles are stored in `~/.codemie/codemie-cli.config.json`:

- **ai-run-sso** - AI/Run CodeMie SSO (unified enterprise gateway)
- **openai** - OpenAI API
- **azure** - Azure OpenAI
- **azure-openai** - Azure OpenAI for OpenAI-compatible clients
- **bedrock** - AWS Bedrock
- **litellm** - LiteLLM Proxy (universal gateway to 100+ providers)
- **ollama** - Ollama (local models)

### Azure and Protocol-Specific Agents

Direct `azure-openai` is intentionally excluded from Claude Code/ACP, Codex, and Gemini
profiles. Their native request formats are Anthropic Messages, OpenAI Responses, and Gemini's
native API, while the CodeMie Azure endpoint exposes classic Azure OpenAI Chat Completions.

Use an externally managed LiteLLM gateway when these agents need Azure-backed models. The
LiteLLM profile should expose the client-facing protocol and route to the Azure deployment.
CodeMie does not install or manage the LiteLLM process.

## Manual Configuration

### Environment Variables (Highest Priority)
Expand All @@ -127,7 +147,7 @@ Environment variables override config file values and are useful for CI/CD, Dock

| Variable | Description | Default | Example |
|----------|-------------|---------|---------|
| `CODEMIE_PROVIDER` | AI provider (ai-run-sso, litellm, openai, azure, bedrock) | - | `litellm` |
| `CODEMIE_PROVIDER` | AI provider (ai-run-sso, litellm, openai, azure-openai, bedrock) | - | `litellm` |
| `CODEMIE_BASE_URL` | Base URL for API endpoint | - | `https://api.openai.com/v1` |
| `CODEMIE_API_KEY` | API key for authentication | - | `sk-...` |
| `CODEMIE_MODEL` | Model to use | - | `claude-sonnet-4-5-20250929` |
Expand Down Expand Up @@ -158,8 +178,11 @@ Environment variables override config file values and are useful for CI/CD, Dock

| Variable | Description | Default | Example |
|----------|-------------|---------|---------|
| `AZURE_OPENAI_API_VERSION` | Azure API version | `2024-02-01` | `2024-02-01` |
| `OPENAI_ORG_ID` | OpenAI organization ID | - | `org-...` |
| `CODEMIE_AZURE_OPENAI_API_VERSION` | Azure API version for deployment discovery and requests | `2025-04-01-preview` | `2025-04-01-preview` |
| `CODEMIE_AZURE_OPENAI_DEPLOYMENT` | Optional Azure deployment override; otherwise `CODEMIE_MODEL` is used | - | `gpt-5.6-luna-2026-07-09` |

`CODEMIE_AZURE_OPENAI_DEPLOYMENT` overrides `CODEMIE_MODEL` when both are set; both are used as the deployment ID.
`OPENAI_ORG_ID` is not supported for Azure OpenAI.

#### Analytics Configuration

Expand Down
93 changes: 77 additions & 16 deletions scripts/validate-secrets.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
#!/usr/bin/env node
/**
* Cross-platform secrets detection using Gitleaks
* Works on Windows, macOS, and Linux
* Works on Windows (native Docker or Docker-in-WSL), macOS, and Linux
*
* Supports Docker, Podman, and Apple Containers.
* On Windows without Docker Desktop, falls back to Docker running inside WSL2
* by invoking: wsl -e bash -l -c "docker ..."
*
* CI uses the official gitleaks-action@v2 for better GitHub integration.
* Both share the same .gitleaks.toml configuration.
*
Expand Down Expand Up @@ -47,11 +50,32 @@ function appleContainersRunning() {
return spawnSync(bin, ['system', 'status'], { stdio: 'ignore', shell: false }).status === 0;
}

/**
* On Windows, check if Docker is available inside WSL2 by running
* `wsl -e bash -l -c "docker info"`. Returns true if the daemon responds.
*/
function wslDockerRunning() {
if (!isWindows) return false;
const wslBin = resolveCommand('wsl');
if (!wslBin) return false;
const result = spawnSync(wslBin, ['-e', 'bash', '-l', '-c', 'docker info'], {
stdio: 'ignore',
shell: false,
});
return result.status === 0;
}

/**
* Detects the available container engine.
* Returns one of: 'docker' | 'podman' | 'container' | 'wsl-docker' | null
*/
function detectEngine() {
for (const engine of ['docker', 'podman']) {
if (commandExists(engine) && daemonRunning(engine)) return engine;
}
if (appleContainersRunning()) return 'container';
// Fallback: Docker running inside WSL2 on Windows
if (wslDockerRunning()) return 'wsl-docker';
return null;
}

Expand All @@ -67,7 +91,7 @@ if (!engine) {
process.exit(0);
}

const engineBin = resolveCommand(engine);
const engineBin = engine === 'wsl-docker' ? resolveCommand('wsl') : resolveCommand(engine);
if (!engineBin) {
if (process.env.CODEMIE_SKIP_SECRETS_SCAN !== '1') {
console.error('Container engine binary not found — install Docker, Podman, or Apple Containers to enable local secrets scanning.');
Expand All @@ -80,7 +104,6 @@ if (!engineBin) {
// shell:true is used on Windows so paths with spaces must be quoted for the shell.
// On Linux/Mac shell:false passes the path directly to execve — no quoting needed.
const spawnBin = isWindows && engineBin.includes(' ') ? `"${engineBin}"` : engineBin;

// Produce the staged diff on the host so gitleaks doesn't need git access
// inside the container — required for Apple Containers which cannot run git
// against the host .git index through a bind mount.
Expand All @@ -97,24 +120,62 @@ if (!stagedDiff || stagedDiff.length === 0) {
process.exit(0);
}

const args = ['run', '--rm', '-i'];
console.log(`Running Gitleaks secrets detection (engine: ${engine})...`);

if (hasConfig) {
args.push('-v', `${projectPath}/.gitleaks.toml:/gitleaks.toml`);
}
let gitleaks;

args.push('ghcr.io/gitleaks/gitleaks:v8.30.1', 'detect', '--pipe', '--verbose');
if (engine === 'wsl-docker') {
// Docker is inside WSL2: build the full docker command as a shell string
// and pass it via `wsl -e bash -l -c "..."`.
// The .gitleaks.toml is mounted from the WSL-translated Windows path.
const wslBin = resolveCommand('wsl');

if (hasConfig) {
args.push('--config=/gitleaks.toml');
}
// Convert Windows path to WSL /mnt/... path: C:\foo\bar -> /mnt/c/foo/bar
function toWslPath(winPath) {
return winPath.replace(/\\/g, '/').replace(/^([A-Za-z]):/, (_, d) => `/mnt/${d.toLowerCase()}`);
}

console.log('Running Gitleaks secrets detection...');
const wslProjectPath = toWslPath(projectPath);
const wslConfigPath = toWslPath(configPath);

const gitleaks = spawn(spawnBin, args, {
stdio: ['pipe', 'inherit', 'inherit'],
shell: isWindows,
});
let dockerCmd = 'docker run --rm -i';
if (hasConfig) {
dockerCmd += ` -v "${wslConfigPath}:/gitleaks.toml"`;
}
dockerCmd += ' ghcr.io/gitleaks/gitleaks:v8.30.1 detect --pipe --verbose';
if (hasConfig) {
dockerCmd += ' --config=/gitleaks.toml';
}

// Pipe the staged diff into the WSL command via stdin
gitleaks = spawn(wslBin, ['-e', 'bash', '-l', '-c', dockerCmd], {
stdio: ['pipe', 'inherit', 'inherit'],
shell: false,
});
} else {
const engineBin = resolveCommand(engine);
if (!engineBin) {
console.log('Container engine binary not found — skipping secrets detection');
process.exit(1);
}
// shell:true is used on Windows so paths with spaces must be quoted for the shell.
// On Linux/Mac shell:false passes the path directly to execve — no quoting needed.
const spawnBin = isWindows && engineBin.includes(' ') ? `"${engineBin}"` : engineBin;

const args = ['run', '--rm', '-i'];
if (hasConfig) {
args.push('-v', `${projectPath}/.gitleaks.toml:/gitleaks.toml`);
}
args.push('ghcr.io/gitleaks/gitleaks:v8.30.1', 'detect', '--pipe', '--verbose');
if (hasConfig) {
args.push('--config=/gitleaks.toml');
}

gitleaks = spawn(spawnBin, args, {
stdio: ['pipe', 'inherit', 'inherit'],
shell: isWindows,
});
}

gitleaks.stdin.write(stagedDiff);
gitleaks.stdin.end();
Expand Down
9 changes: 7 additions & 2 deletions src/agents/core/BaseAgentAdapter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -567,6 +567,7 @@ export abstract class BaseAgentAdapter implements AgentAdapter {
// Display ASCII logo with configuration
console.log(
renderProfileInfo({
title: 'Profile',
profile: profileName,
provider,
model,
Expand Down Expand Up @@ -952,11 +953,12 @@ export abstract class BaseAgentAdapter implements AgentAdapter {

const isSSOProvider = provider?.authType === 'sso';
const isJWTAuth = env.CODEMIE_AUTH_METHOD === 'jwt';
const isAzureOpenAIProvider = providerName === 'azure-openai';
const isProxyEnabled = this.metadata.ssoConfig?.enabled ?? false;

// Proxy is only for model API authentication/forwarding. Analytics sync can
// be configured independently and must not force native providers through it.
return (isSSOProvider || isJWTAuth) && isProxyEnabled;
return (isSSOProvider || isJWTAuth || isAzureOpenAIProvider) && isProxyEnabled;
}

/**
Expand Down Expand Up @@ -1033,7 +1035,10 @@ export abstract class BaseAgentAdapter implements AgentAdapter {

// Update environment with proxy URL
env.CODEMIE_BASE_URL = url;
env.CODEMIE_API_KEY = 'proxy-handled';
env.CODEMIE_PROXY_ACTIVE = '1';
if (env.CODEMIE_PROVIDER !== 'azure-openai') {
env.CODEMIE_API_KEY = 'proxy-handled';
}
} catch (error) {
const errorMessage = error instanceof Error ? error.message : String(error);
throw new Error(`Proxy setup failed: ${errorMessage}`);
Expand Down
Loading