git add/commit에 .env 파일이 들어가면 Bash 호출을 막는다

에이전트의 경험 → 사실 → 판단 → 행동 규칙을 쌓는 메모리 시스템 + Claude Code mods. 설계: docs/DESIGN.md
윈도우(회사 PC)는 docs/SETUP-WINDOWS.md를 따르세요.
git clone <이 저장소> ~/workspace/agent-memory
claude plugin marketplace add ~/workspace/agent-memory
claude plugin install memory-events@agent-memory
claude plugin install memory-lens@agent-memory
claude plugin install env-guard@agent-memory
로컬 폴더 marketplace라 git pull 후 세션에서 /reload-plugins만 하면 반영됨.
git clone https://github.com/alstjrwjd99/memory-personal.git ~/workspace/memory-personal
작업 전후로 uv run amem sync (pull --rebase + push). events/는 PC 로컬에만 남음.
cd engine
uv sync
uv run amem init --machine mac --personal ~/workspace/memory-personal # 맥
uv run amem init --machine win-work --work C:\work\memory-work --personal ... # 윈도우
uv run amem health
uv run amem promote # events → episode (신호 있는 세션만 LLM 호출)
uv run amem reflect # 판단 변화 제안 생성
uv run amem review # 제안 확인
uv run amem apply <id> --only 1,3 / uv run amem reject <id>
uv run amem export # 확신도 높은 판단을 Claude Code 메모리로
uv run amem recall "질문" --cwd . # 관련 기억 꺼내기 (memory-lens가 프롬프트마다 자동 호출)
uv run amem history <id> # 한 기억의 변천 (versions + 확신도 + git diff)
uv run amem sync # store git pull --rebase + push
uv run amem --store work ... # 업무 store 대상
설정: ~/.config/agent-memory/config.yaml (윈도우: %USERPROFILE%\.config\agent-memory\config.yaml)
/config 또는 settings.json pluginConfigs)| 필드 | Mac | Windows(회사) |
|---|---|---|
| machine | mac | win-work |
| defaultScope | personal | work |
| personalStore | ~/workspace/memory-personal 절대경로 | (개인 store 경로) |
| workStore | (비움) | C:\...\memory-work |
| workPaths | (비움) | 필요 시 |
hooks/register.ts 16 lines1import type { Register } from 'claude-code'
2import { findEnvFiles } from './guard.ts'
3
4export const register: Register = on => {
5 on('tool.call', { tool: 'Bash' }, ($, e, next) => {
6 const hits = findEnvFiles(e.command)
7 if (hits.length === 0) return next(e)
8
9 $.ui.toast(`env-guard: ${hits.join(', ')} 커밋 차단`)
10 return { deny: `${$.plugin.name}: .env 파일은 커밋 금지 (${hits.join(', ')}). .gitignore에 추가하고 해당 파일은 빼고 진행할 것.` }
11 }).catch(($, e, next) =>
12 // 가드 자체가 실패하면 안전하게 막는다
13 next.called ? next(e) : { deny: `${$.plugin.name}: 가드 실행 실패` },
14 )
15}
16hooks/guard.ts 15 lines1// git add/commit 명령에서 .env 계열 파일 인자를 찾는다 (.env.example 등 템플릿은 허용)
2const GIT_STAGE = /\bgit\s+(?:-C\s+\S+\s+)?(add|commit)\b/
3const ENV_FILE = /(^|[\/\\])\.env(\.[\w.-]+)?$/
4const TEMPLATE = /\.(example|sample|template|dist)$/
5
6export function findEnvFiles(command: string): string[] {
7 // && ; | 로 이어진 명령을 쪼개서 git add/commit 구간만 본다
8 return command
9 .split(/&&|\|\||;|\|/)
10 .filter(part => GIT_STAGE.test(part))
11 .flatMap(part => part.trim().split(/\s+/))
12 .map(token => token.replace(/^['"]|['"]$/g, ''))
13 .filter(token => ENV_FILE.test(token) && !TEMPLATE.test(token))
14}
15