gramatr 0.3.44 → 0.3.46
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/install.ts +43 -36
- package/codex/install.ts +6 -2
- package/core/version.ts +1 -1
- package/gemini/install.ts +6 -2
- package/package.json +1 -1
package/bin/install.ts
CHANGED
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
|
|
13
13
|
import {
|
|
14
14
|
existsSync, readFileSync, writeFileSync, mkdirSync, cpSync,
|
|
15
|
-
readdirSync, statSync, chmodSync,
|
|
15
|
+
readdirSync, statSync, chmodSync, rmSync,
|
|
16
16
|
} from 'fs';
|
|
17
17
|
import { join, dirname, basename, resolve } from 'path';
|
|
18
18
|
import { execSync, spawnSync } from 'child_process';
|
|
@@ -28,7 +28,6 @@ const CLAUDE_SETTINGS = join(CLAUDE_DIR, 'settings.json');
|
|
|
28
28
|
const CLAUDE_JSON = join(HOME, '.claude.json');
|
|
29
29
|
const CLIENT_DIR = join(HOME, 'gmtr-client');
|
|
30
30
|
const GMTR_JSON = join(HOME, '.gmtr.json');
|
|
31
|
-
const GMTR_BIN = join(HOME, '.gmtr', 'bin');
|
|
32
31
|
const SCRIPT_DIR = dirname(dirname(resolve(import.meta.filename || __filename)));
|
|
33
32
|
const DEFAULT_URL = 'https://api.gramatr.com/mcp';
|
|
34
33
|
|
|
@@ -36,6 +35,14 @@ const args = process.argv.slice(2);
|
|
|
36
35
|
const YES = args.includes('--yes') || args.includes('-y');
|
|
37
36
|
const isInteractive = process.stdin.isTTY && !YES;
|
|
38
37
|
|
|
38
|
+
function getArgValue(flag: string): string | undefined {
|
|
39
|
+
const idx = args.indexOf(flag);
|
|
40
|
+
return idx !== -1 && idx + 1 < args.length ? args[idx + 1] : undefined;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
const ARG_NAME = getArgValue('--name');
|
|
44
|
+
const ARG_TIMEZONE = getArgValue('--timezone');
|
|
45
|
+
|
|
39
46
|
// ── Helpers ──
|
|
40
47
|
|
|
41
48
|
function log(msg: string): void { process.stdout.write(`${msg}\n`); }
|
|
@@ -157,19 +164,6 @@ async function checkPrereqs(): Promise<{ tsRunner: string }> {
|
|
|
157
164
|
log(`OK TS runner: npx tsx (install bun for faster hooks)`);
|
|
158
165
|
}
|
|
159
166
|
|
|
160
|
-
// Ensure ~/.gmtr/bin exists and is on PATH
|
|
161
|
-
mkdirSync(GMTR_BIN, { recursive: true });
|
|
162
|
-
const pathLine = 'export PATH="$HOME/.gmtr/bin:$PATH"';
|
|
163
|
-
for (const rc of ['.zshrc', '.bashrc']) {
|
|
164
|
-
const rcPath = join(HOME, rc);
|
|
165
|
-
if (existsSync(rcPath)) {
|
|
166
|
-
const content = readFileSync(rcPath, 'utf8');
|
|
167
|
-
if (!content.includes('.gmtr/bin')) {
|
|
168
|
-
appendFileSync(rcPath, `\n# gramatr — local tool binaries\n${pathLine}\n`);
|
|
169
|
-
}
|
|
170
|
-
}
|
|
171
|
-
}
|
|
172
|
-
|
|
173
167
|
// Claude Code
|
|
174
168
|
if (!existsSync(CLAUDE_DIR)) {
|
|
175
169
|
log('X Claude Code not found (~/.claude/ does not exist)');
|
|
@@ -446,23 +440,40 @@ async function configureIdentity(): Promise<void> {
|
|
|
446
440
|
|
|
447
441
|
const settings = readJson(settingsPath);
|
|
448
442
|
const currentName = settings.principal?.name || 'User';
|
|
443
|
+
let changed = false;
|
|
449
444
|
|
|
450
|
-
|
|
445
|
+
// --name flag takes precedence
|
|
446
|
+
if (ARG_NAME) {
|
|
447
|
+
settings.principal = settings.principal || {};
|
|
448
|
+
settings.principal.name = ARG_NAME;
|
|
449
|
+
log(` OK Set principal.name to "${ARG_NAME}"`);
|
|
450
|
+
changed = true;
|
|
451
|
+
} else if (currentName === 'User' && isInteractive) {
|
|
451
452
|
const name = await prompt(' What is your name? (shown in gramatr responses)');
|
|
452
453
|
if (name) {
|
|
453
454
|
settings.principal = settings.principal || {};
|
|
454
455
|
settings.principal.name = name;
|
|
455
456
|
log(` OK Set principal.name to "${name}"`);
|
|
457
|
+
changed = true;
|
|
456
458
|
}
|
|
459
|
+
}
|
|
457
460
|
|
|
461
|
+
// --timezone flag takes precedence
|
|
462
|
+
if (ARG_TIMEZONE) {
|
|
463
|
+
settings.principal = settings.principal || {};
|
|
464
|
+
settings.principal.timezone = ARG_TIMEZONE;
|
|
465
|
+
log(` OK Set timezone to "${ARG_TIMEZONE}"`);
|
|
466
|
+
changed = true;
|
|
467
|
+
} else if (currentName === 'User' && isInteractive) {
|
|
458
468
|
const tz = await prompt(' Your timezone?', 'America/Chicago');
|
|
459
469
|
settings.principal = settings.principal || {};
|
|
460
470
|
settings.principal.timezone = tz;
|
|
461
471
|
log(` OK Set timezone to "${tz}"`);
|
|
462
|
-
|
|
463
|
-
writeJson(settingsPath, settings);
|
|
472
|
+
changed = true;
|
|
464
473
|
}
|
|
465
474
|
|
|
475
|
+
if (changed) writeJson(settingsPath, settings);
|
|
476
|
+
|
|
466
477
|
log('');
|
|
467
478
|
}
|
|
468
479
|
|
|
@@ -577,7 +588,7 @@ function registerMcpServer(url: string, token: string): void {
|
|
|
577
588
|
|
|
578
589
|
// ── Step 4c: Additional CLIs ──
|
|
579
590
|
|
|
580
|
-
function installAdditionalClis(
|
|
591
|
+
async function installAdditionalClis(): Promise<void> {
|
|
581
592
|
log('━━━ Step 4c: Additional CLI platforms ━━━');
|
|
582
593
|
log('');
|
|
583
594
|
|
|
@@ -585,14 +596,12 @@ function installAdditionalClis(tsRunner: string): void {
|
|
|
585
596
|
const codexDir = join(HOME, '.codex');
|
|
586
597
|
if (existsSync(codexDir) || which('codex')) {
|
|
587
598
|
log(' Codex CLI detected — installing gramatr hooks...');
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
log(' X Codex install failed (non-fatal)');
|
|
595
|
-
}
|
|
599
|
+
try {
|
|
600
|
+
const { main: installCodex } = await import('../codex/install.ts');
|
|
601
|
+
installCodex();
|
|
602
|
+
log(' OK Codex hooks installed');
|
|
603
|
+
} catch (err: any) {
|
|
604
|
+
log(` X Codex install failed (non-fatal): ${err.message}`);
|
|
596
605
|
}
|
|
597
606
|
log('');
|
|
598
607
|
} else {
|
|
@@ -603,14 +612,12 @@ function installAdditionalClis(tsRunner: string): void {
|
|
|
603
612
|
const geminiDir = join(HOME, '.gemini');
|
|
604
613
|
if (existsSync(geminiDir) || which('gemini')) {
|
|
605
614
|
log(' Gemini CLI detected — installing gramatr extension...');
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
log(' X Gemini install failed (non-fatal)');
|
|
613
|
-
}
|
|
615
|
+
try {
|
|
616
|
+
const { main: installGemini } = await import('../gemini/install.ts');
|
|
617
|
+
await installGemini();
|
|
618
|
+
log(' OK Gemini extension installed');
|
|
619
|
+
} catch (err: any) {
|
|
620
|
+
log(` X Gemini install failed (non-fatal): ${err.message}`);
|
|
614
621
|
}
|
|
615
622
|
log('');
|
|
616
623
|
} else {
|
|
@@ -721,7 +728,7 @@ async function main(): Promise<void> {
|
|
|
721
728
|
await configureIdentity();
|
|
722
729
|
updateClaudeSettings(tsRunner, url, token);
|
|
723
730
|
registerMcpServer(url, token);
|
|
724
|
-
installAdditionalClis(
|
|
731
|
+
await installAdditionalClis();
|
|
725
732
|
|
|
726
733
|
const allOk = verify(url, token);
|
|
727
734
|
|
package/codex/install.ts
CHANGED
|
@@ -41,7 +41,7 @@ function readJsonFile<T>(path: string, fallback: T): T {
|
|
|
41
41
|
return JSON.parse(readFileSync(path, 'utf8')) as T;
|
|
42
42
|
}
|
|
43
43
|
|
|
44
|
-
function main(): void {
|
|
44
|
+
export function main(): void {
|
|
45
45
|
const home = process.env.HOME || process.env.USERPROFILE;
|
|
46
46
|
if (!home) {
|
|
47
47
|
throw new Error('HOME is not set');
|
|
@@ -109,4 +109,8 @@ function main(): void {
|
|
|
109
109
|
log('Restart Codex or start a new session to load the updated hook configuration.');
|
|
110
110
|
}
|
|
111
111
|
|
|
112
|
-
|
|
112
|
+
// Run directly when executed as a script
|
|
113
|
+
const isDirectRun = typeof require !== 'undefined'
|
|
114
|
+
? require.main === module
|
|
115
|
+
: !import.meta.url.includes('node_modules/gramatr/bin/');
|
|
116
|
+
if (isDirectRun) main();
|
package/core/version.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
/** Auto-generated by version-sync.ts — do not edit */
|
|
2
|
-
export const VERSION = '0.3.
|
|
2
|
+
export const VERSION = '0.3.46';
|
package/gemini/install.ts
CHANGED
|
@@ -163,7 +163,7 @@ async function resolveApiKey(home: string): Promise<string | null> {
|
|
|
163
163
|
return null;
|
|
164
164
|
}
|
|
165
165
|
|
|
166
|
-
async function main(): Promise<void> {
|
|
166
|
+
export async function main(): Promise<void> {
|
|
167
167
|
const home = process.env.HOME || process.env.USERPROFILE;
|
|
168
168
|
if (!home) {
|
|
169
169
|
throw new Error('HOME is not set');
|
|
@@ -269,4 +269,8 @@ async function main(): Promise<void> {
|
|
|
269
269
|
log('');
|
|
270
270
|
}
|
|
271
271
|
|
|
272
|
-
|
|
272
|
+
// Run directly when executed as a script
|
|
273
|
+
const isDirectRun = typeof require !== 'undefined'
|
|
274
|
+
? require.main === module
|
|
275
|
+
: !import.meta.url.includes('node_modules/gramatr/bin/');
|
|
276
|
+
if (isDirectRun) main();
|