@gramatr/client 0.5.2 → 0.6.1

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.
@@ -4,13 +4,13 @@
4
4
  *
5
5
  * Three modes:
6
6
  * 1. Interactive prompt: gramatr add-api-key
7
- * 2. Piped stdin: echo "gmtr_sk_..." | gramatr add-api-key
7
+ * 2. Piped stdin: echo "gramatr_sk_..." | gramatr add-api-key
8
8
  * 3. Env-sourced: gramatr add-api-key --from-env GRAMATR_API_KEY
9
9
  *
10
10
  * The key is validated against the gramatr server before being written
11
- * to ~/.gmtr.json. Use --force to skip server validation when offline.
11
+ * to ~/.gramatr.json. Use --force to skip server validation when offline.
12
12
  *
13
- * This command is the ONLY way to put an API key into ~/.gmtr.json.
13
+ * This command is the ONLY way to put an API key into ~/.gramatr.json.
14
14
  * Installers never prompt for API keys — see packages/client/core/auth.ts.
15
15
  */
16
16
 
@@ -20,13 +20,13 @@ import { join } from "path";
20
20
  import { createInterface } from "readline";
21
21
 
22
22
  function gmtrJsonPath(): string {
23
- return join(process.env.HOME || process.env.USERPROFILE || homedir(), ".gmtr.json");
23
+ return join(process.env.HOME || process.env.USERPROFILE || homedir(), ".gramatr.json");
24
24
  }
25
- const SERVER_BASE = (process.env.GMTR_URL || "https://api.gramatr.com").replace(/\/mcp\/?$/, "");
25
+ const SERVER_BASE = (process.env.GRAMATR_URL || "https://api.gramatr.com").replace(/\/mcp\/?$/, "");
26
26
 
27
- // Accept gmtr_sk_, gmtr_pk_, aios_sk_, aios_pk_ (legacy), and Firebase-style
27
+ // Accept gramatr_sk_, gramatr_pk_, aios_sk_, aios_pk_ (legacy), and Firebase-style
28
28
  // long opaque tokens (length >= 32, base64url-ish characters).
29
- const KEY_FORMAT = /^(gmtr|aios)_(sk|pk)_[A-Za-z0-9_-]+$/;
29
+ const KEY_FORMAT = /^(gramatr|gmtr|aios)_(sk|pk)_[A-Za-z0-9_-]+$/;
30
30
  const LEGACY_OPAQUE = /^[A-Za-z0-9_.-]{32,}$/;
31
31
 
32
32
  function log(msg: string = ""): void {
@@ -59,11 +59,11 @@ function parseArgs(argv: string[]): {
59
59
  }
60
60
 
61
61
  function showHelp(): void {
62
- log(`gramatr add-api-key — Add a gramatr API key to ~/.gmtr.json
62
+ log(`gramatr add-api-key — Add a gramatr API key to ~/.gramatr.json
63
63
 
64
64
  Usage:
65
65
  gramatr add-api-key Interactive prompt for the key
66
- echo "gmtr_sk_..." | gramatr add-api-key Read key from piped stdin
66
+ echo "gramatr_sk_..." | gramatr add-api-key Read key from piped stdin
67
67
  gramatr add-api-key --from-env VAR Read key from named env variable
68
68
  gramatr add-api-key --force Skip server validation (offline use)
69
69
 
@@ -94,7 +94,7 @@ async function readPipedStdin(): Promise<string | null> {
94
94
  async function readInteractive(): Promise<string> {
95
95
  log("");
96
96
  log("Paste your gramatr API key below.");
97
- log("(Get one at https://gramatr.com/settings — keys start with gmtr_sk_)");
97
+ log("(Get one at https://gramatr.com/settings — keys start with gramatr_sk_)");
98
98
  log("");
99
99
  process.stdout.write(" Key: ");
100
100
  const rl = createInterface({ input: process.stdin, output: process.stdout });
@@ -168,7 +168,7 @@ function writeKey(key: string): void {
168
168
  }
169
169
  existing.token = key;
170
170
  existing.token_type =
171
- key.startsWith("gmtr_sk_") || key.startsWith("aios_sk_") ? "api_key" : "oauth";
171
+ key.startsWith("gramatr_sk_") || key.startsWith("aios_sk_") ? "api_key" : "oauth";
172
172
  existing.authenticated_at = new Date().toISOString();
173
173
  writeFileSync(gmtrJsonPath(), `${JSON.stringify(existing, null, 2)}\n`, "utf8");
174
174
  try {
@@ -214,7 +214,7 @@ export async function main(argv: string[] = process.argv.slice(2)): Promise<numb
214
214
 
215
215
  // Format validation
216
216
  if (!validateFormat(key)) {
217
- err("ERROR: key format is invalid. Expected gmtr_sk_... or gmtr_pk_...");
217
+ err("ERROR: key format is invalid. Expected gramatr_sk_... or gramatr_pk_...");
218
218
  return 1;
219
219
  }
220
220
 
@@ -14,8 +14,8 @@ function main(): void {
14
14
  }
15
15
 
16
16
  const apply = process.argv.includes('--apply');
17
- const includeOptionalUx = process.env.GMTR_ENABLE_OPTIONAL_CLAUDE_UX === '1';
18
- const clientDir = process.env.GMTR_DIR || join(home, 'gmtr-client');
17
+ const includeOptionalUx = process.env.GRAMATR_ENABLE_OPTIONAL_CLAUDE_UX === '1';
18
+ const clientDir = process.env.GRAMATR_DIR || join(home, '.gramatr');
19
19
  runLegacyMigration({
20
20
  homeDir: home,
21
21
  clientDir,
@@ -2,15 +2,15 @@
2
2
  /**
3
3
  * gramatr clear-creds — Nuke ALL stored gramatr credentials.
4
4
  *
5
- * Stronger than `gramatr logout` (which only removes ~/.gmtr.json).
5
+ * Stronger than `gramatr logout` (which only removes ~/.gramatr.json).
6
6
  * This sweeps every credential location in the resolveAuthToken chain
7
7
  * (core/auth.ts), so the next install/login is forced through OAuth.
8
8
  *
9
9
  * Locations cleared:
10
- * 1. ~/.gmtr.json — deleted entirely
11
- * 2. ~/gmtr-client/settings.json `auth.api_key` — stripped, file preserved
10
+ * 1. ~/.gramatr.json — deleted entirely
11
+ * 2. ~/.gramatr/settings.json `auth.api_key` — stripped, file preserved
12
12
  *
13
- * Env vars (GRAMATR_API_KEY, GMTR_TOKEN) cannot be cleared from a child
13
+ * Env vars (GRAMATR_API_KEY, GRAMATR_TOKEN) cannot be cleared from a child
14
14
  * process — they live in the parent shell. We detect them and warn.
15
15
  *
16
16
  * Not-logged-in is not an error: exits 0 with a clean message.
@@ -24,11 +24,11 @@ function getHome(): string {
24
24
  }
25
25
 
26
26
  function gmtrJsonPath(): string {
27
- return join(getHome(), ".gmtr.json");
27
+ return join(getHome(), ".gramatr.json");
28
28
  }
29
29
 
30
30
  function legacySettingsPath(): string {
31
- const gmtrDir = process.env.GMTR_DIR || join(getHome(), "gmtr-client");
31
+ const gmtrDir = process.env.GRAMATR_DIR || join(getHome(), ".gramatr");
32
32
  return join(gmtrDir, "settings.json");
33
33
  }
34
34
 
@@ -40,11 +40,11 @@ function showHelp(): void {
40
40
  log(`gramatr clear-creds — Remove every stored gramatr credential
41
41
 
42
42
  Usage:
43
- gramatr clear-creds Sweep ~/.gmtr.json + auth.api_key from gmtr-client/settings.json
43
+ gramatr clear-creds Sweep ~/.gramatr.json + auth.api_key from gmtr-client/settings.json
44
44
 
45
45
  After running, the next install or login will be forced through OAuth.
46
46
 
47
- Env vars (GRAMATR_API_KEY, GMTR_TOKEN) cannot be unset from this process.
47
+ Env vars (GRAMATR_API_KEY, GRAMATR_TOKEN) cannot be unset from this process.
48
48
  If they are set, this command warns and tells you the shell command to run.`);
49
49
  }
50
50
 
@@ -61,14 +61,14 @@ export function clearAll(): ClearResult {
61
61
  envVarsSet: [],
62
62
  };
63
63
 
64
- // 1. ~/.gmtr.json — delete entirely
64
+ // 1. ~/.gramatr.json — delete entirely
65
65
  const gj = gmtrJsonPath();
66
66
  if (existsSync(gj)) {
67
67
  unlinkSync(gj);
68
68
  result.removedGmtrJson = true;
69
69
  }
70
70
 
71
- // 2. ~/gmtr-client/settings.json — strip auth.api_key, preserve rest
71
+ // 2. ~/.gramatr/settings.json — strip auth.api_key, preserve rest
72
72
  const ls = legacySettingsPath();
73
73
  if (existsSync(ls)) {
74
74
  try {
@@ -86,7 +86,7 @@ export function clearAll(): ClearResult {
86
86
  }
87
87
 
88
88
  // 3. Env vars — detect only, cannot mutate parent shell
89
- for (const v of ["GRAMATR_API_KEY", "GMTR_TOKEN"]) {
89
+ for (const v of ["GRAMATR_API_KEY", "GRAMATR_TOKEN"]) {
90
90
  if (process.env[v]) result.envVarsSet.push(v);
91
91
  }
92
92
 
package/bin/gmtr-login.ts CHANGED
@@ -3,7 +3,7 @@
3
3
  * gmtr-login — Authenticate with the gramatr server
4
4
  *
5
5
  * Opens the grāmatr dashboard login flow, captures a Firebase ID token
6
- * on localhost, and stores it in ~/.gmtr.json.
6
+ * on localhost, and stores it in ~/.gramatr.json.
7
7
  *
8
8
  * Usage:
9
9
  * bun gmtr-login.ts # Interactive browser login via Firebase dashboard
@@ -11,7 +11,7 @@
11
11
  * bun gmtr-login.ts --status # Check current auth status
12
12
  * bun gmtr-login.ts --logout # Remove stored credentials
13
13
  *
14
- * Token is stored in ~/.gmtr.json under the "token" key.
14
+ * Token is stored in ~/.gramatr.json under the "token" key.
15
15
  * The GMTRPromptEnricher hook reads this on every prompt.
16
16
  */
17
17
 
@@ -23,8 +23,8 @@ import { createServer, type IncomingMessage, type ServerResponse } from 'http';
23
23
  // ── Config ──
24
24
 
25
25
  const HOME = process.env.HOME || process.env.USERPROFILE || '';
26
- const CONFIG_PATH = join(HOME, '.gmtr.json');
27
- const DEFAULT_SERVER = process.env.GMTR_URL || 'https://api.gramatr.com/mcp';
26
+ const CONFIG_PATH = join(HOME, '.gramatr.json');
27
+ const DEFAULT_SERVER = process.env.GRAMATR_URL || 'https://api.gramatr.com/mcp';
28
28
  // Strip /mcp suffix to get base URL
29
29
  const SERVER_BASE = DEFAULT_SERVER.replace(/\/mcp\/?$/, '');
30
30
  const DASHBOARD_BASE = process.env.GMTR_DASHBOARD_URL || (() => {
@@ -317,7 +317,7 @@ async function logout(): Promise<void> {
317
317
  delete config.token_expires;
318
318
  delete config.authenticated_at;
319
319
  writeConfig(config);
320
- console.log('\n ✓ Logged out. Token removed from ~/.gmtr.json\n');
320
+ console.log('\n ✓ Logged out. Token removed from ~/.gramatr.json\n');
321
321
  }
322
322
 
323
323
  async function loginWithToken(token: string): Promise<void> {
@@ -327,10 +327,10 @@ async function loginWithToken(token: string): Promise<void> {
327
327
  if (result.valid) {
328
328
  const config = readConfig();
329
329
  config.token = token;
330
- config.token_type = token.startsWith('aios_sk_') || token.startsWith('gmtr_sk_') ? 'api_key' : 'oauth';
330
+ config.token_type = token.startsWith('aios_sk_') || token.startsWith('gramatr_sk_') ? 'api_key' : 'oauth';
331
331
  config.authenticated_at = new Date().toISOString();
332
332
  writeConfig(config);
333
- console.log(' ✓ Token valid. Saved to ~/.gmtr.json');
333
+ console.log(' ✓ Token valid. Saved to ~/.gramatr.json');
334
334
  console.log(' gramatr intelligence is now active.\n');
335
335
  } else {
336
336
  console.log(` ✗ Token rejected: ${result.error}`);
@@ -396,7 +396,7 @@ async function loginBrowser(): Promise<void> {
396
396
 
397
397
  console.log('');
398
398
  console.log(' ✓ Authenticated successfully');
399
- console.log(' Token saved to ~/.gmtr.json');
399
+ console.log(' Token saved to ~/.gramatr.json');
400
400
  console.log(' gramatr intelligence is now active.\n');
401
401
  return;
402
402
  } catch (e: any) {
@@ -503,7 +503,7 @@ async function loginBrowser(): Promise<void> {
503
503
 
504
504
  console.log('');
505
505
  console.log(' ✓ Authenticated successfully');
506
- console.log(' Token saved to ~/.gmtr.json');
506
+ console.log(' Token saved to ~/.gramatr.json');
507
507
  console.log(' gramatr intelligence is now active.\n');
508
508
  } catch (e: any) {
509
509
  console.log(`\n ✗ Authentication failed: ${e.message}\n`);
@@ -539,7 +539,7 @@ export async function main(): Promise<void> {
539
539
  if (!token) {
540
540
  // Interactive paste mode — like Claude's login
541
541
  console.log('\n Paste your gramatr token below.');
542
- console.log(' (API keys start with aios_sk_ or gmtr_sk_)\n');
542
+ console.log(' (API keys start with aios_sk_ or gramatr_sk_)\n');
543
543
  process.stdout.write(' Token: ');
544
544
 
545
545
  const { createInterface } = await import('readline');
@@ -570,7 +570,7 @@ export async function main(): Promise<void> {
570
570
  gmtr-login --logout Remove stored credentials
571
571
  gmtr-login --help Show this help
572
572
 
573
- Token storage: ~/.gmtr.json
573
+ Token storage: ~/.gramatr.json
574
574
  Server: ${SERVER_BASE}
575
575
  Dashboard: ${DASHBOARD_BASE}
576
576
  `);
package/bin/gramatr.ts CHANGED
@@ -205,11 +205,11 @@ function installTarget(targetId: IntegrationTargetId): void {
205
205
 
206
206
  function migrate(apply: boolean, deep: boolean = false): void {
207
207
  const homeDir = homedir();
208
- const clientDir = process.env.GMTR_DIR || join(homeDir, 'gmtr-client');
208
+ const clientDir = process.env.GRAMATR_DIR || join(homeDir, '.gramatr');
209
209
  runLegacyMigration({
210
210
  homeDir,
211
211
  clientDir,
212
- includeOptionalUx: process.env.GMTR_ENABLE_OPTIONAL_CLAUDE_UX === '1',
212
+ includeOptionalUx: process.env.GRAMATR_ENABLE_OPTIONAL_CLAUDE_UX === '1',
213
213
  apply,
214
214
  log,
215
215
  });
@@ -220,7 +220,7 @@ function migrate(apply: boolean, deep: boolean = false): void {
220
220
  }
221
221
 
222
222
  function doctor(): void {
223
- const gmtrDir = process.env.GMTR_DIR || join(homedir(), 'gmtr-client');
223
+ const gmtrDir = process.env.GRAMATR_DIR || join(homedir(), '.gramatr');
224
224
  const stale = findStaleArtifacts(homedir(), gmtrDir, existsSync);
225
225
  for (const line of formatDoctorLines(detectTargets(), gmtrDir, existsSync(gmtrDir), stale)) log(line);
226
226
  renderRemoteGuidance();
@@ -228,14 +228,14 @@ function doctor(): void {
228
228
 
229
229
  function upgrade(): void {
230
230
  const homeDir = homedir();
231
- const clientDir = process.env.GMTR_DIR || join(homeDir, 'gmtr-client');
231
+ const clientDir = process.env.GRAMATR_DIR || join(homeDir, '.gramatr');
232
232
  const stale = findStaleArtifacts(homeDir, clientDir, existsSync);
233
233
  if (stale.length > 0) {
234
234
  log('Cleaning stale legacy artifacts before upgrade...');
235
235
  runLegacyMigration({
236
236
  homeDir,
237
237
  clientDir,
238
- includeOptionalUx: process.env.GMTR_ENABLE_OPTIONAL_CLAUDE_UX === '1',
238
+ includeOptionalUx: process.env.GRAMATR_ENABLE_OPTIONAL_CLAUDE_UX === '1',
239
239
  apply: true,
240
240
  log,
241
241
  });
@@ -344,7 +344,7 @@ function main(): void {
344
344
  log(' install [target] Install gramatr (claude-code, codex, gemini-cli, all)');
345
345
  log(' login Authenticate with the gramatr server (OAuth)');
346
346
  log(' add-api-key Add an API key explicitly (interactive / piped / --from-env)');
347
- log(' logout Clear session token (~/.gmtr.json)');
347
+ log(' logout Clear session token (~/.gramatr.json)');
348
348
  log(' clear-creds Nuke ALL stored credentials, force OAuth on next login');
349
349
  log(' detect Show detected CLI platforms');
350
350
  log(' doctor Check installation health');
package/bin/install.ts CHANGED
@@ -6,7 +6,7 @@
6
6
  * Usage:
7
7
  * npx tsx install.ts # Universal (Node + tsx)
8
8
  * bun install.ts # If bun is available
9
- * GMTR_TOKEN=xxx npx tsx install.ts # Headless with token
9
+ * GRAMATR_TOKEN=xxx npx tsx install.ts # Headless with token
10
10
  * npx tsx install.ts --yes # Non-interactive (auto-accept defaults)
11
11
  */
12
12
 
@@ -27,8 +27,8 @@ const HOME = process.env.HOME || process.env.USERPROFILE || '';
27
27
  const CLAUDE_DIR = join(HOME, '.claude');
28
28
  const CLAUDE_SETTINGS = join(CLAUDE_DIR, 'settings.json');
29
29
  const CLAUDE_JSON = join(HOME, '.claude.json');
30
- const CLIENT_DIR = join(HOME, 'gmtr-client');
31
- const GMTR_JSON = join(HOME, '.gmtr.json');
30
+ const CLIENT_DIR = join(HOME, '.gramatr');
31
+ const GMTR_JSON = join(HOME, '.gramatr.json');
32
32
  const SCRIPT_DIR = dirname(dirname(resolve(import.meta.filename || __filename)));
33
33
  const DEFAULT_URL = 'https://api.gramatr.com/mcp';
34
34
 
@@ -398,13 +398,13 @@ async function handleAuth(legacyToken: string): Promise<{ url: string; token: st
398
398
  const url = await prompt('gramatr server URL', DEFAULT_URL) || DEFAULT_URL;
399
399
 
400
400
  // Legacy aios token migration: if we cherry-picked a token from a prior
401
- // aios install and there is no current ~/.gmtr.json token, seed it so the
401
+ // aios install and there is no current ~/.gramatr.json token, seed it so the
402
402
  // shared resolver picks it up.
403
403
  if (legacyToken && !existsSync(GMTR_JSON)) {
404
404
  try {
405
405
  writeFileSync(GMTR_JSON, `${JSON.stringify({ token: legacyToken }, null, 2)}\n`, 'utf8');
406
406
  try { chmodSync(GMTR_JSON, 0o600); } catch { /* ok */ }
407
- log('OK Seeded ~/.gmtr.json from legacy aios installation token');
407
+ log('OK Seeded ~/.gramatr.json from legacy aios installation token');
408
408
  } catch { /* ignore */ }
409
409
  }
410
410
 
@@ -508,16 +508,16 @@ function updateClaudeSettings(url: string, token: string): void {
508
508
  cpSync(CLAUDE_SETTINGS, backup);
509
509
  log(`OK Backed up settings to ${basename(backup)}`);
510
510
 
511
- const includeOptionalUx = process.env.GMTR_ENABLE_OPTIONAL_CLAUDE_UX === '1';
511
+ const includeOptionalUx = process.env.GRAMATR_ENABLE_OPTIONAL_CLAUDE_UX === '1';
512
512
  const hooksConfig = buildClaudeHooksFile(CLIENT_DIR, { includeOptionalUx });
513
513
 
514
514
  const settings = readJson(CLAUDE_SETTINGS);
515
515
 
516
516
  // Env vars
517
517
  settings.env = settings.env || {};
518
- settings.env.GMTR_DIR = CLIENT_DIR;
519
- settings.env.GMTR_URL = url;
520
- settings.env.PATH = `${HOME}/.gmtr/bin:/usr/local/bin:/usr/bin:/bin`;
518
+ settings.env.GRAMATR_DIR = CLIENT_DIR;
519
+ settings.env.GRAMATR_URL = url;
520
+ settings.env.PATH = `${HOME}/.gramatr/bin:/usr/local/bin:/usr/bin:/bin`;
521
521
  if (token) settings.env.AIOS_MCP_TOKEN = token;
522
522
 
523
523
  // Identity defaults (don't overwrite)
@@ -539,7 +539,7 @@ function updateClaudeSettings(url: string, token: string): void {
539
539
  if (includeOptionalUx) {
540
540
  log('OK Optional Claude UX hooks enabled');
541
541
  } else {
542
- log('OK Thin-client hook set (set GMTR_ENABLE_OPTIONAL_CLAUDE_UX=1 for optional hooks)');
542
+ log('OK Thin-client hook set (set GRAMATR_ENABLE_OPTIONAL_CLAUDE_UX=1 for optional hooks)');
543
543
  }
544
544
 
545
545
  // Status line
@@ -564,7 +564,7 @@ function registerMcpServer(url: string, token: string): void {
564
564
  const backup = `${CLAUDE_JSON}.backup-${timestamp()}`;
565
565
  cpSync(CLAUDE_JSON, backup);
566
566
 
567
- // Store token in ~/.gmtr.json
567
+ // Store token in ~/.gramatr.json
568
568
  if (token) {
569
569
  mergeJson(GMTR_JSON, (data) => ({
570
570
  ...data,
@@ -572,10 +572,10 @@ function registerMcpServer(url: string, token: string): void {
572
572
  token_updated_at: new Date().toISOString(),
573
573
  }));
574
574
  try { chmodSync(GMTR_JSON, 0o600); } catch { /* ok */ }
575
- log('OK Token stored in ~/.gmtr.json (canonical source)');
575
+ log('OK Token stored in ~/.gramatr.json (canonical source)');
576
576
  }
577
577
 
578
- // Write tool paths to ~/.gmtr.json
578
+ // Write tool paths to ~/.gramatr.json
579
579
  mergeJson(GMTR_JSON, (data) => ({
580
580
  ...data,
581
581
  jq_binary: which('jq') || '',
@@ -585,14 +585,14 @@ function registerMcpServer(url: string, token: string): void {
585
585
  // Register in ~/.claude.json
586
586
  mergeJson(CLAUDE_JSON, (data) => {
587
587
  data.env = data.env || {};
588
- if (token) data.env.GMTR_TOKEN = token;
588
+ if (token) data.env.GRAMATR_TOKEN = token;
589
589
  delete data.env.AIOS_MCP_TOKEN;
590
590
 
591
591
  data.mcpServers = data.mcpServers || {};
592
592
  data.mcpServers.gramatr = {
593
593
  type: 'http',
594
594
  url,
595
- headers: { Authorization: 'Bearer ${GMTR_TOKEN}' },
595
+ headers: { Authorization: 'Bearer ${GRAMATR_TOKEN}' },
596
596
  autoApprove: true,
597
597
  };
598
598
  return data;
@@ -624,10 +624,10 @@ function verify(url: string, token: string): boolean {
624
624
  // exploding at hook execution time. The hook-imports-shipped.test.ts
625
625
  // regression guard catches missing entries at PR review.
626
626
  for (const f of [
627
- 'hooks/GMTRToolTracker.hook.ts',
628
- 'hooks/GMTRPromptEnricher.hook.ts',
629
- 'hooks/GMTRRatingCapture.hook.ts',
630
- 'hooks/GMTRSecurityValidator.hook.ts',
627
+ 'hooks/gramatr-tool-tracker.hook.ts',
628
+ 'hooks/gramatr-prompt-enricher.hook.ts',
629
+ 'hooks/gramatr-rating-capture.hook.ts',
630
+ 'hooks/gramatr-security-validator.hook.ts',
631
631
  'hooks/lib/notify.ts',
632
632
  'core/routing.ts',
633
633
  'core/session.ts',
@@ -734,7 +734,7 @@ async function main(): Promise<void> {
734
734
  if (!token) {
735
735
  log(' 2. Run /gmtr-login in Claude Code to authenticate');
736
736
  } else {
737
- log(' 2. Already authenticated (token found in ~/.gmtr.json)');
737
+ log(' 2. Already authenticated (token found in ~/.gramatr.json)');
738
738
  }
739
739
  log('');
740
740
  } else {
package/bin/lib/config.ts CHANGED
@@ -2,14 +2,14 @@
2
2
  * gramatr client config resolver (statusline refactor, #495).
3
3
  *
4
4
  * Single-purpose helper that returns the server URL + auth token with
5
- * NO reads of ~/.claude* or ~/gmtr-client/settings.json. This is the
5
+ * NO reads of ~/.claude* or ~/.gramatr/settings.json. This is the
6
6
  * statusline-specific config path; the richer installer auth lives in
7
7
  * core/auth.ts for a reason — this file must stay small and side-effect-free
8
8
  * so it can be loaded in a 2s shim without touching disk more than once.
9
9
  *
10
10
  * Resolution:
11
- * URL — GMTR_URL → ~/.gmtr.json.url → https://api.gramatr.com
12
- * Token — GMTR_TOKENAIOS_MCP_TOKEN → ~/.gmtr.json.token → null
11
+ * URL — GRAMATR_URL → ~/.gramatr.json.url → https://api.gramatr.com
12
+ * Token — GRAMATR_API_KEY → ~/.gramatr.json.token → null
13
13
  */
14
14
  import { existsSync, readFileSync } from 'fs';
15
15
  import { homedir } from 'os';
@@ -27,7 +27,7 @@ function getHome(): string {
27
27
  }
28
28
 
29
29
  function readGmtrJson(): Record<string, any> | null {
30
- const path = join(getHome(), '.gmtr.json');
30
+ const path = join(getHome(), '.gramatr.json');
31
31
  if (!existsSync(path)) return null;
32
32
  try {
33
33
  return JSON.parse(readFileSync(path, 'utf8'));
@@ -40,15 +40,15 @@ export function getGramatrConfig(): GramatrConfig {
40
40
  const json = readGmtrJson();
41
41
 
42
42
  const rawUrl =
43
- process.env.GMTR_URL ||
43
+ process.env.GRAMATR_URL ||
44
44
  (typeof json?.url === 'string' && json.url) ||
45
45
  DEFAULT_URL;
46
- // GMTR_URL is conventionally the MCP endpoint (e.g. https://api.gramatr.com/mcp).
46
+ // GRAMATR_URL is conventionally the MCP endpoint (e.g. https://api.gramatr.com/mcp).
47
47
  // REST calls need the API base — strip a trailing /mcp segment.
48
48
  const url = (rawUrl as string).replace(/\/mcp\/?$/, '');
49
49
 
50
50
  const token =
51
- process.env.GMTR_TOKEN ||
51
+ process.env.GRAMATR_TOKEN ||
52
52
  process.env.AIOS_MCP_TOKEN ||
53
53
  (typeof json?.token === 'string' && json.token) ||
54
54
  null;
package/bin/logout.ts CHANGED
@@ -2,8 +2,8 @@
2
2
  /**
3
3
  * gramatr logout — Clear stored gramatr credentials (issue #484).
4
4
  *
5
- * Removes ~/.gmtr.json. With --keep-backup, renames it to
6
- * ~/.gmtr.json.bak.<timestamp> instead of deleting.
5
+ * Removes ~/.gramatr.json. With --keep-backup, renames it to
6
+ * ~/.gramatr.json.bak.<timestamp> instead of deleting.
7
7
  *
8
8
  * Not-logged-in is not an error: exits 0 with a clean message.
9
9
  */
@@ -13,7 +13,7 @@ import { homedir } from "os";
13
13
  import { join } from "path";
14
14
 
15
15
  function gmtrJsonPath(): string {
16
- return join(process.env.HOME || process.env.USERPROFILE || homedir(), ".gmtr.json");
16
+ return join(process.env.HOME || process.env.USERPROFILE || homedir(), ".gramatr.json");
17
17
  }
18
18
 
19
19
  function log(msg: string = ""): void {
@@ -34,8 +34,8 @@ function showHelp(): void {
34
34
  log(`gramatr logout — Clear stored gramatr credentials
35
35
 
36
36
  Usage:
37
- gramatr logout Delete ~/.gmtr.json
38
- gramatr logout --keep-backup Rename to ~/.gmtr.json.bak.<timestamp> instead`);
37
+ gramatr logout Delete ~/.gramatr.json
38
+ gramatr logout --keep-backup Rename to ~/.gramatr.json.bak.<timestamp> instead`);
39
39
  }
40
40
 
41
41
  export function main(argv: string[] = process.argv.slice(2)): number {
@@ -8,7 +8,7 @@ function main(): void {
8
8
  throw new Error('Usage: render-claude-hooks.ts <client-dir>');
9
9
  }
10
10
 
11
- const includeOptionalUx = process.env.GMTR_ENABLE_OPTIONAL_CLAUDE_UX === '1';
11
+ const includeOptionalUx = process.env.GRAMATR_ENABLE_OPTIONAL_CLAUDE_UX === '1';
12
12
  const hooks = buildClaudeHooksFile(clientDir, { includeOptionalUx });
13
13
  process.stdout.write(`${JSON.stringify(hooks.hooks, null, 2)}\n`);
14
14
  }
package/bin/uninstall.ts CHANGED
@@ -5,7 +5,7 @@
5
5
  * Usage:
6
6
  * bun uninstall.ts # Interactive — confirms each step
7
7
  * bun uninstall.ts --yes # Non-interactive — uninstall everything
8
- * bun uninstall.ts --keep-auth # Keep ~/.gmtr.json (preserve login)
8
+ * bun uninstall.ts --keep-auth # Keep ~/.gramatr.json (preserve login)
9
9
  * npx tsx uninstall.ts # Without bun
10
10
  */
11
11
 
@@ -53,7 +53,7 @@ function removeGramatrFromJson(filePath: string, keys: string[]): boolean {
53
53
  delete data[key];
54
54
  changed = true;
55
55
  }
56
- // Handle nested keys like "env.GMTR_TOKEN"
56
+ // Handle nested keys like "env.GRAMATR_TOKEN"
57
57
  if (key.includes('.')) {
58
58
  const [parent, child] = key.split('.');
59
59
  if (data[parent] && child in data[parent]) {
@@ -97,8 +97,8 @@ async function main(): Promise<void> {
97
97
  log(' ===================');
98
98
  log('');
99
99
 
100
- const gmtrClient = join(HOME, 'gmtr-client');
101
- const gmtrJson = join(HOME, '.gmtr.json');
100
+ const gmtrClient = join(HOME, '.gramatr');
101
+ const gmtrJson = join(HOME, '.gramatr.json');
102
102
  const gmtrDotDir = join(HOME, '.gmtr');
103
103
  const claudeSettings = join(HOME, '.claude', 'settings.json');
104
104
  const claudeJson = join(HOME, '.claude.json');
@@ -111,9 +111,9 @@ async function main(): Promise<void> {
111
111
 
112
112
  // Detect what's installed
113
113
  const installed: string[] = [];
114
- if (existsSync(gmtrClient)) installed.push(`~/gmtr-client (${dirSize(gmtrClient)})`);
114
+ if (existsSync(gmtrClient)) installed.push(`~/.gramatr (${dirSize(gmtrClient)})`);
115
115
  if (existsSync(gmtrDotDir)) installed.push(`~/.gmtr/ (${dirSize(gmtrDotDir)})`);
116
- if (existsSync(gmtrJson)) installed.push('~/.gmtr.json');
116
+ if (existsSync(gmtrJson)) installed.push('~/.gramatr.json');
117
117
  if (existsSync(claudeSettings)) installed.push('~/.claude/settings.json (hooks)');
118
118
  if (existsSync(claudeJson)) installed.push('~/.claude.json (MCP server)');
119
119
  if (existsSync(codexHooks)) installed.push('~/.codex/hooks.json');
@@ -136,10 +136,10 @@ async function main(): Promise<void> {
136
136
 
137
137
  log('');
138
138
 
139
- // 1. Remove ~/gmtr-client (hooks, bin, skills, agents, tools)
139
+ // 1. Remove ~/.gramatr (hooks, bin, skills, agents, tools)
140
140
  if (existsSync(gmtrClient)) {
141
141
  rmSync(gmtrClient, { recursive: true, force: true });
142
- log(' OK Removed ~/gmtr-client');
142
+ log(' OK Removed ~/.gramatr');
143
143
  }
144
144
 
145
145
  // 2. Remove ~/.gmtr/ (bun binary, PATH additions)
@@ -148,13 +148,13 @@ async function main(): Promise<void> {
148
148
  log(' OK Removed ~/.gmtr/');
149
149
  }
150
150
 
151
- // 3. Remove ~/.gmtr.json (auth token) — unless --keep-auth
151
+ // 3. Remove ~/.gramatr.json (auth token) — unless --keep-auth
152
152
  if (existsSync(gmtrJson)) {
153
153
  if (KEEP_AUTH) {
154
- log(' -- Kept ~/.gmtr.json (--keep-auth)');
154
+ log(' -- Kept ~/.gramatr.json (--keep-auth)');
155
155
  } else {
156
156
  rmSync(gmtrJson);
157
- log(' OK Removed ~/.gmtr.json');
157
+ log(' OK Removed ~/.gramatr.json');
158
158
  }
159
159
  }
160
160
 
@@ -174,14 +174,14 @@ async function main(): Promise<void> {
174
174
  for (const [event, hooks] of Object.entries(settings.hooks)) {
175
175
  if (Array.isArray(hooks)) {
176
176
  settings.hooks[event] = (hooks as any[]).filter(
177
- (h: any) => !h.command?.includes('gmtr-client') && !h.command?.includes('gramatr')
177
+ (h: any) => !h.command?.includes('.gramatr') && !h.command?.includes('gramatr')
178
178
  );
179
179
  if (settings.hooks[event].length === 0) delete settings.hooks[event];
180
180
  }
181
181
  }
182
182
  if (Object.keys(settings.hooks).length === 0) delete settings.hooks;
183
183
  }
184
- if (settings.statusLine?.command?.includes('gmtr-client')) {
184
+ if (settings.statusLine?.command?.includes('.gramatr')) {
185
185
  delete settings.statusLine;
186
186
  }
187
187
  writeFileSync(claudeSettings, JSON.stringify(settings, null, 2) + '\n');
@@ -194,7 +194,7 @@ async function main(): Promise<void> {
194
194
 
195
195
  // 5. Remove gramatr from ~/.claude.json (MCP server + env vars)
196
196
  if (existsSync(claudeJson)) {
197
- const cleaned = removeGramatrFromJson(claudeJson, ['env.GMTR_TOKEN', 'env.AIOS_MCP_TOKEN']);
197
+ const cleaned = removeGramatrFromJson(claudeJson, ['env.GRAMATR_TOKEN', 'env.AIOS_MCP_TOKEN']);
198
198
  if (cleaned) log(' OK Removed gramatr MCP server + env vars from ~/.claude.json');
199
199
  }
200
200
 
@@ -242,7 +242,7 @@ async function main(): Promise<void> {
242
242
  for (const [event, eventHooks] of Object.entries(hooks.hooks)) {
243
243
  if (Array.isArray(eventHooks)) {
244
244
  hooks.hooks[event] = (eventHooks as any[]).filter(
245
- (h: any) => !h.command?.includes('gmtr-client') && !h.command?.includes('gramatr')
245
+ (h: any) => !h.command?.includes('.gramatr') && !h.command?.includes('gramatr')
246
246
  );
247
247
  if (hooks.hooks[event].length === 0) delete hooks.hooks[event];
248
248
  }
@@ -278,7 +278,7 @@ async function main(): Promise<void> {
278
278
  log(' Uninstall complete.');
279
279
  log(' Restart Claude Code / Codex / Gemini CLI to apply changes.');
280
280
  if (KEEP_AUTH) {
281
- log(' Auth token preserved in ~/.gmtr.json (use --token with next install).');
281
+ log(' Auth token preserved in ~/.gramatr.json (use --token with next install).');
282
282
  }
283
283
  log('');
284
284
  }
@@ -64,7 +64,7 @@ async function main(): Promise<void> {
64
64
  // Step 2: Validate server connectivity
65
65
  log('');
66
66
  log('Step 2: Validating server connectivity...');
67
- const serverUrl = process.env.GMTR_URL || DEFAULT_MCP_URL;
67
+ const serverUrl = process.env.GRAMATR_URL || DEFAULT_MCP_URL;
68
68
  const serverReachable = await validateServer(serverUrl);
69
69
  if (serverReachable) {
70
70
  log(` OK Server reachable at ${serverUrl.replace(/\/mcp$/, '')}`);
package/codex/install.ts CHANGED
@@ -47,7 +47,7 @@ export function main(): void {
47
47
  throw new Error('HOME is not set');
48
48
  }
49
49
 
50
- const gmtrDir = process.env.GMTR_DIR || join(home, 'gmtr-client');
50
+ const gmtrDir = process.env.GRAMATR_DIR || join(home, '.gramatr');
51
51
  const codexHome = join(home, '.codex');
52
52
  const hooksPath = join(codexHome, 'hooks.json');
53
53
  const configPath = join(codexHome, 'config.toml');