@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.
package/core/auth.ts CHANGED
@@ -7,9 +7,9 @@
7
7
  *
8
8
  * Resolution chain (first non-empty wins):
9
9
  * 1. GRAMATR_API_KEY env var
10
- * 2. GMTR_TOKEN env var (legacy)
11
- * 3. ~/.gmtr.json `token` field
12
- * 4. ~/gmtr-client/settings.json `auth.api_key` (legacy, skips placeholder)
10
+ * 2. GRAMATR_TOKEN env var (legacy)
11
+ * 3. ~/.gramatr.json `token` field
12
+ * 4. ~/.gramatr/settings.json `auth.api_key` (legacy, skips placeholder)
13
13
  * 5. If interactive + TTY: spawn gmtr-login.ts (OAuth)
14
14
  * 6. Otherwise: throw clean actionable error
15
15
  *
@@ -44,17 +44,19 @@ function getHome(): string {
44
44
  }
45
45
 
46
46
  function gmtrJsonPath(): string {
47
- return join(getHome(), ".gmtr.json");
47
+ return join(getHome(), ".gramatr.json");
48
48
  }
49
49
 
50
50
  function legacySettingsPath(): string {
51
- const gmtrDir = process.env.GMTR_DIR || join(getHome(), "gmtr-client");
51
+ const gmtrDir = process.env.GRAMATR_DIR || join(getHome(), ".gramatr");
52
52
  return join(gmtrDir, "settings.json");
53
53
  }
54
54
 
55
55
  function tokenFromEnv(): string | null {
56
+ // GRAMATR_API_KEY is the canonical env var for long-lived API keys.
57
+ // Legacy GMTR_TOKEN slot was removed in v0.6.0; see #512 for the full
58
+ // auth architecture refactor (split API keys from OAuth refresh tokens).
56
59
  if (process.env.GRAMATR_API_KEY) return process.env.GRAMATR_API_KEY;
57
- if (process.env.GMTR_TOKEN) return process.env.GMTR_TOKEN;
58
60
  return null;
59
61
  }
60
62
 
@@ -88,7 +90,7 @@ function findGmtrLoginScript(): string | null {
88
90
  }
89
91
  // Fallback to installed client dir
90
92
  const installedCandidate = join(
91
- process.env.GMTR_DIR || join(getHome(), "gmtr-client"),
93
+ process.env.GRAMATR_DIR || join(getHome(), ".gramatr"),
92
94
  "bin",
93
95
  "gmtr-login.ts",
94
96
  );
@@ -142,7 +144,7 @@ export async function resolveAuthToken(opts: ResolveAuthTokenOptions): Promise<s
142
144
  const envToken = tokenFromEnv();
143
145
  if (envToken) return envToken;
144
146
 
145
- // 3: ~/.gmtr.json
147
+ // 3: ~/.gramatr.json
146
148
  const stored = tokenFromGmtrJson();
147
149
  if (stored) return stored;
148
150
 
package/core/feedback.ts CHANGED
@@ -33,7 +33,7 @@ export async function submitPendingClassificationFeedback(
33
33
  }
34
34
 
35
35
  const result = await callMcpToolDetailed(
36
- 'gmtr_classification_feedback',
36
+ 'gramatr_classification_feedback',
37
37
  {
38
38
  timestamp: last.timestamp,
39
39
  was_correct: true,
package/core/install.ts CHANGED
@@ -27,13 +27,13 @@ interface ClaudeHookOptions {
27
27
  }
28
28
 
29
29
  const CLAUDE_HOOKS: HookSpec[] = [
30
- { event: 'PreToolUse', matcher: 'Bash', relativeCommand: 'hooks/GMTRSecurityValidator.hook.ts' },
31
- { event: 'PreToolUse', matcher: 'Edit', relativeCommand: 'hooks/GMTRSecurityValidator.hook.ts' },
32
- { event: 'PreToolUse', matcher: 'Write', relativeCommand: 'hooks/GMTRSecurityValidator.hook.ts' },
33
- { event: 'PreToolUse', matcher: 'Read', relativeCommand: 'hooks/GMTRSecurityValidator.hook.ts' },
34
- { event: 'PostToolUse', matcher: 'mcp__.*gramatr.*__', relativeCommand: 'hooks/GMTRToolTracker.hook.ts' },
35
- { event: 'UserPromptSubmit', relativeCommand: 'hooks/GMTRRatingCapture.hook.ts' },
36
- { event: 'UserPromptSubmit', relativeCommand: 'hooks/GMTRPromptEnricher.hook.ts' },
30
+ { event: 'PreToolUse', matcher: 'Bash', relativeCommand: 'hooks/gramatr-security-validator.hook.ts' },
31
+ { event: 'PreToolUse', matcher: 'Edit', relativeCommand: 'hooks/gramatr-security-validator.hook.ts' },
32
+ { event: 'PreToolUse', matcher: 'Write', relativeCommand: 'hooks/gramatr-security-validator.hook.ts' },
33
+ { event: 'PreToolUse', matcher: 'Read', relativeCommand: 'hooks/gramatr-security-validator.hook.ts' },
34
+ { event: 'PostToolUse', matcher: 'mcp__.*gramatr.*__', relativeCommand: 'hooks/gramatr-tool-tracker.hook.ts' },
35
+ { event: 'UserPromptSubmit', relativeCommand: 'hooks/gramatr-rating-capture.hook.ts' },
36
+ { event: 'UserPromptSubmit', relativeCommand: 'hooks/gramatr-prompt-enricher.hook.ts' },
37
37
  { event: 'SessionStart', relativeCommand: 'hooks/session-start.hook.ts' },
38
38
  { event: 'SessionEnd', relativeCommand: 'hooks/session-end.hook.ts' },
39
39
  { event: 'Stop', relativeCommand: 'hooks/StopOrchestrator.hook.ts' },
package/core/routing.ts CHANGED
@@ -30,7 +30,7 @@ export async function routePrompt(options: {
30
30
  statuslineSize?: 'small' | 'medium' | 'large';
31
31
  }): Promise<{ route: RouteResponse | null; error: MctToolCallError | null }> {
32
32
  const result = await callMcpToolDetailed<RouteResponse>(
33
- 'gmtr_route_request',
33
+ 'gramatr_route_request',
34
34
  {
35
35
  prompt: options.prompt,
36
36
  ...(options.projectId ? { project_id: options.projectId } : {}),
@@ -79,7 +79,7 @@ export function describeRoutingFailure(error: MctToolCallError): {
79
79
  return {
80
80
  title: 'Routing request failed before intelligence could be injected.',
81
81
  detail: error.detail,
82
- action: `Inspect the response from ${resolveMcpUrl()} and the gmtr_route_request handler.`,
82
+ action: `Inspect the response from ${resolveMcpUrl()} and the gramatr_route_request handler.`,
83
83
  };
84
84
  }
85
85
  }
package/core/session.ts CHANGED
@@ -28,7 +28,7 @@ export interface CurrentProjectContextPayload {
28
28
  project_name: string;
29
29
  working_directory: string;
30
30
  session_start: string;
31
- gmtr_config_path: string;
31
+ gramatr_config_path: string;
32
32
  project_entity_id: string | null;
33
33
  action_required: string;
34
34
  project_id?: string;
@@ -114,7 +114,7 @@ export async function startRemoteSession(options: {
114
114
  directory: string;
115
115
  }): Promise<SessionStartResponse | null> {
116
116
  return (await callMcpTool(
117
- 'gmtr_session_start',
117
+ 'gramatr_session_start',
118
118
  {
119
119
  client_type: options.clientType,
120
120
  project_id: options.projectId,
@@ -129,7 +129,7 @@ export async function startRemoteSession(options: {
129
129
 
130
130
  export async function loadProjectHandoff(projectId: string): Promise<HandoffResponse | null> {
131
131
  return (await callMcpTool(
132
- 'gmtr_load_handoff',
132
+ 'gramatr_load_handoff',
133
133
  { project_id: projectId },
134
134
  15000,
135
135
  )) as HandoffResponse | null;
@@ -143,7 +143,7 @@ export function persistSessionRegistration(rootDir: string, response: SessionSta
143
143
  if (!config) return null;
144
144
  config.current_session = config.current_session || {};
145
145
  if (normalized.interactionId) config.current_session.interaction_id = normalized.interactionId;
146
- if (normalized.entityId) config.current_session.gmtr_entity_id = normalized.entityId;
146
+ if (normalized.entityId) config.current_session.gramatr_entity_id = normalized.entityId;
147
147
  writeGmtrConfig(rootDir, config);
148
148
  return config;
149
149
  }
@@ -176,7 +176,7 @@ export function buildGitProjectContextPayload(options: {
176
176
  git_remote: options.git.remote,
177
177
  working_directory: options.workingDirectory,
178
178
  session_start: options.sessionStart,
179
- gmtr_config_path: join(options.git.root, '.gmtr', 'settings.json'),
179
+ gramatr_config_path: join(options.git.root, '.gmtr', 'settings.json'),
180
180
  project_entity_id: options.projectEntityId,
181
181
  restore_needed: options.restoreNeeded,
182
182
  action_required: 'check_or_create_project_entity',
@@ -195,8 +195,8 @@ export function buildNonGitProjectContextPayload(options: {
195
195
  project_name: basename(options.cwd),
196
196
  working_directory: options.cwd,
197
197
  session_start: options.sessionStart,
198
- gmtr_config_path: join(options.cwd, '.gmtr', 'settings.json'),
198
+ gramatr_config_path: join(options.cwd, '.gmtr', 'settings.json'),
199
199
  project_entity_id: options.projectEntityId,
200
- action_required: 'gmtr_init_needed',
200
+ action_required: 'gramatr_init_needed',
201
201
  };
202
202
  }
package/core/version.ts CHANGED
@@ -8,8 +8,8 @@
8
8
  * Works in two environments:
9
9
  * 1. Source checkout: packages/client/core/version.ts →
10
10
  * packages/client/package.json (found one directory up).
11
- * 2. Installed client: ~/gmtr-client/core/version.ts →
12
- * ~/gmtr-client/package.json (copied by installClientFiles()).
11
+ * 2. Installed client: ~/.gramatr/core/version.ts →
12
+ * ~/.gramatr/package.json (copied by installClientFiles()).
13
13
  *
14
14
  * If the file cannot be resolved (unexpected layout), falls back to '0.0.0'
15
15
  * rather than throwing — the version check is opportunistic and must never
@@ -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/gemini/README.md CHANGED
@@ -74,7 +74,7 @@ bun packages/client/bin/gmtr-login.ts
74
74
 
75
75
  This stores the token in `~/.gmtr.json`, which the installer reads automatically.
76
76
 
77
- API keys start with `gmtr_sk_` and can be created at [gramatr.com](https://gramatr.com) or via the `gmtr_create_api_key` MCP tool.
77
+ API keys start with `gramatr_sk_` and can be created at [gramatr.com](https://gramatr.com) or via the `gramatr_create_api_key` MCP tool.
78
78
 
79
79
  ## Hook Event Mapping
80
80
 
package/gemini/install.ts CHANGED
@@ -46,7 +46,7 @@ async function promptForApiKey(): Promise<string | null> {
46
46
  log(' gramatr requires authentication.');
47
47
  log(' Options:');
48
48
  log(' 1. Run `bun gmtr-login.ts` first to authenticate via browser');
49
- log(' 2. Paste an API key below (starts with gmtr_sk_)');
49
+ log(' 2. Paste an API key below (starts with gramatr_sk_)');
50
50
  log('');
51
51
  process.stdout.write(' API Key (enter to skip): ');
52
52
 
@@ -104,10 +104,10 @@ async function testApiKey(key: string): Promise<boolean> {
104
104
  }
105
105
 
106
106
  async function resolveApiKey(home: string): Promise<string | null> {
107
- // 1. Check if already stored in ~/.gmtr.json (shared with other platforms)
107
+ // 1. Check if already stored in ~/.gramatr.json (shared with other platforms)
108
108
  const stored = readStoredApiKey(home);
109
109
  if (stored) {
110
- log(` Found existing token in ~/.gmtr.json`);
110
+ log(` Found existing token in ~/.gramatr.json`);
111
111
  log(' Testing token...');
112
112
  const valid = await testApiKey(stored);
113
113
  if (valid) {
@@ -142,8 +142,8 @@ async function resolveApiKey(home: string): Promise<string | null> {
142
142
  const valid = await testApiKey(prompted);
143
143
  if (valid) {
144
144
  log(' OK Token is valid');
145
- // Save to ~/.gmtr.json for cross-platform reuse
146
- const configPath = join(home, '.gmtr.json');
145
+ // Save to ~/.gramatr.json for cross-platform reuse
146
+ const configPath = join(home, '.gramatr.json');
147
147
  let config: Record<string, unknown> = {};
148
148
  if (existsSync(configPath)) {
149
149
  try {
@@ -154,12 +154,12 @@ async function resolveApiKey(home: string): Promise<string | null> {
154
154
  }
155
155
  config.token = prompted;
156
156
  config.token_type =
157
- prompted.startsWith('gmtr_sk_') || prompted.startsWith('aios_sk_')
157
+ prompted.startsWith('gramatr_sk_') || prompted.startsWith('aios_sk_')
158
158
  ? 'api_key'
159
159
  : 'oauth';
160
160
  config.authenticated_at = new Date().toISOString();
161
161
  writeFileSync(configPath, JSON.stringify(config, null, 2) + '\n');
162
- log(' OK Saved to ~/.gmtr.json');
162
+ log(' OK Saved to ~/.gramatr.json');
163
163
  return prompted;
164
164
  }
165
165
  log(' Token rejected by server.');
@@ -244,9 +244,9 @@ export async function main(): Promise<void> {
244
244
  );
245
245
  log(' OK Wrote hooks/hooks.json');
246
246
 
247
- // ── Store token in ~/.gmtr.json (canonical source, not in extension dir) ──
247
+ // ── Store token in ~/.gramatr.json (canonical source, not in extension dir) ──
248
248
  if (apiKey) {
249
- const gmtrJsonPath = join(home, '.gmtr.json');
249
+ const gmtrJsonPath = join(home, '.gramatr.json');
250
250
  let gmtrConfig: Record<string, unknown> = {};
251
251
  if (existsSync(gmtrJsonPath)) {
252
252
  try { gmtrConfig = JSON.parse(readFileSync(gmtrJsonPath, 'utf8')); } catch {}
@@ -254,7 +254,7 @@ export async function main(): Promise<void> {
254
254
  gmtrConfig.token = apiKey;
255
255
  gmtrConfig.token_updated_at = new Date().toISOString();
256
256
  writeFileSync(gmtrJsonPath, JSON.stringify(gmtrConfig, null, 2) + '\n');
257
- log(' OK Token stored in ~/.gmtr.json (hooks read from here at runtime)');
257
+ log(' OK Token stored in ~/.gramatr.json (hooks read from here at runtime)');
258
258
  }
259
259
 
260
260
  // ── Summary ──
@@ -67,7 +67,7 @@ export function buildExtensionManifest(): GeminiExtensionManifest {
67
67
  name: 'API Key',
68
68
  envVar: 'GRAMATR_API_KEY',
69
69
  sensitive: true,
70
- description: 'gramatr API key (starts with gmtr_sk_). Get one at gramatr.com or via gmtr-login.',
70
+ description: 'gramatr API key (starts with gramatr_sk_). Get one at gramatr.com or via gmtr-login.',
71
71
  },
72
72
  ],
73
73
  };
@@ -155,10 +155,10 @@ export function getGramatrExtensionDir(home: string): string {
155
155
  }
156
156
 
157
157
  /**
158
- * Read the stored API key from ~/.gmtr.json (shared with other platforms).
158
+ * Read the stored API key from ~/.gramatr.json (shared with other platforms).
159
159
  */
160
160
  export function readStoredApiKey(home: string): string | null {
161
- const configPath = join(home, '.gmtr.json');
161
+ const configPath = join(home, '.gramatr.json');
162
162
  if (!existsSync(configPath)) return null;
163
163
  try {
164
164
  const config = JSON.parse(readFileSync(configPath, 'utf8'));
@@ -36,11 +36,11 @@ async function main() {
36
36
 
37
37
  // Read server URL and token for direct HTTP feedback
38
38
  const gmtrDir = getGmtrDir();
39
- let serverUrl = process.env.GMTR_URL || 'https://api.gramatr.com/mcp';
39
+ let serverUrl = process.env.GRAMATR_URL || 'https://api.gramatr.com/mcp';
40
40
  let token = '';
41
41
 
42
42
  try {
43
- const gmtrJson = JSON.parse(readFileSync(`${process.env.HOME}/.gmtr.json`, 'utf8'));
43
+ const gmtrJson = JSON.parse(readFileSync(`${process.env.HOME}/.gramatr.json`, 'utf8'));
44
44
  token = gmtrJson.token || '';
45
45
  } catch { /* no token */ }
46
46
 
@@ -61,7 +61,7 @@ async function main() {
61
61
  id: 1,
62
62
  method: 'tools/call',
63
63
  params: {
64
- name: 'gmtr_classification_feedback',
64
+ name: 'gramatr_classification_feedback',
65
65
  arguments: {
66
66
  original_prompt: parsed.userMessages?.[0] || '',
67
67
  session_id: hookInput.session_id,
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * gmtr-tool-tracker-utils.ts — Pure utility functions for the GMTR Tool Tracker hook.
3
3
  *
4
- * Extracted from GMTRToolTracker.hook.ts for testability. These are pure functions
4
+ * Extracted from gramatr-tool-tracker.hook.ts for testability. These are pure functions
5
5
  * with no Bun dependencies, no I/O, no side effects.
6
6
  */
7
7
 
@@ -1,13 +1,13 @@
1
1
  #!/usr/bin/env node
2
2
  /**
3
- * GMTRPromptEnricher.hook.ts — grāmatr UserPromptSubmit Hook
3
+ * gramatr-prompt-enricher.hook.ts — grāmatr UserPromptSubmit Hook
4
4
  *
5
5
  * Fires before the agent processes a user prompt. Calls the grāmatr
6
6
  * decision router to pre-classify the request, then injects
7
7
  * the intelligence as additionalContext so the agent sees it.
8
8
  *
9
9
  * TRIGGER: UserPromptSubmit
10
- * TIMEOUT: 15s default (configurable via GMTR_TIMEOUT)
10
+ * TIMEOUT: 15s default (configurable via GRAMATR_TIMEOUT)
11
11
  * SAFETY: Never blocks. On any error, prompt passes through unmodified.
12
12
  *
13
13
  * What it injects:
@@ -42,8 +42,8 @@ interface HookInput {
42
42
 
43
43
  // ── Configuration ──
44
44
 
45
- const TIMEOUT_MS = parseInt(process.env.GMTR_TIMEOUT || '30000', 10);
46
- const ENABLED = process.env.GMTR_ENRICH !== '0'; // disable with GMTR_ENRICH=0
45
+ const TIMEOUT_MS = parseInt(process.env.GRAMATR_TIMEOUT || '30000', 10);
46
+ const ENABLED = process.env.GRAMATR_ENRICH !== '0'; // disable with GRAMATR_ENRICH=0
47
47
 
48
48
  // ── Project ID Resolution (Issue #76 — project-scoped memory) ──
49
49
 
@@ -398,9 +398,9 @@ function formatIntelligence(data: RouteResponse): string {
398
398
  lines.push(` Context: ${ca.context_summary || 'memory-aware'}`);
399
399
  lines.push(' ACTION: Use the Task tool with subagent_type="general-purpose" and inject this system prompt:');
400
400
  lines.push(' --- AGENT SYSTEM PROMPT START ---');
401
- // Truncate to avoid overwhelming the context — full prompt available via gmtr_invoke_agent
401
+ // Truncate to avoid overwhelming the context — full prompt available via gramatr_invoke_agent
402
402
  const promptPreview = (ca.system_prompt || '').substring(0, 800);
403
- lines.push(` ${promptPreview}${(ca.system_prompt || '').length > 800 ? '... [truncated — use gmtr_invoke_agent for full prompt]' : ''}`);
403
+ lines.push(` ${promptPreview}${(ca.system_prompt || '').length > 800 ? '... [truncated — use gramatr_invoke_agent for full prompt]' : ''}`);
404
404
  lines.push(' --- AGENT SYSTEM PROMPT END ---');
405
405
  }
406
406
  }
@@ -1,9 +1,9 @@
1
1
  #!/usr/bin/env node
2
2
  /**
3
- * GMTRRatingCapture.hook.ts — gramatr-native Rating Capture (UserPromptSubmit)
3
+ * gramatr-rating-capture.hook.ts — gramatr-native Rating Capture (UserPromptSubmit)
4
4
  *
5
5
  * Captures explicit ratings (1-10 pattern) from user prompts and writes
6
- * to $GMTR_DIR/.state/ratings.jsonl for sparkline consumption.
6
+ * to $GRAMATR_DIR/.state/ratings.jsonl for sparkline consumption.
7
7
  *
8
8
  * TRIGGER: UserPromptSubmit
9
9
  *
@@ -15,7 +15,7 @@
15
15
  * - Self-contained: only depends on ./lib/paths
16
16
  *
17
17
  * SIDE EFFECTS:
18
- * - Writes to: $GMTR_DIR/.state/ratings.jsonl
18
+ * - Writes to: $GRAMATR_DIR/.state/ratings.jsonl
19
19
  * - macOS notification for low ratings (<= 3)
20
20
  *
21
21
  * PERFORMANCE:
@@ -100,13 +100,13 @@ function parseExplicitRating(prompt: string): { rating: number; comment?: string
100
100
  function writeRating(entry: RatingEntry): void {
101
101
  if (!existsSync(STATE_DIR)) mkdirSync(STATE_DIR, { recursive: true });
102
102
  appendFileSync(RATINGS_FILE, JSON.stringify(entry) + '\n', 'utf-8');
103
- console.error(`[GMTRRatingCapture] Wrote rating ${entry.rating} to ${RATINGS_FILE}`);
103
+ console.error(`[gramatr-rating-capture] Wrote rating ${entry.rating} to ${RATINGS_FILE}`);
104
104
  }
105
105
 
106
106
  // ── Push to GMTR Server (fire-and-forget) ──
107
107
 
108
108
  function pushToServer(entry: RatingEntry): void {
109
- const gmtrUrl = process.env.GMTR_URL || 'https://api.gramatr.com/mcp';
109
+ const gmtrUrl = process.env.GRAMATR_URL || 'https://api.gramatr.com/mcp';
110
110
  const apiBase = gmtrUrl.replace(/\/mcp$/, '/api/v1');
111
111
 
112
112
  fetch(`${apiBase}/feedback`, {
@@ -124,9 +124,9 @@ function pushToServer(entry: RatingEntry): void {
124
124
  })
125
125
  .then((res) => {
126
126
  if (res.ok) {
127
- console.error(`[GMTRRatingCapture] Pushed rating ${entry.rating} to server`);
127
+ console.error(`[gramatr-rating-capture] Pushed rating ${entry.rating} to server`);
128
128
  } else {
129
- console.error(`[GMTRRatingCapture] Server push failed: HTTP ${res.status}`);
129
+ console.error(`[gramatr-rating-capture] Server push failed: HTTP ${res.status}`);
130
130
  }
131
131
  })
132
132
  .catch(() => {
@@ -169,7 +169,7 @@ async function main() {
169
169
  process.exit(0);
170
170
  }
171
171
 
172
- console.error(`[GMTRRatingCapture] Explicit rating: ${result.rating}${result.comment ? ` - ${result.comment}` : ''}`);
172
+ console.error(`[gramatr-rating-capture] Explicit rating: ${result.rating}${result.comment ? ` - ${result.comment}` : ''}`);
173
173
 
174
174
  const entry: RatingEntry = {
175
175
  timestamp: new Date().toISOString(),
@@ -190,7 +190,7 @@ async function main() {
190
190
 
191
191
  process.exit(0);
192
192
  } catch (err) {
193
- console.error(`[GMTRRatingCapture] Error: ${err}`);
193
+ console.error(`[gramatr-rating-capture] Error: ${err}`);
194
194
  process.exit(0);
195
195
  }
196
196
  }
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
  /**
3
- * GMTRSecurityValidator.hook.ts — gramatr-native Security Validation (PreToolUse)
3
+ * gramatr-security-validator.hook.ts — gramatr-native Security Validation (PreToolUse)
4
4
  *
5
5
  * Validates Bash commands and file operations against security patterns
6
6
  * before execution. Prevents destructive operations and protects sensitive files.
@@ -10,7 +10,7 @@
10
10
  * This is the gramatr-native replacement for PAI's SecurityValidator.hook.ts.
11
11
  * Key differences:
12
12
  * - Inline default patterns (no yaml dependency, no PAI skill dir)
13
- * - Logs to $GMTR_DIR/.state/security/ (not PAI MEMORY/SECURITY/)
13
+ * - Logs to $GRAMATR_DIR/.state/security/ (not PAI MEMORY/SECURITY/)
14
14
  * - Self-contained: only depends on ./lib/paths
15
15
  *
16
16
  * OUTPUT:
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
  /**
3
- * GMTRToolTracker.hook.ts — grāmatr PostToolUse Hook
3
+ * gramatr-tool-tracker.hook.ts — grāmatr PostToolUse Hook
4
4
  *
5
5
  * Fires after any GMTR MCP tool call. Extracts execution metrics from
6
6
  * tool_result and surfaces them as a user-visible status line.
@@ -146,7 +146,7 @@ async function main() {
146
146
  try { stats = JSON.parse(readFileSync(statsFile, 'utf8')); } catch {}
147
147
 
148
148
  // Track search count
149
- if (shortName.includes('search') || shortName === 'gmtr_execute_intent') {
149
+ if (shortName.includes('search') || shortName === 'gramatr_execute_intent') {
150
150
  stats.search_count = ((stats.search_count as number) || 0) + 1;
151
151
  }
152
152
 
@@ -46,7 +46,7 @@ export interface GmtrConfig {
46
46
  last_updated?: string;
47
47
  token_limit?: number;
48
48
  interaction_id?: string;
49
- gmtr_entity_id?: string;
49
+ gramatr_entity_id?: string;
50
50
  helper_pid?: number | null;
51
51
  last_classification?: {
52
52
  timestamp?: string;
@@ -341,31 +341,31 @@ export function createDefaultConfig(options: {
341
341
  * Resolve auth token. gramatr credentials NEVER live in CLI-specific config files.
342
342
  *
343
343
  * Priority:
344
- * 1. ~/.gmtr.json (canonical, gramatr-owned, vendor-agnostic)
345
- * 2. GMTR_TOKEN env var (CI, headless override)
346
- * 3. ~/gmtr-client/settings.json auth.api_key (legacy, will be migrated)
344
+ * 1. ~/.gramatr.json (canonical, gramatr-owned, vendor-agnostic)
345
+ * 2. GRAMATR_TOKEN env var (CI, headless override)
346
+ * 3. ~/.gramatr/settings.json auth.api_key (legacy, will be migrated)
347
347
  *
348
348
  * Token is NEVER stored in ~/.claude.json, ~/.codex/, or ~/.gemini/.
349
349
  */
350
350
  export function resolveAuthToken(): string | null {
351
- // 1. ~/.gmtr.json (canonical source — written by installer, read by all platforms)
351
+ // 1. ~/.gramatr.json (canonical source — written by installer, read by all platforms)
352
352
  try {
353
- const configPath = join(HOME, '.gmtr.json');
353
+ const configPath = join(HOME, '.gramatr.json');
354
354
  const config = JSON.parse(readFileSync(configPath, 'utf8'));
355
355
  if (config.token) return config.token;
356
356
  } catch {
357
357
  // No config file or parse error
358
358
  }
359
359
 
360
- // 2. GMTR_TOKEN env var (CI, headless, or shell profile override)
361
- if (process.env.GMTR_TOKEN) return process.env.GMTR_TOKEN;
360
+ // 2. GRAMATR_TOKEN env var (CI, headless, or shell profile override)
361
+ if (process.env.GRAMATR_TOKEN) return process.env.GRAMATR_TOKEN;
362
362
 
363
363
  // 3. Legacy: AIOS_MCP_TOKEN env var (deprecated)
364
364
  if (process.env.AIOS_MCP_TOKEN) return process.env.AIOS_MCP_TOKEN;
365
365
 
366
- // 4. Legacy: ~/gmtr-client/settings.json (will be migrated to ~/.gmtr.json)
366
+ // 4. Legacy: ~/.gramatr/settings.json (will be migrated to ~/.gramatr.json)
367
367
  try {
368
- const gmtrDir = process.env.GMTR_DIR || join(HOME, 'gmtr-client');
368
+ const gmtrDir = process.env.GRAMATR_DIR || join(HOME, '.gramatr');
369
369
  const settingsPath = join(gmtrDir, 'settings.json');
370
370
  const settings = JSON.parse(readFileSync(settingsPath, 'utf8'));
371
371
  if (settings.auth?.api_key && settings.auth.api_key !== 'REPLACE_WITH_YOUR_API_KEY') {
@@ -382,12 +382,12 @@ export function resolveAuthToken(): string | null {
382
382
 
383
383
  /**
384
384
  * Resolve MCP server URL from config files.
385
- * Priority: ~/gmtr-client/settings.json > GMTR_URL env > ~/.claude.json > default
385
+ * Priority: ~/.gramatr/settings.json > GRAMATR_URL env > ~/.claude.json > default
386
386
  */
387
387
  export function resolveMcpUrl(): string {
388
- // 1. ~/gmtr-client/settings.json (canonical, vendor-agnostic)
388
+ // 1. ~/.gramatr/settings.json (canonical, vendor-agnostic)
389
389
  try {
390
- const gmtrDir = process.env.GMTR_DIR || join(HOME, 'gmtr-client');
390
+ const gmtrDir = process.env.GRAMATR_DIR || join(HOME, '.gramatr');
391
391
  const settingsPath = join(gmtrDir, 'settings.json');
392
392
  const settings = JSON.parse(readFileSync(settingsPath, 'utf8'));
393
393
  if (settings.auth?.server_url) return settings.auth.server_url;
@@ -396,7 +396,7 @@ export function resolveMcpUrl(): string {
396
396
  }
397
397
 
398
398
  // 2. Environment variable
399
- if (process.env.GMTR_URL) return process.env.GMTR_URL;
399
+ if (process.env.GRAMATR_URL) return process.env.GRAMATR_URL;
400
400
 
401
401
  // 3. ~/.claude.json (Claude-specific MCP config)
402
402
  try {
@@ -10,8 +10,8 @@ import { readFileSync, existsSync } from 'fs';
10
10
  import { join } from 'path';
11
11
 
12
12
  const HOME = process.env.HOME!;
13
- const GMTR_DIR = process.env.GMTR_DIR || join(HOME, 'gmtr-client');
14
- const GMTR_SETTINGS_PATH = join(GMTR_DIR, 'settings.json'); // gramatr-owned, vendor-agnostic
13
+ const GRAMATR_DIR = process.env.GRAMATR_DIR || join(HOME, '.gramatr');
14
+ const GMTR_SETTINGS_PATH = join(GRAMATR_DIR, 'settings.json'); // gramatr-owned, vendor-agnostic
15
15
  const CLAUDE_SETTINGS_PATH = join(HOME, '.claude/settings.json'); // legacy fallback only
16
16
 
17
17
  // Default identity (fallback if settings.json doesn't have identity section)
@@ -82,7 +82,7 @@ let cachedSettings: Settings | null = null;
82
82
  * Load settings — gramatr-owned config first, Claude vendor file as legacy fallback.
83
83
  *
84
84
  * Priority:
85
- * 1. ~/gmtr-client/settings.json (gramatr-owned, vendor-agnostic)
85
+ * 1. ~/.gramatr/settings.json (gramatr-owned, vendor-agnostic)
86
86
  * 2. ~/.claude/settings.json (Claude vendor file — legacy fallback only)
87
87
  *
88
88
  * Merges both: gramatr settings take precedence for identity fields,
@@ -28,15 +28,15 @@ export function expandPath(path: string): string {
28
28
 
29
29
  /**
30
30
  * Get the GMTR base directory (expanded)
31
- * Priority: GMTR_DIR env var → PAI_DIR env var (migration) → ~/.claude
31
+ * Priority: GRAMATR_DIR env var → PAI_DIR env var (migration) → ~/.claude
32
32
  */
33
33
  export function getGmtrDir(): string {
34
- const envGmtrDir = process.env.GMTR_DIR;
34
+ const envGmtrDir = process.env.GRAMATR_DIR;
35
35
  if (envGmtrDir) {
36
36
  return expandPath(envGmtrDir);
37
37
  }
38
38
 
39
- // Migration fallback: honor PAI_DIR if GMTR_DIR not set yet
39
+ // Migration fallback: honor PAI_DIR if GRAMATR_DIR not set yet
40
40
  const envPaiDir = process.env.PAI_DIR;
41
41
  if (envPaiDir) {
42
42
  return expandPath(envPaiDir);
@@ -49,15 +49,15 @@ export function getGmtrDir(): string {
49
49
 
50
50
  /**
51
51
  * Get the settings.json path
52
- * Always ~/.claude/settings.json — NOT relative to GMTR_DIR.
53
- * GMTR_DIR is the client payload directory (~/gmtr-client), not ~/.claude.
52
+ * Always ~/.claude/settings.json — NOT relative to GRAMATR_DIR.
53
+ * GRAMATR_DIR is the client payload directory (~/.gramatr), not ~/.claude.
54
54
  */
55
55
  export function getSettingsPath(): string {
56
56
  return join(homedir(), '.claude', 'settings.json');
57
57
  }
58
58
 
59
59
  /**
60
- * Get a path relative to GMTR_DIR
60
+ * Get a path relative to GRAMATR_DIR
61
61
  */
62
62
  export function gmtrPath(...segments: string[]): string {
63
63
  return join(getGmtrDir(), ...segments);
@@ -123,17 +123,17 @@ async function main(): Promise<void> {
123
123
  }
124
124
 
125
125
  // Get session state from config
126
- const sessionEntityId = config?.current_session?.gmtr_entity_id || '';
126
+ const sessionEntityId = config?.current_session?.gramatr_entity_id || '';
127
127
  const interactionId = config?.current_session?.interaction_id || '';
128
128
 
129
129
  log('');
130
130
  log('Saving session state to gramatr...');
131
131
 
132
- // Session lifecycle only — gmtr_session_end records git summary on the session entity.
133
- // Handoffs are saved by the AGENT in the LEARN phase via gmtr_save_handoff (HARD GATE).
132
+ // Session lifecycle only — gramatr_session_end records git summary on the session entity.
133
+ // Handoffs are saved by the AGENT in the LEARN phase via gramatr_save_handoff (HARD GATE).
134
134
  // The hook does NOT save handoffs — it lacks conversation context.
135
135
  try {
136
- const rawResult = await callMcpToolRaw('gmtr_session_end', {
136
+ const rawResult = await callMcpToolRaw('gramatr_session_end', {
137
137
  entity_id: sessionEntityId || sessionId,
138
138
  session_id: sessionId,
139
139
  interaction_id: interactionId,
@@ -171,7 +171,7 @@ function displayBanner(): void {
171
171
  // ── Sync Ratings (background, non-blocking) ──
172
172
 
173
173
  function syncRatingsInBackground(): void {
174
- const syncScript = join(process.env.GMTR_DIR || join(process.env.HOME || '', 'gmtr-client'), 'hooks', 'sync-ratings.hook.ts');
174
+ const syncScript = join(process.env.GRAMATR_DIR || join(process.env.HOME || '', '.gramatr'), 'hooks', 'sync-ratings.hook.ts');
175
175
  if (existsSync(syncScript)) {
176
176
  try {
177
177
  const npxBin = process.platform === 'win32' ? 'npx.cmd' : 'npx';
@@ -336,9 +336,9 @@ async function main(): Promise<void> {
336
336
  log(' - Show observation timestamps');
337
337
  log(`3. Load related entities from \`${gmtrConfigPath}\`:`);
338
338
  log(' - Check .related_entities for linked databases, people, services, concepts');
339
- log(' - Optionally fetch details for key related entities (use gmtr_execute_intent with detail_level: summary)');
339
+ log(' - Optionally fetch details for key related entities (use gramatr_execute_intent with detail_level: summary)');
340
340
  log('4. Keep summary concise - just enough context to resume work');
341
- log(' NOTE: Using intelligent tools (gmtr_execute_intent) provides 80-95% token reduction vs direct get_entities calls');
341
+ log(' NOTE: Using intelligent tools (gramatr_execute_intent) provides 80-95% token reduction vs direct get_entities calls');
342
342
  log('');
343
343
  }
344
344
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gramatr/client",
3
- "version": "0.5.2",
3
+ "version": "0.6.1",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },