Skip to content

Commit 2567ecc

Browse files
fix(cli): persist auth token to ~/.aegis/auth-token file (#3369) (#3386)
- ag init now writes auth token to ~/.aegis/auth-token (mode 0600) - ag run resolveAuthToken() checks ~/.aegis/auth-token as fallback - Non-fatal: token still available in config.yaml as clientAuthToken - Fixes user lockout when terminal output scrolls past token Co-authored-by: aegis-gh-agent[bot] <272581873+aegis-gh-agent[bot]@users.noreply.github.com>
1 parent 4d22cc2 commit 2567ecc

2 files changed

Lines changed: 35 additions & 3 deletions

File tree

src/commands/init.ts

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,9 @@
66
* Also handles `--list-templates` and `--from-template`.
77
*/
88

9-
import { existsSync, readFileSync } from 'node:fs';
9+
import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';
1010
import { copyFile, mkdir, readFile, readdir, writeFile } from 'node:fs/promises';
11+
import { homedir } from 'node:os';
1112
import { dirname, join, relative, resolve, sep } from 'node:path';
1213
import { createInterface } from 'node:readline/promises';
1314
import { fileURLToPath } from 'node:url';
@@ -46,6 +47,23 @@ interface InitSummary {
4647
identityScaffolded: boolean;
4748
}
4849

50+
/**
51+
* Persist the auth token to ~/.aegis/auth-token for easy access.
52+
* File is created with 0600 permissions (owner read/write only).
53+
* Non-fatal on failure — token remains in config.yaml as clientAuthToken.
54+
*/
55+
function persistAuthTokenFile(token: string): void {
56+
const tokenDir = join(homedir(), '.aegis');
57+
const tokenPath = join(tokenDir, 'auth-token');
58+
try {
59+
if (!existsSync(tokenDir)) mkdirSync(tokenDir, { recursive: true });
60+
writeFileSync(tokenPath, token, { encoding: 'utf-8', mode: 0o600 });
61+
} catch {
62+
// Non-fatal — token is still in config.yaml as clientAuthToken
63+
}
64+
}
65+
66+
4967
type TemplateType = 'agent' | 'skill' | 'slash-command';
5068

5169
interface TemplateManifestEntry {
@@ -785,6 +803,11 @@ export async function handleInit(args: string[], io: CliIO): Promise<number> {
785803
}
786804
}
787805

806+
// #3369: Persist token to ~/.aegis/auth-token for easy scripting access
807+
if (authToken) {
808+
persistAuthTokenFile(authToken);
809+
}
810+
788811
printInitSummary(io, {
789812
authToken,
790813
baseUrl,

src/commands/run.ts

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
*/
1212

1313
import { spawn, type ChildProcess } from 'node:child_process';
14-
import { existsSync } from 'node:fs';
14+
import { existsSync, readFileSync } from 'node:fs';
1515
import { homedir } from 'node:os';
1616
import { join, resolve } from 'node:path';
1717

@@ -31,7 +31,16 @@ function writeLine(stream: NodeJS.WritableStream, text: string = ''): void {
3131
}
3232

3333
function resolveAuthToken(): string | undefined {
34-
return process.env.AEGIS_AUTH_TOKEN || process.env.AEGIS_TOKEN || undefined;
34+
const envToken = process.env.AEGIS_AUTH_TOKEN || process.env.AEGIS_TOKEN;
35+
if (envToken) return envToken;
36+
37+
// #3369: Check ~/.aegis/auth-token file as fallback
38+
try {
39+
const tokenPath = join(homedir(), '.aegis', 'auth-token');
40+
return readFileSync(tokenPath, 'utf-8').trim() || undefined;
41+
} catch {
42+
return undefined;
43+
}
3544
}
3645

3746
/**

0 commit comments

Comments
 (0)