MCPcopy
hub / github.com/codeaashu/claude-code / readLocalTeamMemory

Function readLocalTeamMemory

src/services/teamMemorySync/index.ts:567–673  ·  view source on GitHub ↗

* Read all team memory files from the local directory into a flat key-value map. * Keys are relative paths from the team memory directory. * Empty files are included (content will be empty string). * * PSR M22174: Each file is scanned for credentials before inclusion * using patterns from gitle

(maxEntries: number | null)

Source from the content-addressed store, hash-verified

565 * warn the user.
566 */
567async function readLocalTeamMemory(maxEntries: number | null): Promise<{
568 entries: Record<string, string>
569 skippedSecrets: SkippedSecretFile[]
570}> {
571 const teamDir = getTeamMemPath()
572 const entries: Record<string, string> = {}
573 const skippedSecrets: SkippedSecretFile[] = []
574
575 async function walkDir(dir: string): Promise<void> {
576 try {
577 const dirEntries = await readdir(dir, { withFileTypes: true })
578 await Promise.all(
579 dirEntries.map(async entry => {
580 const fullPath = join(dir, entry.name)
581 if (entry.isDirectory()) {
582 await walkDir(fullPath)
583 } else if (entry.isFile()) {
584 try {
585 const stats = await stat(fullPath)
586 if (stats.size > MAX_FILE_SIZE_BYTES) {
587 logForDebugging(
588 `team-memory-sync: skipping oversized file ${entry.name} (${stats.size} > ${MAX_FILE_SIZE_BYTES} bytes)`,
589 { level: 'info' },
590 )
591 return
592 }
593 const content = await readFile(fullPath, 'utf8')
594 const relPath = relative(teamDir, fullPath).replaceAll('\\', '/')
595
596 // PSR M22174: scan for secrets BEFORE adding to the upload
597 // payload. If a secret is detected, skip this file entirely
598 // so it never leaves the machine.
599 const secretMatches = scanForSecrets(content)
600 if (secretMatches.length > 0) {
601 // Report only the first match per file — one secret is
602 // enough to skip the file and we don't want to log more
603 // than necessary about credential locations.
604 const firstMatch = secretMatches[0]!
605 skippedSecrets.push({
606 path: relPath,
607 ruleId: firstMatch.ruleId,
608 label: firstMatch.label,
609 })
610 logForDebugging(
611 `team-memory-sync: skipping "${relPath}" — detected ${firstMatch.label}`,
612 { level: 'warn' },
613 )
614 return
615 }
616
617 entries[relPath] = content
618 } catch {
619 // Skip unreadable files
620 }
621 }
622 }),
623 )
624 } catch (e) {

Callers 1

pushTeamMemoryFunction · 0.85

Calls 5

getTeamMemPathFunction · 0.85
walkDirFunction · 0.85
logForDebuggingFunction · 0.85
logEventFunction · 0.85
keysMethod · 0.80

Tested by

no test coverage detected