agent-confhub-cli 0.1.0__tar.gz
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.
- agent_confhub_cli-0.1.0/.claude/rules/architecture.md +6 -0
- agent_confhub_cli-0.1.0/.claude/rules/coding.md +27 -0
- agent_confhub_cli-0.1.0/.claude/rules/testing.md +6 -0
- agent_confhub_cli-0.1.0/.claude/settings.local.json +9 -0
- agent_confhub_cli-0.1.0/.github/workflows/ci.yml +67 -0
- agent_confhub_cli-0.1.0/.gitignore +19 -0
- agent_confhub_cli-0.1.0/.pre-commit-config.yaml +18 -0
- agent_confhub_cli-0.1.0/CLAUDE.md +97 -0
- agent_confhub_cli-0.1.0/PKG-INFO +15 -0
- agent_confhub_cli-0.1.0/README.md +195 -0
- agent_confhub_cli-0.1.0/nexus/__init__.py +3 -0
- agent_confhub_cli-0.1.0/nexus/cli.py +113 -0
- agent_confhub_cli-0.1.0/nexus/commands/__init__.py +0 -0
- agent_confhub_cli-0.1.0/nexus/commands/agent.py +325 -0
- agent_confhub_cli-0.1.0/nexus/commands/app.py +234 -0
- agent_confhub_cli-0.1.0/nexus/commands/init.py +150 -0
- agent_confhub_cli-0.1.0/nexus/commands/install.py +129 -0
- agent_confhub_cli-0.1.0/nexus/commands/link.py +171 -0
- agent_confhub_cli-0.1.0/nexus/commands/resolve.py +125 -0
- agent_confhub_cli-0.1.0/nexus/commands/status.py +124 -0
- agent_confhub_cli-0.1.0/nexus/commands/submodule.py +348 -0
- agent_confhub_cli-0.1.0/nexus/commands/sync.py +155 -0
- agent_confhub_cli-0.1.0/nexus/core/__init__.py +0 -0
- agent_confhub_cli-0.1.0/nexus/core/agents.py +99 -0
- agent_confhub_cli-0.1.0/nexus/core/linker.py +215 -0
- agent_confhub_cli-0.1.0/nexus/core/merger.py +223 -0
- agent_confhub_cli-0.1.0/nexus/core/registry.py +147 -0
- agent_confhub_cli-0.1.0/nexus/utils/__init__.py +0 -0
- agent_confhub_cli-0.1.0/nexus/utils/console.py +41 -0
- agent_confhub_cli-0.1.0/nexus/utils/git.py +125 -0
- agent_confhub_cli-0.1.0/pyproject.toml +49 -0
- agent_confhub_cli-0.1.0/tests/__init__.py +0 -0
- agent_confhub_cli-0.1.0/tests/test_agent.py +186 -0
- agent_confhub_cli-0.1.0/tests/test_app.py +105 -0
- agent_confhub_cli-0.1.0/tests/test_git.py +74 -0
- agent_confhub_cli-0.1.0/tests/test_init.py +103 -0
- agent_confhub_cli-0.1.0/tests/test_linker.py +198 -0
- agent_confhub_cli-0.1.0/tests/test_merger.py +221 -0
- agent_confhub_cli-0.1.0/tests/test_registry.py +74 -0
- agent_confhub_cli-0.1.0/tests/test_resolve_cmd.py +73 -0
- agent_confhub_cli-0.1.0/tests/test_sync.py +129 -0
- agent_confhub_cli-0.1.0/uv.lock +704 -0
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
# 아키텍처 원칙
|
|
2
|
+
|
|
3
|
+
- **Registry 의존성 주입**: 모든 코어 클래스는 `Registry(base_path)` 또는 `base_path`를 주입받는다. 하드코딩된 `~/.nexus` 경로 사용 금지.
|
|
4
|
+
- **resolved/ 불변성**: `root/`와 `apps/` 원본은 절대 수정하지 않는다. 병합 결과는 반드시 `resolved/`에만 쓴다.
|
|
5
|
+
- **심볼릭 링크 단위**: 에이전트 폴더(`.claude/` 등) 전체를 단위로 링크한다. 개별 파일 링크 금지.
|
|
6
|
+
- **links.json이 링크 레지스트리**: 심볼릭 링크 상태는 `links/links.json`에서 추적한다. 파일시스템 탐색만으로 상태를 판단하지 않는다.
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# 코딩 규칙
|
|
2
|
+
|
|
3
|
+
## 타입 안전성
|
|
4
|
+
|
|
5
|
+
- `str | None` 파라미터를 `str`을 받는 함수에 전달하기 전에 반드시 `assert param is not None`으로 타입을 좁힌다.
|
|
6
|
+
- `Optional[X]` 대신 `X | None` 문법을 사용한다 (Python 3.10+).
|
|
7
|
+
|
|
8
|
+
## 파일 입출력
|
|
9
|
+
|
|
10
|
+
- 모든 파일 열기에 `encoding="utf-8"`을 명시한다.
|
|
11
|
+
- 설정 파일 포맷: Registry 메타 → YAML, 링크 정보 → JSON, 에이전트 설정 → YAML.
|
|
12
|
+
|
|
13
|
+
## CLI 패턴
|
|
14
|
+
|
|
15
|
+
- 오류 발생 시 `print_error()`로 메시지를 출력하고 `raise typer.Exit(1)`로 종료한다.
|
|
16
|
+
- Registry 미초기화 상태는 `RegistryNotFoundError`로 처리하고 `nxs init` 실행을 안내한다.
|
|
17
|
+
- 성공/경고/오류는 `print_success()` / `print_warning()` / `print_error()` 헬퍼로 구분 출력한다.
|
|
18
|
+
|
|
19
|
+
## 린트/타입 검사
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
uv tool run ruff check . --fix # import 정렬, 미사용 import 등 자동 수정
|
|
23
|
+
uv tool run ruff format . # 포맷 적용
|
|
24
|
+
uv tool run ty check nexus/ # 타입 오류 확인
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
커밋 전 위 세 명령이 오류 없이 통과해야 한다.
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
# 테스트 규칙
|
|
2
|
+
|
|
3
|
+
- 모든 테스트는 `tmp_path` fixture를 사용해 임시 디렉토리에서 실행한다. 실제 `~/.nexus` 경로를 건드리지 않는다.
|
|
4
|
+
- `Registry.DEFAULT_PATH`와 `Registry.NEXUSRC_PATH`는 `monkeypatch`로 패치한다.
|
|
5
|
+
- 새 기능 추가 시 대응하는 단위 테스트를 `tests/`에 추가한다.
|
|
6
|
+
- 테스트 실행: `uv run pytest` (전체), `uv run pytest tests/<file>.py` (개별)
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
pull_request:
|
|
7
|
+
branches: [main]
|
|
8
|
+
|
|
9
|
+
jobs:
|
|
10
|
+
lint:
|
|
11
|
+
name: Lint & Type Check
|
|
12
|
+
runs-on: ubuntu-latest
|
|
13
|
+
|
|
14
|
+
steps:
|
|
15
|
+
- uses: actions/checkout@v4
|
|
16
|
+
|
|
17
|
+
- name: Set up Python 3.11
|
|
18
|
+
uses: actions/setup-python@v5
|
|
19
|
+
with:
|
|
20
|
+
python-version: "3.11"
|
|
21
|
+
|
|
22
|
+
- name: Install uv
|
|
23
|
+
uses: astral-sh/setup-uv@v3
|
|
24
|
+
|
|
25
|
+
- name: Install dependencies
|
|
26
|
+
run: uv pip install -e ".[dev]" --system
|
|
27
|
+
|
|
28
|
+
- name: Install ty
|
|
29
|
+
run: uv pip install ty --system
|
|
30
|
+
|
|
31
|
+
- name: Run ruff (lint + format check)
|
|
32
|
+
run: |
|
|
33
|
+
ruff check .
|
|
34
|
+
ruff format --check .
|
|
35
|
+
|
|
36
|
+
- name: Run ty (type check)
|
|
37
|
+
run: ty check nexus/
|
|
38
|
+
|
|
39
|
+
test:
|
|
40
|
+
name: Test (Python ${{ matrix.python-version }} / ${{ matrix.os }})
|
|
41
|
+
runs-on: ${{ matrix.os }}
|
|
42
|
+
strategy:
|
|
43
|
+
fail-fast: false
|
|
44
|
+
matrix:
|
|
45
|
+
os: [ubuntu-latest, macos-latest]
|
|
46
|
+
python-version: ["3.10", "3.11", "3.12"]
|
|
47
|
+
|
|
48
|
+
steps:
|
|
49
|
+
- uses: actions/checkout@v4
|
|
50
|
+
|
|
51
|
+
- name: Set up Python ${{ matrix.python-version }}
|
|
52
|
+
uses: actions/setup-python@v5
|
|
53
|
+
with:
|
|
54
|
+
python-version: ${{ matrix.python-version }}
|
|
55
|
+
|
|
56
|
+
- name: Install uv
|
|
57
|
+
uses: astral-sh/setup-uv@v3
|
|
58
|
+
|
|
59
|
+
- name: Install dependencies
|
|
60
|
+
run: uv pip install -e ".[dev]" --system
|
|
61
|
+
|
|
62
|
+
- name: Run tests
|
|
63
|
+
run: pytest tests/ -v --cov=nexus --cov-report=term-missing
|
|
64
|
+
|
|
65
|
+
- name: Upload coverage report
|
|
66
|
+
uses: codecov/codecov-action@v4
|
|
67
|
+
if: matrix.os == 'ubuntu-latest' && matrix.python-version == '3.11'
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
repos:
|
|
2
|
+
# ruff: fast Python linter & formatter
|
|
3
|
+
- repo: https://github.com/astral-sh/ruff-pre-commit
|
|
4
|
+
rev: v0.9.10
|
|
5
|
+
hooks:
|
|
6
|
+
- id: ruff
|
|
7
|
+
args: [--fix]
|
|
8
|
+
- id: ruff-format
|
|
9
|
+
|
|
10
|
+
# pytest: run tests before commit
|
|
11
|
+
- repo: local
|
|
12
|
+
hooks:
|
|
13
|
+
- id: pytest
|
|
14
|
+
name: pytest
|
|
15
|
+
entry: pytest tests/ --tb=short -q
|
|
16
|
+
language: system
|
|
17
|
+
pass_filenames: false
|
|
18
|
+
always_run: true
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
# Nexus CLI
|
|
2
|
+
|
|
3
|
+
AI 에이전트(Claude, Gemini, Codex, Cursor, Copilot) 설정을 중앙에서 관리하고 프로젝트별 심볼릭 링크로 적용하는 CLI 프레임워크. CLI 명령어: `nxs`.
|
|
4
|
+
|
|
5
|
+
## 개발 환경 설정
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
# 의존성 설치
|
|
9
|
+
uv sync
|
|
10
|
+
uv sync --extra dev # 개발 의존성 포함
|
|
11
|
+
|
|
12
|
+
# 테스트 실행
|
|
13
|
+
uv run pytest
|
|
14
|
+
uv run pytest tests/test_registry.py # 특정 파일
|
|
15
|
+
uv run pytest -v --cov=nexus # 커버리지 포함
|
|
16
|
+
|
|
17
|
+
# CLI 실행
|
|
18
|
+
uv run nxs --help
|
|
19
|
+
|
|
20
|
+
# 린트/타입 검사
|
|
21
|
+
uv tool run ruff check .
|
|
22
|
+
uv tool run ty check nexus/
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## 핵심 개념
|
|
26
|
+
|
|
27
|
+
| 개념 | 설명 |
|
|
28
|
+
|------|------|
|
|
29
|
+
| **Registry** | `~/.nexus` - 설정의 중앙 저장소. `Registry(base_path)`로 주입 |
|
|
30
|
+
| **Root Config** | `root/agents/<agent>/` - 모든 앱이 상속하는 기본 설정 |
|
|
31
|
+
| **App** | `apps/<app>/` - 프로젝트 단위 설정 묶음. Root를 상속·오버라이드 |
|
|
32
|
+
| **Resolved** | `resolved/<app>/<agent>/` - root + app 병합 결과 (자동 생성) |
|
|
33
|
+
| **Link** | 프로젝트의 `.claude/` 등을 `resolved/` 경로로 심볼릭 링크 |
|
|
34
|
+
|
|
35
|
+
## Registry 디렉토리 구조
|
|
36
|
+
|
|
37
|
+
```
|
|
38
|
+
~/.nexus/
|
|
39
|
+
├── nexus.config.yaml
|
|
40
|
+
├── root/agents/
|
|
41
|
+
│ └── claude/
|
|
42
|
+
│ ├── agent.config.yaml
|
|
43
|
+
│ └── .claude/
|
|
44
|
+
│ ├── CLAUDE.md
|
|
45
|
+
│ └── settings.json
|
|
46
|
+
├── apps/
|
|
47
|
+
│ └── web-frontend/
|
|
48
|
+
│ ├── app.config.yaml
|
|
49
|
+
│ └── agents/
|
|
50
|
+
│ └── claude/
|
|
51
|
+
│ ├── agent.config.yaml
|
|
52
|
+
│ └── .claude/
|
|
53
|
+
│ ├── CLAUDE.md
|
|
54
|
+
│ └── settings.json
|
|
55
|
+
├── resolved/ # nxs resolve로 자동 생성, 레포에 커밋 대상
|
|
56
|
+
│ └── web-frontend/
|
|
57
|
+
│ └── claude/
|
|
58
|
+
│ └── .claude/
|
|
59
|
+
└── links/
|
|
60
|
+
└── links.json
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
## 지원 에이전트
|
|
64
|
+
|
|
65
|
+
| ID | 에이전트 | 링크 대상 |
|
|
66
|
+
|----|----------|-----------|
|
|
67
|
+
| `claude` | Anthropic Claude | `.claude/` |
|
|
68
|
+
| `gemini` | Google Gemini | `.gemini/` |
|
|
69
|
+
| `codex` | OpenAI Codex | `AGENTS.md` |
|
|
70
|
+
| `cursor` | Cursor AI | `.cursorrules` |
|
|
71
|
+
| `copilot` | GitHub Copilot | `.github/copilot-instructions.md` |
|
|
72
|
+
|
|
73
|
+
## CLI 명령어
|
|
74
|
+
|
|
75
|
+
```bash
|
|
76
|
+
nxs init [--path PATH] [--from-repo URL]
|
|
77
|
+
nxs app add <name> / list / show <name> / remove <name>
|
|
78
|
+
nxs agent add <agent> --app <app>|--root
|
|
79
|
+
nxs agent show/list/remove <agent> --app <app>|--root
|
|
80
|
+
nxs resolve <app> / --all / --dry-run
|
|
81
|
+
nxs link <app> [--target PATH] [--agent claude,gemini]
|
|
82
|
+
nxs unlink <app>
|
|
83
|
+
nxs submodule add <app> [--target PATH] [--agent claude,gemini]
|
|
84
|
+
nxs submodule remove <app> [--target PATH] [--agent claude,gemini] [--keep-submodule]
|
|
85
|
+
nxs sync push [--message MSG] / pull / remote set <url>
|
|
86
|
+
nxs status [--app NAME] [--with-links]
|
|
87
|
+
nxs install [--from-repo URL] [--verify] [--apps app1,app2]
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
## 병합 전략
|
|
91
|
+
|
|
92
|
+
| 전략 | 동작 | 기본 대상 |
|
|
93
|
+
|------|------|-----------|
|
|
94
|
+
| `append` | 루트 내용 + 구분선 + 앱 내용 | `.md` 파일 |
|
|
95
|
+
| `deep-merge` | JSON 필드 단위 재귀 병합, 스칼라는 앱이 오버라이드 | `.json` 파일 |
|
|
96
|
+
| `replace` | 앱 내용이 루트를 완전 대체 | 명시적 지정 시 |
|
|
97
|
+
| `prepend` | 앱 내용 앞에 루트 내용 추가 | 명시적 지정 시 |
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: agent-confhub-cli
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: AI 에이전트 설정 중앙 관리 CLI 프레임워크
|
|
5
|
+
Requires-Python: >=3.10
|
|
6
|
+
Requires-Dist: gitpython>=3.1.0
|
|
7
|
+
Requires-Dist: jinja2>=3.1.0
|
|
8
|
+
Requires-Dist: pyyaml>=6.0
|
|
9
|
+
Requires-Dist: rich>=13.0.0
|
|
10
|
+
Requires-Dist: typer>=0.9.0
|
|
11
|
+
Provides-Extra: dev
|
|
12
|
+
Requires-Dist: pre-commit>=3.0; extra == 'dev'
|
|
13
|
+
Requires-Dist: pytest-cov>=4.0; extra == 'dev'
|
|
14
|
+
Requires-Dist: pytest>=7.0; extra == 'dev'
|
|
15
|
+
Requires-Dist: ruff>=0.9.0; extra == 'dev'
|
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
# Nexus CLI (`nxs`)
|
|
2
|
+
|
|
3
|
+
AI 에이전트(Claude, Gemini, Codex, Cursor, Copilot) 설정을 팀 전체에 중앙 관리하는 CLI 프레임워크.
|
|
4
|
+
|
|
5
|
+
## 개념 구조
|
|
6
|
+
|
|
7
|
+
```mermaid
|
|
8
|
+
graph TD
|
|
9
|
+
R["~/.nexus (Registry)"]
|
|
10
|
+
ROOT["root/agents/claude/\n팀 공통 기본 설정"]
|
|
11
|
+
APP["apps/api-server/agents/claude/\n프로젝트별 설정"]
|
|
12
|
+
RESOLVED["resolved/api-server/claude/\n병합 결과 (자동 생성)"]
|
|
13
|
+
REMOTE["nexus-config\n(private git repo)"]
|
|
14
|
+
PROJECT["api-server 프로젝트\n.nexus-config/ (submodule)"]
|
|
15
|
+
SYMLINK[".claude/ 심볼릭 링크"]
|
|
16
|
+
|
|
17
|
+
ROOT -->|"상속 + 오버라이드"| RESOLVED
|
|
18
|
+
APP -->|"nxs resolve"| RESOLVED
|
|
19
|
+
RESOLVED -->|"nxs sync push"| REMOTE
|
|
20
|
+
REMOTE -->|"git submodule"| PROJECT
|
|
21
|
+
PROJECT -->|"nxs submodule init"| SYMLINK
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
## 설치
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
pipx install agent-confhub-cli
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
## 빠른 시작
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
# Registry 초기화
|
|
34
|
+
nxs init
|
|
35
|
+
|
|
36
|
+
# 앱 등록
|
|
37
|
+
nxs app add web-frontend
|
|
38
|
+
|
|
39
|
+
# Claude 에이전트 설정 추가
|
|
40
|
+
nxs agent add claude --app web-frontend
|
|
41
|
+
|
|
42
|
+
# 설정 병합
|
|
43
|
+
nxs resolve web-frontend
|
|
44
|
+
|
|
45
|
+
# 프로젝트에 심볼릭 링크 연결
|
|
46
|
+
nxs link web-frontend --target /workspace/my-project
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
## 주요 명령어
|
|
50
|
+
|
|
51
|
+
| 명령어 | 설명 |
|
|
52
|
+
|--------|------|
|
|
53
|
+
| `nxs init` | Registry 초기화 |
|
|
54
|
+
| `nxs app add/list/show/remove` | 앱 관리 |
|
|
55
|
+
| `nxs agent add/list/show/remove` | 에이전트 설정 관리 |
|
|
56
|
+
| `nxs resolve <app>` | 설정 병합 빌드 |
|
|
57
|
+
| `nxs link <app>` | 프로젝트에 심볼릭 링크 |
|
|
58
|
+
| `nxs unlink <app>` | 링크 해제 |
|
|
59
|
+
| `nxs submodule add <app>` | 프로젝트에 git submodule + sparse-checkout으로 설정 적용 |
|
|
60
|
+
| `nxs submodule init <app>` | 클론 후 sparse-checkout 및 심볼릭 링크 설정 (팀원용) |
|
|
61
|
+
| `nxs submodule remove <app>` | submodule 설정 제거 |
|
|
62
|
+
| `nxs sync push/pull` | Git 동기화 |
|
|
63
|
+
| `nxs status` | Registry 상태 확인 |
|
|
64
|
+
| `nxs install --from-repo <url>` | 회사 레포 설치 |
|
|
65
|
+
|
|
66
|
+
## 지원 에이전트
|
|
67
|
+
|
|
68
|
+
| 에이전트 | 링크 대상 |
|
|
69
|
+
|----------|----------|
|
|
70
|
+
| `claude` | `.claude/` |
|
|
71
|
+
| `gemini` | `.gemini/` |
|
|
72
|
+
| `codex` | `AGENTS.md` |
|
|
73
|
+
| `cursor` | `.cursorrules` |
|
|
74
|
+
| `copilot` | `.github/copilot-instructions.md` |
|
|
75
|
+
|
|
76
|
+
## 팀 공유 워크플로우
|
|
77
|
+
|
|
78
|
+
### 심볼릭 링크 방식 (개인 머신 로컬 적용)
|
|
79
|
+
|
|
80
|
+
```mermaid
|
|
81
|
+
sequenceDiagram
|
|
82
|
+
participant A as 설정 관리자
|
|
83
|
+
participant R as ~/.nexus (Registry)
|
|
84
|
+
participant G as nexus-config (git)
|
|
85
|
+
participant T as 팀원
|
|
86
|
+
|
|
87
|
+
A->>R: nxs app add / nxs agent add
|
|
88
|
+
A->>R: 파일 직접 편집
|
|
89
|
+
A->>R: nxs resolve <app>
|
|
90
|
+
A->>G: nxs sync push
|
|
91
|
+
T->>G: nxs sync pull
|
|
92
|
+
T->>R: nxs resolve --all
|
|
93
|
+
Note over T: 심볼릭 링크로<br/>연결된 프로젝트에 즉시 반영
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
```bash
|
|
97
|
+
# 설정 관리자 - 설정 변경 후 push
|
|
98
|
+
nxs sync push --message "feat: Claude 설정 업데이트"
|
|
99
|
+
|
|
100
|
+
# 팀원 - pull 후 resolve로 로컬 반영
|
|
101
|
+
nxs sync pull && nxs resolve --all
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
### Git Submodule 방식 (sparse-checkout으로 앱 설정만 적용)
|
|
105
|
+
|
|
106
|
+
nexus-config 레포 전체가 아닌 해당 앱의 `resolved/<app>/` 만 체크아웃합니다.
|
|
107
|
+
|
|
108
|
+
```mermaid
|
|
109
|
+
sequenceDiagram
|
|
110
|
+
participant A as 설정 관리자
|
|
111
|
+
participant N as ~/.nexus (Registry)
|
|
112
|
+
participant G as nexus-config (git)
|
|
113
|
+
participant P as api-server 프로젝트
|
|
114
|
+
participant T as 팀원
|
|
115
|
+
|
|
116
|
+
A->>N: nxs app add api-server
|
|
117
|
+
A->>N: nxs agent add claude --app api-server
|
|
118
|
+
A->>N: 파일 직접 편집
|
|
119
|
+
A->>G: nxs submodule add api-server --target ./api-server
|
|
120
|
+
Note over A,G: resolve → push → submodule add<br/>→ sparse-checkout 자동 수행
|
|
121
|
+
A->>P: .nexus-config/ submodule + .claude/ 심볼릭 링크 생성
|
|
122
|
+
A->>P: git push (프로젝트 레포)
|
|
123
|
+
|
|
124
|
+
T->>P: git clone api-server
|
|
125
|
+
T->>P: nxs submodule init api-server
|
|
126
|
+
Note over T,P: sparse-checkout + 심볼릭 링크 자동 설정
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
**설정 관리자 (최초 1회):**
|
|
130
|
+
|
|
131
|
+
```bash
|
|
132
|
+
# 1. Registry를 private 레포와 연결
|
|
133
|
+
nxs sync remote set https://github.com/your-team/nexus-config.git
|
|
134
|
+
|
|
135
|
+
# 2. 앱 및 에이전트 설정 준비
|
|
136
|
+
nxs app add api-server
|
|
137
|
+
nxs agent add claude --app api-server
|
|
138
|
+
# ~/.nexus/apps/api-server/agents/claude/ 에서 직접 파일 편집
|
|
139
|
+
|
|
140
|
+
# 3. 프로젝트에 submodule 적용
|
|
141
|
+
# resolve → remote push → git submodule add → sparse-checkout 자동 수행
|
|
142
|
+
nxs submodule add api-server --target /workspace/api-server
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
**프로젝트 레포에 생성되는 구조:**
|
|
146
|
+
|
|
147
|
+
```
|
|
148
|
+
api-server/
|
|
149
|
+
├── .nexus-config/ ← nexus-config submodule (resolved/api-server/ 만 sparse-checkout)
|
|
150
|
+
├── .claude/ ← symlink → .nexus-config/resolved/api-server/claude/.claude/
|
|
151
|
+
├── .gemini/ ← symlink → .nexus-config/resolved/api-server/gemini/.gemini/
|
|
152
|
+
└── ...
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
개발자는 `.claude/`, `.gemini/` 등 프로젝트 루트의 심볼릭 링크만 사용하면 됩니다. `.nexus-config/` 내부 구조는 신경 쓸 필요 없습니다.
|
|
156
|
+
|
|
157
|
+
**팀원 (레포 클론 후):**
|
|
158
|
+
|
|
159
|
+
```bash
|
|
160
|
+
# 심볼릭 링크는 레포에 이미 커밋되어 있어 별도 생성 불필요
|
|
161
|
+
git clone --recurse-submodules https://github.com/your-team/api-server.git
|
|
162
|
+
cd api-server
|
|
163
|
+
|
|
164
|
+
# sparse-checkout 적용 (resolved/api-server/ 만 체크아웃)
|
|
165
|
+
nxs submodule init api-server
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
**설정 업데이트:**
|
|
169
|
+
|
|
170
|
+
```mermaid
|
|
171
|
+
flowchart LR
|
|
172
|
+
E["파일 직접 편집\n~/.nexus/apps/api-server/..."]
|
|
173
|
+
S["nxs submodule add api-server\n--target ./api-server"]
|
|
174
|
+
GP["git push\n(프로젝트 레포)"]
|
|
175
|
+
T["팀원: git pull\n+ git submodule update\n+ nxs submodule init api-server"]
|
|
176
|
+
|
|
177
|
+
E --> S --> GP --> T
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
```bash
|
|
181
|
+
# ~/.nexus/apps/api-server/agents/claude/ 파일 직접 수정 후
|
|
182
|
+
nxs submodule add api-server --target /workspace/api-server
|
|
183
|
+
# resolve → nexus push → submodule ref + 심볼릭 링크 커밋
|
|
184
|
+
|
|
185
|
+
# 팀원은 프로젝트에서 반영
|
|
186
|
+
git pull && git submodule update
|
|
187
|
+
nxs submodule init api-server # sparse-checkout 재적용
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
## 개발
|
|
191
|
+
|
|
192
|
+
```bash
|
|
193
|
+
uv sync --extra dev
|
|
194
|
+
pytest tests/ -v
|
|
195
|
+
```
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
"""Nexus CLI - 진입점 모듈"""
|
|
2
|
+
|
|
3
|
+
from pathlib import Path
|
|
4
|
+
|
|
5
|
+
import typer
|
|
6
|
+
|
|
7
|
+
from nexus import __version__
|
|
8
|
+
from nexus.commands import agent as agent_cmd
|
|
9
|
+
from nexus.commands import app as app_cmd
|
|
10
|
+
from nexus.commands.link import link_app
|
|
11
|
+
from nexus.commands.submodule import submodule_app
|
|
12
|
+
from nexus.commands.sync import sync_app
|
|
13
|
+
|
|
14
|
+
app = typer.Typer(
|
|
15
|
+
name="nxs",
|
|
16
|
+
help="Nexus CLI - AI 에이전트 설정 관리",
|
|
17
|
+
add_completion=False,
|
|
18
|
+
)
|
|
19
|
+
|
|
20
|
+
app.add_typer(app_cmd.app, name="app")
|
|
21
|
+
app.add_typer(agent_cmd.app, name="agent")
|
|
22
|
+
app.add_typer(link_app, name="link")
|
|
23
|
+
app.add_typer(submodule_app, name="submodule")
|
|
24
|
+
app.add_typer(sync_app, name="sync")
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def version_callback(value: bool):
|
|
28
|
+
"""버전 정보 출력 콜백"""
|
|
29
|
+
if value:
|
|
30
|
+
typer.echo(f"nexus-cli version: {__version__}")
|
|
31
|
+
raise typer.Exit()
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
@app.callback()
|
|
35
|
+
def main(
|
|
36
|
+
version: bool | None = typer.Option(
|
|
37
|
+
None,
|
|
38
|
+
"--version",
|
|
39
|
+
"-v",
|
|
40
|
+
help="현재 버전을 출력합니다.",
|
|
41
|
+
callback=version_callback,
|
|
42
|
+
is_eager=True,
|
|
43
|
+
),
|
|
44
|
+
):
|
|
45
|
+
"""Nexus CLI - AI 에이전트 설정 중앙 관리 프레임워크"""
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
@app.command("init")
|
|
49
|
+
def init_command(
|
|
50
|
+
path: Path | None = typer.Option(None, "--path", "-p", help="Registry 경로"),
|
|
51
|
+
from_repo: str | None = typer.Option(None, "--from-repo", help="Git 레포 URL에서 초기화"),
|
|
52
|
+
):
|
|
53
|
+
"""Nexus Registry를 초기화합니다."""
|
|
54
|
+
from nexus.commands.init import do_init
|
|
55
|
+
|
|
56
|
+
do_init(path, from_repo)
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
@app.command("resolve")
|
|
60
|
+
def resolve_command(
|
|
61
|
+
app_name: str | None = typer.Argument(None, help="앱 이름 (생략시 --all 필요)"),
|
|
62
|
+
all_apps: bool = typer.Option(False, "--all", "-a", help="모든 앱 빌드"),
|
|
63
|
+
dry_run: bool = typer.Option(False, "--dry-run", help="결과 미리보기 (파일 미생성)"),
|
|
64
|
+
):
|
|
65
|
+
"""설정을 병합하여 resolved 디렉토리에 저장합니다."""
|
|
66
|
+
from nexus.commands.resolve import do_resolve
|
|
67
|
+
|
|
68
|
+
do_resolve(app_name, all_apps, dry_run)
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
@app.command("unlink")
|
|
72
|
+
def unlink_command(
|
|
73
|
+
app_name: str = typer.Argument(..., help="앱 이름"),
|
|
74
|
+
target: Path | None = typer.Option(
|
|
75
|
+
None, "--target", "-t", help="링크 해제할 프로젝트 경로 (기본: 현재 디렉토리)"
|
|
76
|
+
),
|
|
77
|
+
agent: str | None = typer.Option(
|
|
78
|
+
None, "--agent", help="특정 에이전트만 해제 (쉼표 구분: claude,gemini)"
|
|
79
|
+
),
|
|
80
|
+
):
|
|
81
|
+
"""프로젝트의 심볼릭 링크를 해제합니다."""
|
|
82
|
+
from nexus.commands.link import do_unlink
|
|
83
|
+
|
|
84
|
+
do_unlink(app_name, target, agent)
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
@app.command("status")
|
|
88
|
+
def status_command(
|
|
89
|
+
app_name: str | None = typer.Option(None, "--app", help="특정 앱 이름"),
|
|
90
|
+
with_links: bool = typer.Option(False, "--with-links", help="링크 상태 포함"),
|
|
91
|
+
):
|
|
92
|
+
"""Registry 상태를 표시합니다."""
|
|
93
|
+
from nexus.commands.status import do_status
|
|
94
|
+
|
|
95
|
+
do_status(app_name, with_links)
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
@app.command("install")
|
|
99
|
+
def install_command(
|
|
100
|
+
from_repo: str | None = typer.Option(None, "--from-repo", help="Git 레포 URL에서 설치"),
|
|
101
|
+
verify: bool = typer.Option(False, "--verify", help="설치 상태 확인"),
|
|
102
|
+
apps: str | None = typer.Option(
|
|
103
|
+
None, "--apps", help="특정 앱만 설치 (쉼표 구분: web-frontend,api-server)"
|
|
104
|
+
),
|
|
105
|
+
):
|
|
106
|
+
"""Git 레포에서 Registry를 설치합니다."""
|
|
107
|
+
from nexus.commands.install import do_install
|
|
108
|
+
|
|
109
|
+
do_install(from_repo, verify, apps)
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
if __name__ == "__main__":
|
|
113
|
+
app()
|
|
File without changes
|