mirror of
https://github.com/AutoMaker-Org/automaker.git
synced 2026-02-05 09:33:07 +00:00
refactor: remove CLAUDE_CODE_OAUTH_TOKEN references and update authentication to use ANTHROPIC_API_KEY exclusively
This commit is contained in:
10
README.md
10
README.md
@@ -151,20 +151,16 @@ npm run lint
|
|||||||
Automaker supports multiple authentication methods (in order of priority):
|
Automaker supports multiple authentication methods (in order of priority):
|
||||||
|
|
||||||
| Method | Environment Variable | Description |
|
| Method | Environment Variable | Description |
|
||||||
| -------------------- | ------------------------- | --------------------------------------------------------- |
|
| ---------------- | -------------------- | ------------------------------- |
|
||||||
| OAuth Token (env) | `CLAUDE_CODE_OAUTH_TOKEN` | From `claude setup-token` - uses your Claude subscription |
|
| API Key (env) | `ANTHROPIC_API_KEY` | Anthropic API key |
|
||||||
| OAuth Token (stored) | — | Stored in app credentials file |
|
|
||||||
| API Key (stored) | — | Anthropic API key stored in app |
|
| API Key (stored) | — | Anthropic API key stored in app |
|
||||||
| API Key (env) | `ANTHROPIC_API_KEY` | Pay-per-use API key |
|
|
||||||
|
|
||||||
**Recommended:** Use `CLAUDE_CODE_OAUTH_TOKEN` if you have a Claude subscription.
|
|
||||||
|
|
||||||
### Persistent Setup (Optional)
|
### Persistent Setup (Optional)
|
||||||
|
|
||||||
Add to your `~/.bashrc` or `~/.zshrc`:
|
Add to your `~/.bashrc` or `~/.zshrc`:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
export CLAUDE_CODE_OAUTH_TOKEN="YOUR_TOKEN_HERE"
|
export ANTHROPIC_API_KEY="YOUR_API_KEY_HERE"
|
||||||
```
|
```
|
||||||
|
|
||||||
Then restart your terminal or run `source ~/.bashrc`.
|
Then restart your terminal or run `source ~/.bashrc`.
|
||||||
|
|||||||
@@ -33,25 +33,15 @@ cd automaker
|
|||||||
npm install
|
npm install
|
||||||
```
|
```
|
||||||
|
|
||||||
**Step 3:** Get your Claude subscription token:
|
**Step 3:** Set your Anthropic API key (optional - you can also enter it in the app's setup wizard):
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
claude setup-token
|
export ANTHROPIC_API_KEY="sk-ant-..."
|
||||||
```
|
```
|
||||||
|
|
||||||
This command will authenticate you via your browser and print a token to your terminal.
|
Alternatively, you can enter your API key directly in the Automaker setup wizard when you launch the app.
|
||||||
|
|
||||||
> **⚠️ Warning:** This command will print your token to your terminal. Be careful if you're streaming or sharing your screen, as the token will be visible to anyone watching.
|
**Step 4:** Start the development server:
|
||||||
|
|
||||||
**Step 4:** Export the Claude Code OAuth token in your shell (optional - you can also enter it in the app's setup wizard):
|
|
||||||
|
|
||||||
```bash
|
|
||||||
export CLAUDE_CODE_OAUTH_TOKEN="your-token-here"
|
|
||||||
```
|
|
||||||
|
|
||||||
Alternatively, you can enter your token directly in the Automaker setup wizard when you launch the app.
|
|
||||||
|
|
||||||
**Step 5:** Start the development server:
|
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
npm run dev:electron
|
npm run dev:electron
|
||||||
|
|||||||
@@ -2,9 +2,6 @@ import type { NextConfig } from "next";
|
|||||||
|
|
||||||
const nextConfig: NextConfig = {
|
const nextConfig: NextConfig = {
|
||||||
output: "export",
|
output: "export",
|
||||||
env: {
|
|
||||||
CLAUDE_CODE_OAUTH_TOKEN: process.env.CLAUDE_CODE_OAUTH_TOKEN || "",
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export default nextConfig;
|
export default nextConfig;
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ export async function POST(request: NextRequest) {
|
|||||||
const { apiKey } = await request.json();
|
const { apiKey } = await request.json();
|
||||||
|
|
||||||
// Use provided API key or fall back to environment variable
|
// Use provided API key or fall back to environment variable
|
||||||
const effectiveApiKey = apiKey || process.env.ANTHROPIC_API_KEY || process.env.CLAUDE_CODE_OAUTH_TOKEN;
|
const effectiveApiKey = apiKey || process.env.ANTHROPIC_API_KEY;
|
||||||
|
|
||||||
if (!effectiveApiKey) {
|
if (!effectiveApiKey) {
|
||||||
return NextResponse.json(
|
return NextResponse.json(
|
||||||
|
|||||||
@@ -55,9 +55,7 @@ export function AuthenticationStatusDisplay({
|
|||||||
<div className="flex items-center gap-2 text-muted-foreground">
|
<div className="flex items-center gap-2 text-muted-foreground">
|
||||||
<Info className="w-3 h-3 shrink-0" />
|
<Info className="w-3 h-3 shrink-0" />
|
||||||
<span>
|
<span>
|
||||||
{claudeAuthStatus.method === "oauth_token_env"
|
{claudeAuthStatus.method === "oauth_token"
|
||||||
? "Using CLAUDE_CODE_OAUTH_TOKEN"
|
|
||||||
: claudeAuthStatus.method === "oauth_token"
|
|
||||||
? "Using stored OAuth token (subscription)"
|
? "Using stored OAuth token (subscription)"
|
||||||
: claudeAuthStatus.method === "api_key_env"
|
: claudeAuthStatus.method === "api_key_env"
|
||||||
? "Using ANTHROPIC_API_KEY"
|
? "Using ANTHROPIC_API_KEY"
|
||||||
|
|||||||
@@ -50,30 +50,21 @@ const DATA_DIR = process.env.DATA_DIR || "./data";
|
|||||||
const ENABLE_REQUEST_LOGGING = process.env.ENABLE_REQUEST_LOGGING !== "false"; // Default to true
|
const ENABLE_REQUEST_LOGGING = process.env.ENABLE_REQUEST_LOGGING !== "false"; // Default to true
|
||||||
|
|
||||||
// Check for required environment variables
|
// Check for required environment variables
|
||||||
// Claude Agent SDK supports EITHER OAuth token (subscription) OR API key (pay-per-use)
|
|
||||||
const hasAnthropicKey = !!process.env.ANTHROPIC_API_KEY;
|
const hasAnthropicKey = !!process.env.ANTHROPIC_API_KEY;
|
||||||
const hasOAuthToken = !!process.env.CLAUDE_CODE_OAUTH_TOKEN;
|
|
||||||
|
|
||||||
if (!hasAnthropicKey && !hasOAuthToken) {
|
if (!hasAnthropicKey) {
|
||||||
console.warn(`
|
console.warn(`
|
||||||
╔═══════════════════════════════════════════════════════════════════════╗
|
╔═══════════════════════════════════════════════════════════════════════╗
|
||||||
║ ⚠️ WARNING: No Claude authentication configured ║
|
║ ⚠️ WARNING: No Claude authentication configured ║
|
||||||
║ ║
|
║ ║
|
||||||
║ The Claude Agent SDK requires authentication to function. ║
|
║ The Claude Agent SDK requires authentication to function. ║
|
||||||
║ ║
|
║ ║
|
||||||
║ Option 1 - Subscription (OAuth Token): ║
|
║ Set your Anthropic API key: ║
|
||||||
║ export CLAUDE_CODE_OAUTH_TOKEN="your-oauth-token" ║
|
|
||||||
║ ║
|
|
||||||
║ Option 2 - Pay-per-use (API Key): ║
|
|
||||||
║ export ANTHROPIC_API_KEY="sk-ant-..." ║
|
║ export ANTHROPIC_API_KEY="sk-ant-..." ║
|
||||||
║ ║
|
║ ║
|
||||||
║ Or use the setup wizard in Settings to configure authentication. ║
|
║ Or use the setup wizard in Settings to configure authentication. ║
|
||||||
╚═══════════════════════════════════════════════════════════════════════╝
|
╚═══════════════════════════════════════════════════════════════════════╝
|
||||||
`);
|
`);
|
||||||
} else if (hasOAuthToken) {
|
|
||||||
console.log(
|
|
||||||
"[Server] ✓ CLAUDE_CODE_OAUTH_TOKEN detected (subscription auth)"
|
|
||||||
);
|
|
||||||
} else {
|
} else {
|
||||||
console.log("[Server] ✓ ANTHROPIC_API_KEY detected (API key auth)");
|
console.log("[Server] ✓ ANTHROPIC_API_KEY detected (API key auth)");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -112,9 +112,7 @@ export class ClaudeProvider extends BaseProvider {
|
|||||||
*/
|
*/
|
||||||
async detectInstallation(): Promise<InstallationStatus> {
|
async detectInstallation(): Promise<InstallationStatus> {
|
||||||
// Claude SDK is always available since it's a dependency
|
// Claude SDK is always available since it's a dependency
|
||||||
const hasAnthropicKey = !!process.env.ANTHROPIC_API_KEY;
|
const hasApiKey = !!process.env.ANTHROPIC_API_KEY;
|
||||||
const hasOAuthToken = !!process.env.CLAUDE_CODE_OAUTH_TOKEN;
|
|
||||||
const hasApiKey = hasAnthropicKey || hasOAuthToken;
|
|
||||||
|
|
||||||
const status: InstallationStatus = {
|
const status: InstallationStatus = {
|
||||||
installed: true,
|
installed: true,
|
||||||
|
|||||||
@@ -35,19 +35,9 @@ export function setRunningState(
|
|||||||
* Helper to log authentication status
|
* Helper to log authentication status
|
||||||
*/
|
*/
|
||||||
export function logAuthStatus(context: string): void {
|
export function logAuthStatus(context: string): void {
|
||||||
const hasOAuthToken = !!process.env.CLAUDE_CODE_OAUTH_TOKEN;
|
|
||||||
const hasApiKey = !!process.env.ANTHROPIC_API_KEY;
|
const hasApiKey = !!process.env.ANTHROPIC_API_KEY;
|
||||||
|
|
||||||
logger.info(`${context} - Auth Status:`);
|
logger.info(`${context} - Auth Status:`);
|
||||||
logger.info(
|
|
||||||
` CLAUDE_CODE_OAUTH_TOKEN: ${
|
|
||||||
hasOAuthToken
|
|
||||||
? "SET (" +
|
|
||||||
process.env.CLAUDE_CODE_OAUTH_TOKEN?.substring(0, 20) +
|
|
||||||
"...)"
|
|
||||||
: "NOT SET"
|
|
||||||
}`
|
|
||||||
);
|
|
||||||
logger.info(
|
logger.info(
|
||||||
` ANTHROPIC_API_KEY: ${
|
` ANTHROPIC_API_KEY: ${
|
||||||
hasApiKey
|
hasApiKey
|
||||||
@@ -56,7 +46,7 @@ export function logAuthStatus(context: string): void {
|
|||||||
}`
|
}`
|
||||||
);
|
);
|
||||||
|
|
||||||
if (!hasOAuthToken && !hasApiKey) {
|
if (!hasApiKey) {
|
||||||
logger.warn("⚠️ WARNING: No authentication configured! SDK will fail.");
|
logger.warn("⚠️ WARNING: No authentication configured! SDK will fail.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,9 +15,7 @@ export function createProvidersHandler() {
|
|||||||
const providers: Record<string, any> = {
|
const providers: Record<string, any> = {
|
||||||
anthropic: {
|
anthropic: {
|
||||||
available: statuses.claude?.installed || false,
|
available: statuses.claude?.installed || false,
|
||||||
hasApiKey:
|
hasApiKey: !!process.env.ANTHROPIC_API_KEY,
|
||||||
!!process.env.ANTHROPIC_API_KEY ||
|
|
||||||
!!process.env.CLAUDE_CODE_OAUTH_TOKEN,
|
|
||||||
},
|
},
|
||||||
google: {
|
google: {
|
||||||
available: !!process.env.GOOGLE_API_KEY,
|
available: !!process.env.GOOGLE_API_KEY,
|
||||||
|
|||||||
@@ -74,7 +74,6 @@ export async function getClaudeStatus() {
|
|||||||
hasStoredOAuthToken: !!getApiKey("anthropic_oauth_token"),
|
hasStoredOAuthToken: !!getApiKey("anthropic_oauth_token"),
|
||||||
hasStoredApiKey: !!getApiKey("anthropic"),
|
hasStoredApiKey: !!getApiKey("anthropic"),
|
||||||
hasEnvApiKey: !!process.env.ANTHROPIC_API_KEY,
|
hasEnvApiKey: !!process.env.ANTHROPIC_API_KEY,
|
||||||
hasEnvOAuthToken: !!process.env.CLAUDE_CODE_OAUTH_TOKEN,
|
|
||||||
// Additional fields for detailed status
|
// Additional fields for detailed status
|
||||||
oauthTokenValid: false,
|
oauthTokenValid: false,
|
||||||
apiKeyValid: false,
|
apiKeyValid: false,
|
||||||
@@ -148,11 +147,7 @@ export async function getClaudeStatus() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Environment variables override stored credentials (higher priority)
|
// Environment variables override stored credentials (higher priority)
|
||||||
if (auth.hasEnvOAuthToken) {
|
if (auth.hasEnvApiKey) {
|
||||||
auth.authenticated = true;
|
|
||||||
auth.oauthTokenValid = true;
|
|
||||||
auth.method = "oauth_token_env";
|
|
||||||
} else if (auth.hasEnvApiKey) {
|
|
||||||
auth.authenticated = true;
|
auth.authenticated = true;
|
||||||
auth.apiKeyValid = true;
|
auth.apiKeyValid = true;
|
||||||
auth.method = "api_key_env"; // API key from ANTHROPIC_API_KEY env var
|
auth.method = "api_key_env"; // API key from ANTHROPIC_API_KEY env var
|
||||||
|
|||||||
@@ -31,16 +31,8 @@ export function createStoreApiKeyHandler() {
|
|||||||
setApiKey(provider, apiKey);
|
setApiKey(provider, apiKey);
|
||||||
|
|
||||||
// Also set as environment variable and persist to .env
|
// Also set as environment variable and persist to .env
|
||||||
// IMPORTANT: OAuth tokens and API keys must be stored separately
|
if (provider === "anthropic" || provider === "anthropic_oauth_token") {
|
||||||
// - OAuth tokens (subscription auth) -> CLAUDE_CODE_OAUTH_TOKEN
|
// Both API key and OAuth token use ANTHROPIC_API_KEY
|
||||||
// - API keys (pay-per-use) -> ANTHROPIC_API_KEY
|
|
||||||
if (provider === "anthropic_oauth_token") {
|
|
||||||
// OAuth token from claude setup-token (subscription-based auth)
|
|
||||||
process.env.CLAUDE_CODE_OAUTH_TOKEN = apiKey;
|
|
||||||
await persistApiKeyToEnv("CLAUDE_CODE_OAUTH_TOKEN", apiKey);
|
|
||||||
logger.info("[Setup] Stored OAuth token as CLAUDE_CODE_OAUTH_TOKEN");
|
|
||||||
} else if (provider === "anthropic") {
|
|
||||||
// Direct API key (pay-per-use)
|
|
||||||
process.env.ANTHROPIC_API_KEY = apiKey;
|
process.env.ANTHROPIC_API_KEY = apiKey;
|
||||||
await persistApiKeyToEnv("ANTHROPIC_API_KEY", apiKey);
|
await persistApiKeyToEnv("ANTHROPIC_API_KEY", apiKey);
|
||||||
logger.info("[Setup] Stored API key as ANTHROPIC_API_KEY");
|
logger.info("[Setup] Stored API key as ANTHROPIC_API_KEY");
|
||||||
|
|||||||
@@ -12,7 +12,6 @@ describe("claude-provider.ts", () => {
|
|||||||
vi.clearAllMocks();
|
vi.clearAllMocks();
|
||||||
provider = new ClaudeProvider();
|
provider = new ClaudeProvider();
|
||||||
delete process.env.ANTHROPIC_API_KEY;
|
delete process.env.ANTHROPIC_API_KEY;
|
||||||
delete process.env.CLAUDE_CODE_OAUTH_TOKEN;
|
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("getName", () => {
|
describe("getName", () => {
|
||||||
@@ -254,15 +253,6 @@ describe("claude-provider.ts", () => {
|
|||||||
expect(result.authenticated).toBe(true);
|
expect(result.authenticated).toBe(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should detect CLAUDE_CODE_OAUTH_TOKEN", async () => {
|
|
||||||
process.env.CLAUDE_CODE_OAUTH_TOKEN = "oauth-token";
|
|
||||||
|
|
||||||
const result = await provider.detectInstallation();
|
|
||||||
|
|
||||||
expect(result.hasApiKey).toBe(true);
|
|
||||||
expect(result.authenticated).toBe(true);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("should return hasApiKey false when no keys present", async () => {
|
it("should return hasApiKey false when no keys present", async () => {
|
||||||
const result = await provider.detectInstallation();
|
const result = await provider.detectInstallation();
|
||||||
|
|
||||||
|
|||||||
@@ -179,9 +179,8 @@ Routes models that:
|
|||||||
|
|
||||||
#### Authentication
|
#### Authentication
|
||||||
|
|
||||||
Requires one of:
|
Requires:
|
||||||
- `ANTHROPIC_API_KEY` environment variable
|
- `ANTHROPIC_API_KEY` environment variable
|
||||||
- `CLAUDE_CODE_OAUTH_TOKEN` environment variable
|
|
||||||
|
|
||||||
#### Example Usage
|
#### Example Usage
|
||||||
|
|
||||||
@@ -704,9 +703,8 @@ describe("Provider Integration", () => {
|
|||||||
### Claude Provider
|
### Claude Provider
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# Required (one of):
|
# Required:
|
||||||
ANTHROPIC_API_KEY=sk-ant-...
|
ANTHROPIC_API_KEY=sk-ant-...
|
||||||
CLAUDE_CODE_OAUTH_TOKEN=...
|
|
||||||
```
|
```
|
||||||
|
|
||||||
### Codex Provider
|
### Codex Provider
|
||||||
|
|||||||
Reference in New Issue
Block a user