Created
June 27, 2025 19:30
-
-
Save acreeger/ffd333b6e32f9e6e0dd4017c004381b4 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env node | |
const fs = require('fs'); | |
const { execSync } = require('child_process'); | |
const path = require('path'); | |
// Parse command line arguments | |
function parseArgs() { | |
const args = process.argv.slice(2); | |
const options = {}; | |
for (let i = 0; i < args.length; i++) { | |
switch (args[i]) { | |
case '-k': | |
case '--keychain-entry': | |
options.keychainEntry = args[++i]; | |
break; | |
case '-s': | |
case '--secret-name': | |
options.secretName = args[++i]; | |
break; | |
case '-r': | |
case '--repo': | |
options.repo = args[++i]; | |
break; | |
case '-h': | |
case '--help': | |
console.log('Usage: node update_oauth_creds.js -k <keychain-entry> -s <secret-name> [-r <repo>]'); | |
console.log(' -k, --keychain-entry Name of keychain entry'); | |
console.log(' -s, --secret-name GitHub secret name'); | |
console.log(' -r, --repo Repository (optional, uses current if not specified)'); | |
process.exit(0); | |
default: | |
console.error(`Unknown option: ${args[i]}`); | |
process.exit(1); | |
} | |
} | |
return options; | |
} | |
// Check if required tools are available | |
function checkRequiredTools() { | |
try { | |
execSync('which security', { stdio: 'ignore' }); | |
execSync('which gh', { stdio: 'ignore' }); | |
} catch (error) { | |
if (error.status === 1) { | |
console.error('Error: Required tools (security or gh) not found'); | |
process.exit(1); | |
} | |
} | |
} | |
// Parse JSON from comment at top of file | |
function parseJson(jsonData) { | |
try { | |
// Parse the JSON | |
const parsed = JSON.parse(jsonData); | |
const oauth = parsed.claudeAiOauth; | |
// Extract the values | |
const accessToken = oauth.accessToken; | |
const refreshToken = oauth.refreshToken; | |
const expiresAt = oauth.expiresAt; | |
return oauth | |
} catch (error) { | |
console.error('Error parsing JSON:', error.message); | |
} | |
return null; | |
} | |
// Get password from keychain | |
function getKeychainPassword(keychainEntry) { | |
try { | |
console.log('Retrieving password from keychain...'); | |
const result = execSync(`security find-generic-password -s "${keychainEntry}" -w`, { | |
encoding: 'utf8' | |
}); | |
return result.trim(); | |
} catch (error) { | |
console.error('Error: Could not retrieve password from keychain'); | |
process.exit(1); | |
} | |
} | |
// Update GitHub secret | |
function updateGitHubSecret(secretName, secretValue, repo) { | |
try { | |
console.log('Updating GitHub secret...'); | |
const cmd = repo | |
? `gh secret set "${secretName}" --repo "${repo}"` | |
: `gh secret set "${secretName}"`; | |
execSync(cmd, { | |
input: secretValue, | |
stdio: ['pipe', 'inherit', 'inherit'] | |
}); | |
console.log(`Successfully updated GitHub secret: ${secretName}`); | |
} catch (error) { | |
console.error('Error updating GitHub secret:', error.message); | |
process.exit(1); | |
} | |
} | |
// Main function | |
function main() { | |
const options = parseArgs(); | |
const keychainEntry = options.keychainEntry || 'Claude Code-credentials'; | |
checkRequiredTools(); | |
const secretValue = getKeychainPassword(keychainEntry); | |
if (!secretValue) { | |
console.error('Error: No secret value found in keychain'); | |
process.exit(1); | |
} | |
const { accessToken, refreshToken, expiresAt } = parseJson(secretValue); | |
if (!accessToken || !refreshToken || !expiresAt) { | |
console.error('Error: Invalid OAuth credentials'); | |
process.exit(1); | |
} | |
// console.log(`CLAUDE_ACCESS_TOKEN="${accessToken}"`); | |
// console.log(`CLAUDE_REFRESH_TOKEN="${refreshToken}"`); | |
console.log('Updating GitHub secrets...'); | |
console.log("Updating Access Token"); | |
updateGitHubSecret("CLAUDE_ACCESS_TOKEN", accessToken, options.repo); | |
console.log("Updating Refresh Token"); | |
updateGitHubSecret("CLAUDE_REFRESH_TOKEN", refreshToken, options.repo); | |
console.log(`Updating Expires At: ${expiresAt} converted to UTC: ${new Date(expiresAt).toISOString()}`); | |
updateGitHubSecret("CLAUDE_EXPIRES_AT", expiresAt.toString(), options.repo); | |
console.log('All secrets updated successfully!'); | |
} | |
// Run the script | |
if (require.main === module) { | |
main(); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment