thedotmack/claude-mem · warning

Skipped Codex transcript watch because native Codex hooks ar

Error message

Skipped Codex transcript watch because native Codex hooks are authoritative

What it means

claude-mem captures Codex sessions through native Codex hooks, which are authoritative. filterNativeHookBackedCodexWatches() therefore removes the canonical Codex transcript watch (name 'codex' targeting ~/.codex/sessions/**/*.jsonl) from the watch config unless CLAUDE_MEM_CODEX_TRANSCRIPT_INGESTION is exactly 'true'. This warning reports how many watches were removed so ingestion is not duplicated.

Source

Thrown at src/services/worker-service.ts:738

    const configPath = settings.CLAUDE_MEM_TRANSCRIPTS_CONFIG_PATH || DEFAULT_CONFIG_PATH;
    const resolvedConfigPath = expandHomePath(configPath);

    if (!existsSync(resolvedConfigPath)) {
      logger.info('TRANSCRIPT', 'Transcript watcher config not found; skipping automatic transcript capture', {
        configPath: resolvedConfigPath
      });
      return;
    }

    const allowCodexTranscriptIngestion = settings.CLAUDE_MEM_CODEX_TRANSCRIPT_INGESTION === 'true';
    const { config: transcriptConfig, removed } = filterNativeHookBackedCodexWatches(
      loadTranscriptWatchConfig(configPath),
      allowCodexTranscriptIngestion
    );
    const statePath = expandHomePath(transcriptConfig.stateFile ?? DEFAULT_STATE_PATH);

    if (removed > 0) {
      logger.warn('TRANSCRIPT', 'Skipped Codex transcript watch because native Codex hooks are authoritative', {
        removed,
        optInSetting: 'CLAUDE_MEM_CODEX_TRANSCRIPT_INGESTION=true',
      });
    }

    if (transcriptConfig.watches.length === 0) {
      logger.info('TRANSCRIPT', 'Transcript watcher config has no active watches; skipping automatic transcript capture', {
        configPath: resolvedConfigPath,
      });
      return;
    }

    try {
      this.transcriptWatcher = new TranscriptWatcher(transcriptConfig, statePath);
      await this.transcriptWatcher.start();
    } catch (error) {
      this.transcriptWatcher?.stop();
      this.transcriptWatcher = null;

View on GitHub (pinned to e2d1df569a)

Solutions

  1. Do nothing if native Codex hooks are active — sessions are still captured, this skip is intentional and avoids duplicates
  2. If you genuinely need transcript tailing instead, set CLAUDE_MEM_CODEX_TRANSCRIPT_INGESTION=true in the worker's environment (e.g. ~/.claude-mem/.env) and restart

Example fix

# ~/.claude-mem/.env - add to re-enable tailing
CLAUDE_MEM_CODEX_TRANSCRIPT_INGESTION=true
Defensive patterns

Strategy: validation

Validate before calling

function expectCodexIngestion(env: NodeJS.ProcessEnv): void {
  const tailing = env.CLAUDE_MEM_CODEX_TRANSCRIPT_INGESTION === 'true';
  const nativeHooks = fs.existsSync(path.join(os.homedir(), '.codex'));
  if (!tailing && !nativeHooks) {
    throw new Error('Codex capture disabled: no native hooks and transcript ingestion not opted in');
  }
}

Prevention

When it happens

Trigger: The watch config ships the default codex watch while native hooks are installed, and the opt-in env var is unset or set to anything other than the literal string 'true'.

Common situations: Users re-enabling an old transcript-watch config after upgrading to a claude-mem version that ships native Codex hooks; setting CLAUDE_MEM_CODEX_TRANSCRIPT_INGESTION in the wrong env file so it never reaches the worker.

Related errors


AI-assisted analysis of thedotmack/claude-mem@e2d1df569a (2026-08-20). Data as JSON: /api/errors/561eb4b08401da6a. Report an issue: GitHub.