감지
디렉터리를 훑어 빌드 가능한 하위 프로젝트를 모두 찾고 11개 타입 중 하나로
분류합니다. detect --json으로 결과만 받아볼 수도 있습니다.
프로젝트 종류가 무엇인지, 무엇이 무엇보다 먼저 빌드돼야 하는지 UBS가 알아냅니다. 설정 파일은 만들지 않습니다.
Flutter · Tauri · Android/Kotlin · React/Node · iOS/Xcode · Godot — 11개 프로젝트 타입을 파일시스템 신호만으로 구분합니다.
빌드가 시작되기 전에 무엇이 어떤 순서로 돌지 먼저 볼 수 있습니다. 감지와 계획은 아무것도 바꾸지 않습니다.
디렉터리를 훑어 빌드 가능한 하위 프로젝트를 모두 찾고 11개 타입 중 하나로
분류합니다. detect --json으로 결과만 받아볼 수도 있습니다.
프로젝트 사이 의존성을 위상 정렬해 층으로 나누고, 각 프로젝트에 실제로 실행될
명령을 그대로 보여줍니다. plan은 읽기 전용입니다.
층마다 독립 프로젝트를 병렬로, 충돌하는 프로젝트는 직렬로 돌립니다. 성공하면 한 줄, 실패하면 마지막 2 MiB 로그를 그대로 다시 보여줍니다.
설정 파일에 적어 주는 것이 아니라, 아래 파일이 있는지로 판정합니다. 더 구체적인 신호가 있으면 그쪽이 이깁니다.
| 타입 | 감지 신호 | 빌드 산출물 |
|---|---|---|
| flutter | pubspec.yaml의 flutter: 항목 |
AAB · APK · IPA · PKG · Web |
| tauri | src-tauri/tauri.conf.json |
.app · 서명된 .pkg (macOS) |
| android | Android 플러그인을 쓰는 Gradle 프로젝트 | :app:bundleRelease 산출물 |
| kotlin-multiplatform | KMP 플러그인을 쓰는 Gradle 프로젝트 | Gradle build 산출물 |
| kotlin | Kotlin Gradle 프로젝트 (Android·KMP 아님) | Gradle build 산출물 |
| gradle | build.gradle(.kts) · gradlew |
Gradle build 산출물 |
| react | package.json의 React 의존성 |
build 스크립트 산출물 |
| next | package.json의 Next.js 의존성 |
build 스크립트 산출물 |
| node | build 스크립트가 있는 package.json |
build 스크립트 산출물 |
| ios-xcode | Flutter·Tauri 래퍼가 없는 *.xcodeproj |
Release 아카이브 · 내보낸 산출물 |
| godot | project.godot |
export_presets.cfg의 프리셋별 릴리스 export |
빌드만 돌리는 스크립트가 아니라, 릴리스 한 번이 끝날 때까지 필요한 단계를 같은 명령 안에 둡니다.
Node 워크스페이스·패키지 이름에서 의존성을 추론하고, ubs.dependencies.json으로
직접 선언할 수도 있습니다. 순환은 빌드 시작 전에 거부합니다. 병렬 수는 논리
CPU의 절반(최대 4)이 기본값입니다.
빌드하지 않고 설정만 검사합니다. Flutter의 --obfuscate,
Tauri의 Cargo lto/strip, Android의 R8·리소스 축소,
Xcode Release 최적화·심볼 스트립, Godot의 PCK 암호화까지 항목별로 봅니다.
.ipa/.pkg는 App Store Connect로,
.aab는 Google Play의 internal·alpha·beta·production
트랙으로 올립니다. Google 클라이언트 라이브러리 없이 서비스 계정 JWT를 직접
만들어 씁니다.
업데이트 매니페스트의 ECDSA-P256 서명을 설치 시점에 로컬 디스크에 박아 둔 공개키로 검증하고, 파일별 해시를 확인해 스테이징한 뒤 한 번에 교체합니다. 어느 단계가 실패해도 적용한 파일을 전부 되돌립니다.
같은 코어를 stdio MCP 서버로 노출합니다. 기본은 읽기 전용
(detect·audit·plan·graph·update_check)
이고, 실제 빌드는 서버의 UBS_MCP_ALLOW_BUILD=true와 호출의
confirm=true가 둘 다 있어야 돌아갑니다.
같은 엔진 위에 올린 Tauri 2 창. OS WebView와 순수 HTML/CSS/JS만 쓰고, React·Vite·
로컬 웹서버·분석 도구·원격 자산이 없습니다. GUI 빌드는 항상
--non-interactive --no-publish로 실행됩니다.
UBS_NON_INTERACTIVE=true로 질문 없이 돌고,
--report-json으로 계획이 아닌 실제 결과를 파일로 남깁니다.
--fail-fast는 첫 실패에서 멈추고, 기본값은 독립 프로젝트를 계속
진행합니다.
오류 · 진행 · 메뉴 · --help가 ko·en·ja·zh로
나옵니다. 환경변수가 비어 있으면 macOS에서는 시스템 언어까지 확인합니다 —
IDE나 에이전트에서 실행해도 한국어 Mac이 영어로 뒤집히지 않습니다.
Python 3.9 이상만 있으면 됩니다. 설치 스크립트는 관리 파일 전부를 스테이징하고 체크섬을 검증한 뒤 한 트랜잭션으로 적용하며, 실패하면 전부 되돌립니다.
$ curl -fsSL https://raw.githubusercontent.com/Claude-Personal/ubs/main/install.sh | bash
$ curl -fsSL https://raw.githubusercontent.com/Claude-Personal/ubs/main/install.sh -o install.sh
$ gh attestation verify install.sh \
--repo Claude-Personal/ubs \
--signer-workflow Claude-Personal/ubs/.github/workflows/attest-release.yml
$ bash install.sh
# 현재 폴더 아래를 전부 감지해 안전한 기본값으로 빌드
$ ./build.sh
# 아무것도 빌드하지 않고, 무엇이 돌지만 확인
$ ./build.sh --dry-run --all
# CI: 질문 없이 patch 올리고 병렬로, 결과를 JSON으로
$ UBS_NON_INTERACTIVE=true ./build.sh --all \
--version-bump patch --jobs 4 --report-json report.json
# 부작용 없이 들여다보기
$ ./build.sh detect --json
$ ./build.sh audit --json
$ ./build.sh graph --json
설치 스크립트와 자체 업데이트는 서로 다른 신뢰 기반을 씁니다 — 첫 설치는 GitHub
채널 자체가 신뢰 기반이고, 설치 이후의 update는 이미 로컬에 있는
공개키로 검증합니다. 그래서 첫 설치 때만 위 attestation 검증을 한 번 해두는 것을
권합니다. 자세한 설명과 공개키 지문은
README의 Security 절에
있습니다.
빌드 도구가 프로젝트에 더 얹는 것을 줄이는 쪽으로 결정했습니다.
감지에 필요한 설정 파일이 없습니다. 의존성을 직접 선언하고 싶을 때만
ubs.dependencies.json을 씁니다.
Python 3.9 외에 설치할 것이 없습니다. MCP 서버도 의존성이 없고, Rust 헬퍼는 선택이며 없으면 순수 Python 경로로 대체됩니다.
모든 어댑터가 릴리스 경로만 씁니다. Godot은 디버그 export 템플릿을 아예 쓰지 않고, Flutter는 난독화·심볼 분리·아이콘 트리셰이킹을 켠 릴리스로 굽습니다.
릴리스 도구가 조용히 해서는 안 되는 일이라고 판단한 것들입니다.