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 CHANGED
@@ -12,7 +12,7 @@
12
12
 
13
13
  import {
14
14
  existsSync, readFileSync, writeFileSync, mkdirSync, cpSync,
15
- readdirSync, statSync, chmodSync, appendFileSync, rmSync,
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
- if (currentName === 'User' && isInteractive) {
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(tsRunner: string): void {
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
- const codexInstall = join(SCRIPT_DIR, 'codex', 'install.ts');
589
- if (existsSync(codexInstall)) {
590
- const result = spawnSync(tsRunner, [codexInstall], { stdio: 'inherit' });
591
- if (result.status === 0) {
592
- log(' OK Codex hooks installed');
593
- } else {
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
- const geminiInstall = join(SCRIPT_DIR, 'gemini', 'install.ts');
607
- if (existsSync(geminiInstall)) {
608
- const result = spawnSync(tsRunner, [geminiInstall], { stdio: 'inherit' });
609
- if (result.status === 0) {
610
- log(' OK Gemini extension installed');
611
- } else {
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(tsRunner);
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
- main();
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.44';
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
- main();
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();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gramatr",
3
- "version": "0.3.44",
3
+ "version": "0.3.46",
4
4
  "description": "gramatr — your cross-agent AI brain. Intelligence layer for Claude Code, Codex, Gemini CLI.",
5
5
  "license": "MIT",
6
6
  "repository": {