슬래시 명령과 /config 설정 행에 한국어 설명을 덧붙인다

개발자를 위한 커뮤니케이션 허브. 대화 · 파일 · 이슈 · 저장소 · AI 를 한 화면에 모은다.
일반 메신저는 개발 맥락을 모르고, 개발 도구는 대화를 담지 못한다. Nexus 는 그 사이를 메운다.
| 영역 | 내용 |
|---|---|
| 대화 | 스페이스 · 카테고리 · 채널(공개/비공개) · 실시간 전송 · 스레드 · 답장(인용) · 멘션 · 리액션 · 핀 · 마크다운 |
| DM · 프레즌스 | 스페이스 안 1:1 DM · 온라인 / 자리비움(10분 무입력) / 오프라인 · 입력 중 표시 |
| 멤버 · 권한 | 스페이스 만들기 · 초대 코드 · 초대 링크 · 역할(owner · admin · member · guest) · 비공개 채널 명단 · 역할별 채널 권한(가리기 · 읽기 전용) |
| 알림 | 알림함(멘션 · @channel · DM · 내 글의 답글) · 종류별 스위치 · 채널 음소거 · 앱을 보고 있지 않을 때 OS 알림(Windows 토스트 · 브라우저) · Windows 트레이 |
| 파일 | 첨부 업로드(진행률) · 이미지 미리보기 · 스페이스 파일 목록 · 무기한 보관 |
| 이슈 | 칸반 보드(끌어 옮기기) · 상세 · 댓글 · 라벨 · 대화 → 이슈 · 스프린트 · 번다운(스페이스마다 켜는 선택 기능) |
| GitHub | 계정 연결(OAuth) · 웹훅 자동 등록 · 브랜치 · 파일 트리 · 커밋 · PR 열람 |
| 인덱싱 | 저장소를 청크로 나눠 임베딩 · 벡터 검색(pgvector HNSW) · push 마다 증분 갱신 |
| AI 패널 | 자유 지시문 + 프리셋(요약 · 이슈 초안) · 컨텍스트(메시지 · 채널 최근 대화 · 저장소 RAG) · 이어 묻기 · 지난 대화 다시 열기 |
| 설정 | 표시 이름 · 프로필 사진 · 비밀번호 변경 · 알림 · 테마(시스템 · 라이트 · 다크) |
| 화면 | 자체 UI — Material · Cupertino 없이 직접 만든 부품(app/lib/ui/) · 반응형(데스크톱 · 태블릿 · 모바일) · 새로고침 · 로그인 뒤 원래 주소로 |
app/ Flutter — 한 코드베이스로 Windows · Android · Web (iOS 는 macOS 가 없어 동결)
│ Riverpod · go_router · dio · drift(오프라인 캐시 + 전송 큐) · 자체 UI(WidgetsApp)
│
│ REST + Socket.IO
▼
server/ NestJS + Prisma
├─ PostgreSQL + pgvector 모든 데이터 · 코드 임베딩 · 작업 큐(AI · 인덱싱)
├─ 스토리지 첨부 파일 (개발은 로컬 디스크, 배포는 S3 호환 — R2)
├─ LLM gemini · local(Ollama) · fake
└─ 임베딩 gemini · local(Ollama) · fake
deploy/ VM 한 대 — Docker Compose(postgres · server · nginx · cloudflared · backup)
웹과 API 를 nginx 한 오리진으로 낸다 · Cloudflare Tunnel · R2
Space 가 모든 데이터의 루트인 멀티테넌트 구조다. 채널 · 메시지 · 이슈 · 저장소는 전부 스페이스에 속하고, 스페이스에 속한 테이블은 spaceId 를 직접 가진다. 볼 수 없는 리소스는 403 이 아니라 404 로 답한다.
외부 원본(GitHub)은 사본을 두지 않고 프록시한다. Redis 는 쓰지 않는다 — 큐도 Postgres 에 둔다.
| 폴더 | 설명 |
|---|---|
server/ | NestJS 백엔드 — REST API · Socket.IO 게이트웨이 · 계약 검증 스크립트(scripts/) |
app/ | Flutter 앱 — 실행법은 app/README.md |
deploy/ | 배포 구성 — prod compose · nginx · 절차는 deploy/README.md |
design-system/ | 디자인 토큰(tokens.css) · 컴포넌트 · 화면 프리뷰 |
docs/ | 기획 · 설계 문서 · 진행 기록 |
필요한 것: Node.js 22 · Flutter 3.44.9 이상 · WSL2(Ubuntu) 또는 Docker
git clone https://github.com/dbsrjs/Nexus.git && cd Nexus
npm --prefix server install
npm run env:setup # server/.env 생성 · 시크릿 자동 채움
npm run db:setup # (1회) WSL 안에 Postgres + pgvector
npm run db:up # Docker 라면 위 둘 대신 npm run db:up:docker
npm --prefix server run prisma:generate
npm --prefix server run prisma:deploy
npm run db:seed
npm run server:dev # http://localhost:3000/api
env:setup 은 여러 번 돌려도 안전하다. 만들어 낼 수 없는 값(GITHUB_CLIENT_ID · GITHUB_CLIENT_SECRET · PUBLIC_BASE_URL)은 끝에 목록으로 알려 준다 — GitHub 연동을 쓸 때만 필요하다. AI · 인덱싱은 .env 의 LLM_PROVIDER · EMBEDDING_PROVIDER 를 채워야 켜진다.
Windows 에서는
DATABASE_URL에localhost대신127.0.0.1을 쓴다(WSL 포워딩이 IPv4 만 동작한다). 서버가listen EACCES ...:3000으로 죽으면 Windows 가 그 포트를 예약한 것이다 — 처방은 CLAUDE.md §2.
cd app
flutter pub get
flutter run -d windows --dart-define=API_BASE=http://127.0.0.1:3000
flutter run -d chrome --web-port=5173 # 서버 CORS 가 5173 만 허용한다
Android 에뮬레이터는 --dart-define=API_BASE=http://10.0.2.2:3000 을 넘긴다(에뮬레이터에게 127.0.0.1 은 자기 자신이다). Windows 데스크톱 빌드에는 개발자 모드가 켜져 있어야 한다.
| 명령 | 내용 | |
|---|---|---|
| 명령 | 내용 | 규모 (2026-10-09) |
| --- | --- | --- |
npm run server:test · server:lint | 서버 단위 테스트(Jest) · ESLint — 순수 로직 · 가드 · 권한 규칙 | 535개 |
npm run check:* | 실서버 · 실DB · 실소켓 계약 검증 — 실시간 · 리액션 · 스레드 · 첨부 · 이슈 · GitHub 연동 · 인덱싱 · AI · 설정 · 멤버 · 권한 · DM · 프레즌스 · 알림 · 테넌트 격리(check:tenancy — 스페이스 경로 전부를 남의 id 로 친다). GitHub 은 스스로 띄우는 가짜 서버로 대신한다 | 20종 1,123개 |
npm run check:migrations · check:sql-time | 마이그레이션 · raw SQL 정적 검사 (DB 불필요) | |
cd app && flutter analyze && flutter test | 앱 정적 분석 · 단위 · 위젯 테스트 | 591개 |
npm run app:flow | 앱 통합 테스트 — Windows 앱을 실서버에 붙여 로그인부터 전송 · 실시간 · 설정 · 멤버 · DM · 알림함 · AI 까지 돈다 | 약 30초 |
npm run app:flow:headless | 같은 흐름을 창 없이(flutter_tester) 돈다 — CI 가 이것을 돈다 | 약 15초 |
CI(.github/workflows/ci.yml)가 main 과 feat/** 의 push 마다 위 전부를 돈다 — 앱 통합 테스트는 창 없는 쪽(app:flow:headless)으로, 첨부는 S3 경로(SeaweedFS)로도 한 번 더. Windows 창으로 보는 app:flow 는 화면 모습을 바꿨을 때 사람이 돌린다.
1~19단계와 «마지막»(출시 준비)의 네 갈래가 끝났다(2026-10-09). 위 기능표가 전부 동작하고, 배포 구성(deploy/) · 테넌트 격리 통합 검증 · 딥링크 · 데스크톱 · 웹 알림 + Windows 트레이까지 들어갔다.
| 남은 것 | 내용 |
|---|---|
| 실제 VM 배포 | 구성과 절차(deploy/README.md)는 있다. VM · R2 · Cloudflare Tunnel 을 정하고 올리는 일 |
| OS 수준 링크 연결 | Android App Links · Windows 프로토콜 등록 — 공개 도메인이 정해진 뒤 |
| 20 GitLab 연동 | provider 추상화 뒤에 GitLab. 배포 뒤로 미뤄도 되는 유일한 단계 |
모바일 푸시(FCM)는 범위에서 뺐다(2026-10-09). 단계마다의 결정과 확인 내역은 진행 기록 에 있다.
| 로드맵 | 목표 |
|---|---|
| Phase 0 | 나 혼자 쓰는 개발 허브 — 프로젝트를 채널로 나누고 할 일 · 저장소를 붙인다 |
| Phase 1 | 2~10인 소규모 팀 — 초대 · 온보딩 · 알림 |
| Phase 2 | 공개 서비스 — 테넌트 격리 · 스토리지 쿼터 · 과금 |
| 문서 | 내용 |
|---|---|
| 코드 둘러보기 | 처음 열었을 때 여기부터. 돌려 보기 · 구조 · 한 줄기 따라가기 |
| 제품 기획 | 방향 · 타겟 · 기능 범위 · 로드맵 |
| 백엔드 설계 | 멀티테넌시 · 데이터 모델 · API 계약 · 실시간 · 인증 |
| 앱 설계 | Flutter 스택 · 화면 · 상태 관리 · 오프라인 전략 |
| 인프라 설계 | 배포 구성 · 공개 저장소 보안 체크리스트 |
| 디자인 시스템 | 색 · 타이포 · 간격 · 컴포넌트 |
| 전환 계획 | 작업 목록과 진행 상황 |
| 진행 기록 | 단계마다 갈린 결정 · 확인한 것 · 확인하지 못한 것 |
| 기술 스택 가이드 | 스택별 학습 순서 · 코드 읽기 시작점 |
| 서버 README | 서버 셋업 · 규약 · Ollama · 실제 GitHub 웹훅 붙이는 법 |
| 배포 README | VM · R2 · Cloudflare Tunnel 로 올리는 절차 |
| 단계별 설계 스펙 | 단계마다 정한 것 · 범위에서 뺀 것과 그 이유 |
hooks/register.ts 40 lines1import type { Register } from 'claude-code'
2
3import { COMMANDS, CONFIG } from './dictionary'
4
5// 이미 한글이 들어 있으면(이 모드나 다른 플러그인이 붙였거나 원래 한국어) 다시 붙이지 않는다.
6const HANGUL = /[ㄱ-ㆎ가-힣]/
7
8// 플러그인 · 스킬 명령은 `anthropic-skills:pdf` 처럼 접두사가 붙는다. 정확한 이름을 먼저,
9// 없으면 마지막 마디로 찾는다.
10export function lookupCommand(name: string): string | undefined {
11 return COMMANDS[name] ?? COMMANDS[name.split(':').pop() ?? name]
12}
13
14// 명령 목록은 한 줄로 그려져 길면 뒤가 잘린다. 스킬 설명은 영어가 길어서 뒤에 붙이면
15// 한국어가 잘려 보이지 않으므로 앞에 둔다.
16export function koDescription(name: string, description: string): string | undefined {
17 const ko = lookupCommand(name)
18 if (!ko || HANGUL.test(description)) return undefined
19 return description ? `${ko} — ${description}` : ko
20}
21
22// 설정 행은 라벨이 짧아 잘릴 걱정이 없으므로 원문 옆에 둔다(원문을 먼저 두어 문서 · 검색어와 대조된다).
23export function koLabel(key: string, label: string): string | undefined {
24 const ko = CONFIG[key]
25 if (!ko || HANGUL.test(label)) return undefined
26 return `${label} · ${ko}`
27}
28
29export const register: Register = on => {
30 on('command.describe', ($, e, next) => {
31 const description = koDescription(e.command, e.description)
32 return description ? next({ ...e, description }) : next(e)
33 })
34
35 on('config.describe', ($, e, next) => {
36 const label = koLabel(e.key, e.label)
37 return label ? next({ ...e, label }) : next(e)
38 })
39}
40hooks/dictionary.ts 173 lines1// 이름 → 한국어 설명. 영어 고유 명칭(MCP · IDE · CLAUDE.md · Chrome 등)은 그대로 둔다.
2// 엔진이 이름으로만 찾으므로, 사전에 없는 명령 · 행은 원문 그대로 보인다(조용히 틀리게 번역하지 않는다).
3
4export const COMMANDS: Readonly<Record<string, string>> = {
5 // 내장 명령
6 'add-dir': '작업 디렉터리 추가',
7 advisor: '중요한 순간에 더 강한 모델에게 자문',
8 agents: '서브에이전트 관리',
9 autocompact: '자동 압축 창 크기 설정',
10 btw: '작업을 멈추지 않고 곁가지 질문',
11 bug: '버그 신고 · 피드백 보내기',
12 feedback: '버그 신고 · 피드백 보내기',
13 chrome: 'Claude in Chrome 설정',
14 clear: '빈 컨텍스트로 새 세션 시작(이전 세션은 /resume 으로 재개 가능)',
15 color: '이번 세션 입력창 색 설정',
16 compact: '지금까지의 대화를 요약해 컨텍스트 확보',
17 config: '설정 열기 · 키로 설정 변경',
18 context: '현재 컨텍스트 사용량 보기',
19 copy: '마지막 응답 복사',
20 cost: '세션 비용 · 사용량 보기',
21 debug: '디버그 로그 켜고 문제 진단',
22 doctor: 'Claude Code 설치 · 설정 상태 점검',
23 effort: '모델 추론 노력 수준 설정',
24 exit: 'Claude Code 종료',
25 quit: 'Claude Code 종료',
26 export: '대화를 파일 · 클립보드로 내보내기',
27 fast: '빠른 모드 전환',
28 focus: '집중 보기 전환(프롬프트 · 요약 · 응답만)',
29 goal: '조건을 만족할 때까지 계속 작업할 목표 설정',
30 heapdump: 'JS 힙 덤프 저장',
31 help: '도움말 · 명령 목록',
32 hooks: '훅 설정 관리',
33 ide: 'IDE 연결 관리',
34 import: '다른 AI 코딩 에이전트의 설정 가져오기',
35 init: '코드베이스 문서화용 CLAUDE.md 생성',
36 insights: 'Claude Code 세션 분석 보고서 생성',
37 'install-github-app': 'GitHub Actions 용 Claude 앱 설치',
38 'install-slack-app': 'Slack 용 Claude 앱 설치',
39 keybindings: '단축키 설정',
40 'list-agents': '메시지를 보낼 수 있는 서브에이전트 · 팀원 · 세션 목록',
41 login: '로그인 · 계정 전환',
42 logout: '로그아웃',
43 mcp: 'MCP 서버 관리',
44 memory: '메모리 파일(CLAUDE.md) 편집',
45 model: '사용할 AI 모델 설정',
46 'output-style': '출력 스타일 목록 · 전환',
47 permissions: '도구 허용 · 거부 규칙 관리',
48 allowed_tools: '도구 허용 · 거부 규칙 관리',
49 plugin: '플러그인 관리',
50 plugins: '플러그인 관리',
51 'pr-comments': 'GitHub PR 댓글 가져오기',
52 'privacy-settings': '개인정보 설정',
53 recap: '세션 한 줄 요약 지금 만들기',
54 'release-notes': '릴리스 노트 보기',
55 'reload-plugins': '변경된 플러그인을 이번 세션에 적용',
56 'reload-skills': '세션 중 추가 · 변경된 스킬 다시 읽기',
57 'remote-control': '다른 기기에서 이 세션 원격 제어',
58 rename: '현재 대화 이름 바꾸기',
59 resume: '이전 대화 재개',
60 continue: '이전 대화 재개',
61 review: 'PR 리뷰',
62 rewind: '대화 · 코드를 이전 시점으로 되감기',
63 checkpoint: '대화 · 코드를 이전 시점으로 되감기',
64 sandbox: '샌드박스 설정',
65 'security-review': '현재 브랜치 변경의 보안 리뷰',
66 'skill-doctor': '안 쓰이면서 컨텍스트를 차지하는 스킬 보기',
67 skills: '스킬 목록',
68 stats: '사용 통계 보기',
69 status: '버전 · 모델 · 계정 · 연결 상태 보기',
70 statusline: '상태 줄 설정',
71 tasks: '백그라운드 작업 목록',
72 bashes: '백그라운드 작업 목록',
73 'team-onboarding': '사용 기록으로 팀원용 Claude Code 안내서 만들기',
74 'terminal-setup': '터미널 줄바꿈 키(Shift+Enter) 설정',
75 theme: '테마 변경',
76 todos: '할 일 목록 보기',
77 upgrade: '요금제 업그레이드',
78 usage: '세션 비용 · 요금제 사용량 · 한도 기여 항목 보기',
79 vim: 'Vim 편집 모드 전환',
80
81 // 내장 스킬
82 batch: '대규모 변경을 계획하고 여러 worktree 에이전트로 병렬 실행',
83 'claude-api': 'Claude API · Anthropic SDK 참고 자료',
84 'code-review': '현재 diff · PR 의 버그 리뷰',
85 dataviz: '차트 · 그래프 · 대시보드 작성 가이드',
86 'deep-research': '여러 출처를 조사해 인용 보고서 작성',
87 design: '요청서로 새 Design 아티팩트 만들기',
88 'design-consent': 'Design 프로젝트 접근 권한 허용',
89 'design-revoke': 'Design 프로젝트 접근 권한 회수',
90 'design-sync': 'React 디자인 시스템을 claude.ai/design 으로 올리기',
91 'artifact-capabilities': '아티팩트 런타임 기능 안내',
92 'artifact-design': '아티팩트 디자인 가이드',
93 'artifact-diagramming': '아티팩트 다이어그램 가이드',
94 'fewer-permission-prompts': '자주 쓰는 읽기 전용 명령을 허용 목록에 추가해 권한 확인 줄이기',
95 'keybindings-help': '단축키 바꾸기 도움말',
96 loop: '프롬프트 · 명령을 주기적으로 반복 실행',
97 'plugin-authoring': '모드(띠 · 패널 · 상태 줄 · 훅) 만들기',
98 run: '앱을 실행해 변경을 직접 확인',
99 'run-skill-generator': '프로젝트별 run 스킬 작성 · 개선',
100 simplify: '변경 코드의 재사용 · 단순화 · 효율 정리',
101 slides: '요청서로 새 슬라이드 덱 만들기',
102 'update-config': 'settings.json 설정(훅 · 권한 · 환경 변수) 변경',
103 verify: '변경이 실제로 동작하는지 끝까지 실행해 확인',
104 'workflow-authoring': 'Workflow 스크립트 작성 참고 자료',
105
106 // 클라우드 · 사용자 스킬
107 'startup-hook-skill': '클라우드 세션용 시작 훅 만들기',
108 'session-start-hook': '클라우드 세션용 시작 훅 만들기',
109 'built-in-browser': '데스크톱 앱 내장 브라우저 사용 안내',
110 'chrome-browser': 'Claude in Chrome 확장 사용 안내',
111 'computer-use': '내 컴퓨터의 앱 조작(computer use) 안내',
112 docs: '함께 편집 · 공유하는 문서 만들기',
113 docx: 'Word(.docx) 문서 만들기 · 편집',
114 'google-workspace': 'Google Docs · Sheets · Slides 파일 만들기 · 편집',
115 'import-memory': '다른 AI 비서의 메모리 가져오기',
116 morning: '아침 브리핑 만들기 · 예약',
117 pdf: 'PDF 읽기 · 병합 · 분할 · 생성',
118 pptx: 'PowerPoint(.pptx) 만들기 · 편집',
119 'skill-creator': '스킬 만들기 · 개선 · 평가',
120 xlsx: '스프레드시트 만들기 · 편집',
121
122 // 이 저장소(Nexus) 스킬
123 'nexus-android-verify': 'Android 에뮬레이터 · 실기기에서 앱 변경 확인',
124 'nexus-deck': 'Nexus 발표 자료(PPT) 만들기',
125 'nexus-migration': 'Prisma 마이그레이션 추가 · 변경(HNSW 인덱스 보호)',
126 'nexus-pc-handoff': 'PC 를 옮길 때 git 으로 안 옮겨지는 것 챙기기',
127 'nexus-verify': 'check:* 계약 검증 실행 · 디버그',
128}
129
130export const CONFIG: Readonly<Record<string, string>> = {
131 autoCompact: '자동 압축',
132 autoContinueAtUsageLimit: '사용 한도에서 자동으로 계속',
133 switchModelsOnFlag: '메시지가 플래그되면 모델 전환',
134 tips: '팁 보기',
135 reduceMotion: '움직임 줄이기',
136 thinking: '생각 모드',
137 promptSuggestionEnabled: '프롬프트 제안',
138 recap: '세션 요약',
139 checkpoints: '코드 되감기(체크포인트)',
140 workflows: '동적 워크플로',
141 workflowKeywordTriggerEnabled: 'Ultracode 키워드로 시작',
142 workflowSizeGuideline: '동적 워크플로 규모',
143 artifacts: '아티팩트',
144 verbose: '자세한 출력',
145 progressBar: '터미널 진행 막대',
146 turnDuration: '턴 소요 시간 보기',
147 timeFormat: '시간 형식',
148 permissionMode: '기본 권한 모드',
149 worktreeBaseRef: 'worktree 기준 ref',
150 useAutoModeDuringPlan: '계획 중 자동 모드 사용',
151 gitignore: '파일 선택기에서 .gitignore 따르기',
152 copyFullResponse: '/copy 선택 창 건너뛰기',
153 copyOnSelect: '선택하면 복사',
154 autoScroll: '자동 스크롤',
155 defaultToAgentsView: '기본으로 에이전트 보기 열기',
156 leftArrowOpensAgents: '← 키로 에이전트 보기 열기',
157 autoUpdatesChannel: '자동 업데이트 채널',
158 theme: '테마',
159 notifChannel: '로컬 알림',
160 inputNeededNotifEnabled: '조치가 필요하면 푸시',
161 agentPushNotifEnabled: 'Claude 가 판단하면 푸시',
162 outputStyle: '출력 스타일',
163 language: '언어',
164 editor: '편집기 모드',
165 askUserQuestionTimeout: '질문 자동 진행 대기 시간',
166 externalEditorContext: '외부 편집기에 마지막 응답 표시',
167 prStatus: 'PR 상태 표시줄 보기',
168 model: '모델',
169 autoConnectIde: 'IDE 자동 연결(외부 터미널)',
170 chrome: 'Claude in Chrome 기본 사용',
171 dialogExpiry: '대화 상자 만료',
172}
173