npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@cvprun/cli

v0.1.0

Published

CVP command-line interface

Readme

@cvprun/cli

CVP 에이전트 CLI. 로컬 머신을 CVP 플랫폼의 에이전트로 연결하고, 명령별 기능(현재: modbus-monitor)을 웹 UI와 실시간으로 연동합니다.

요구 사항

  • Node.js 22 이상 (전역 WebSocket 사용)

사용

npx @cvprun/cli <token> <command> [options]

<token>은 웹 UI에서 에이전트 생성 시 표시되는 결합 토큰 (cvp_..._<agent-id>)을 그대로 사용합니다.

npx @cvprun/cli cvp_xxxx..._<agent-id> modbus-monitor

전역 설치 시에는 cvp 명령으로 실행합니다.

npm install -g @cvprun/cli
cvp <token> modbus-monitor

명령

| 명령 | 설명 | | ------------------ | ---------------------------------------------------- | | modbus-monitor | Modbus 클라이언트(monitor)로 접속해 외부 장치를 폴링 | | modbus-simulator | Modbus TCP 서버(simulator)를 기동 | | schedule | 등록된 cron 스케줄을 로컬에서 실행 | | rfdetr | RF-DETR 비전 모델 추론/학습 서버로 대기 | | sam2 | SAM2 세그멘테이션(매직 완드) 서버로 대기 | | train | 훈련 위저드 학습 러너로 대기 (rfdetr 어댑터) | | ytdlp | yt-dlp 동영상 다운로드 러너로 대기 |

명령에 따라 에이전트가 담당하는 connector 모드가 달라지고, 웹 UI의 에이전트 Modbus 화면도 실행 중인 명령에 맞는 탭을 기본으로 보여줍니다.

명령별 실행 권한은 웹 UI의 에이전트 상세 → 권한 탭에서 제어합니다. 차단된 명령으로 접속하면 /connect403 command_disabled로 거부하고 CLI는 안내 메시지를 출력한 뒤 종료합니다 (이미 실행 중인 명령은 재시작 시점부터 적용).

옵션

| 옵션 | 설명 | | -------------- | ---------------------------------------------------------------- | | --url <base> | API 베이스 URL (기본: $CVP_API_URL 또는 https://app.cvp.run) | | --help | 도움말 출력 | | --version | 버전 출력 |

콘솔 로그 적재 (모든 명령 공통)

  • 콘솔 로그는 로컬 ~/.cache/cvp/logs/<agentId>/YYYY-MM-DD.log (JSONL, UTC 날짜, 최근 14일 보관)에 기록되고, 30초 주기로 해당 일자 파일 전체를 콘솔과 같은 ANSI 컬러 라인으로 렌더해 PUT /api/agents/:id/logs/:date 로 업로드합니다.
  • 서버는 프로젝트 스토리지의 Agents/<에이전트 UUID>/logs/<YYYY>/<MM>/<DD>.log 키에 덮어쓰므로, '프로젝트 > 파일' 페이지와 에이전트 상세의 '로그' 탭에서 그대로 조회됩니다. 업로드 실패 시 다음 주기에 재시도합니다.

리소스 모니터링 (모든 명령 공통)

에이전트 상세 페이지의 '리소스' 탭에 실시간 시스템 지표를 보냅니다. 어떤 명령을 실행 중이든 켜지며, 별도 설정이 없습니다.

  • 수집 항목 — CPU(전체·코어별 사용률, load1), 메모리(+swap), 디스크(마운트 용량·읽기/쓰기 처리율), 네트워크(수신/송신 처리율), 온도, NVIDIA GPU(사용률· VRAM·온도·전력).
  • 플랫폼 제약 — CPU·메모리·디스크 용량은 모든 OS 에서 동작합니다. 디스크 I/O(/proc/diskstats)·네트워크(/proc/net/dev)·온도(/sys/class/thermal, /sys/class/hwmon)는 Linux 전용이고, GPU 는 nvidia-smi 가 PATH 에 있을 때만 수집합니다. 수집할 수 없는 항목은 UI 가 패널째 숨깁니다.
  • 런타임 의존성 없음 — Node 내장 API 와 /proc·/sys 파싱, nvidia-smi 서브프로세스만 씁니다. nvidia-smi 가 없으면 첫 시도의 ENOENT 이후 다시 실행하지 않습니다.
  • 샘플링과 송신은 별개 — 2초마다 샘플을 떠서 약 30분치 링버퍼(900개)를 채우는 일은 항상 하지만, WebSocket 송신은 UI 구독이 살아 있을 때만 합니다. 구독은 UI 가 sys.subscribe 를 다시 보내 갱신하는 90초짜리 lease 라서, 브라우저가 탭을 닫으며 사라져도 스트림이 자동으로 멎습니다.
  • 히스토리는 서버에 저장하지 않습니다. 대시보드를 열면 링버퍼를 백필로 한 번 받아 과거 구간을 채우므로, 볼 수 있는 최대 구간이 그 30분입니다.

modbus 계열 명령 동작

  • modbus-monitor (monitor): 설정된 외부 Modbus TCP 장치를 영역별 pollMs 주기로 폴링하여 변경분을 UI에 전파합니다 (읽기 전용).
  • modbus-simulator (simulator): 설정된 포트에 실제 Modbus TCP 서버를 띄웁니다. 외부 Modbus 클라이언트의 쓰기와 UI의 셀 편집이 모두 레지스터에 반영되고, 구독 중인 UI에 델타로 전파됩니다. 레지스터는 시드 값으로 초기화됩니다.
  • connector 설정 변경/활성화 토글은 약 10초 주기로 자동 반영됩니다.

rfdetr 명령 동작

RF-DETR(Apache-2.0)의 추론/학습 서버로 대기합니다. 객체 탐지 · 인스턴스 세그멘테이션 · 키포인트 세 태스크를 모두 지원하며, 웹 UI의 에이전트 → 어플리케이션 → RF-DETR 화면과 실시간으로 연동됩니다.

  • 최초 실행 시 uv로 격리된 Python 3.11 환경을 ~/.cache/cvp/rfdetr/에 준비하고 rfdetr 패키지를 설치합니다 (torch 포함 — 수 분이 걸릴 수 있습니다).
  • 모델 다운로드: 사전학습 가중치는 사용자가 UI 모델 탭에서 명시적으로 받습니다. 추론·학습은 가중치가 없으면 자동으로 받지 않고 weights_missing 으로 되돌려 보냅니다 — 수백 MB 다운로드가 요청 안에서 조용히 일어나면 화면이 멈춘 것처럼 보이기 때문입니다. URL·MD5 는 rfdetr 의 ModelWeights 레지스트리에서 가져오며, 받은 뒤 MD5 대조와 torch 판독까지 확인합니다.
  • 추론: UI가 지정한 모델(사전학습 variant 또는 파인튜닝 실행)로 추론하고, 태스크에 따라 박스 · 마스크 폴리곤 · 키포인트를 회신합니다. 모델은 프로세스에 상주하며, 다른 모델이 요청되면 워커를 다시 띄웁니다.
  • 학습: UI에서 선택한 CVP 이미지 데이터셋을 태스크에 맞는 COCO 포맷으로 내려받아(세그멘테이션은 폴리곤만, 키포인트는 클래스 스켈레톤을 categories[].keypoints/skeleton 으로) 시드 결정적으로 train/valid 분할 후 파인튜닝합니다. 에폭 진행률과 로그가 UI로 중계되고, 완료된 가중치는 즉시 추론에 사용할 수 있습니다.
  • 학습 취소 시 SIGINT → SIGTERM → SIGKILL 순으로 에스컬레이션하며, GPU(CUDA)가 없으면 CPU로 동작합니다.
  • 모델·데이터셋·실행 결과는 모두 ~/.cache/cvp/rfdetr/ 아래에 있습니다 (CVP_RFDETR_DIR 로 재정의 가능). rfdetr/DINOv2 의 자체 캐시(RF_HOME, HF_HOME)도 이 디렉토리 안으로 묶어 두었으므로 이 하나만 지우면 정리됩니다.

sam2 명령 동작

SAM2(Apache-2.0) 세그멘테이션 모델의 추론 서버로 대기합니다. 라벨링 에디터의 매직 완드(W)가 연결된 sam2 에이전트를 우선 사용해 토큰 차감 없이 자동 세그멘테이션을 수행합니다 (에이전트가 없으면 클라우드 provider 로 폴백 — 세그멘테이션 provider 가이드).

  • 최초 실행 시 uv로 격리된 Python 3.11 환경을 ~/.cache/cvp/sam2/에 준비하고 sam2 패키지를 설치합니다 (torch 포함 — 수 분이 걸릴 수 있습니다).
  • 체크포인트는 Hugging Face Hub facebook/sam2.1-hiera-small 기본이며 CVP_SAM2_MODEL 환경변수로 재정의할 수 있습니다.
  • 추론 요청의 샘플 이미지는 에이전트 토큰으로 내려받아 로컬 캐시하고, 같은 이미지의 연속 클릭은 상주 워커의 임베딩 캐시로 빠르게 처리합니다.
  • GPU(CUDA)가 없으면 CPU로 동작합니다.

train 명령 동작

프로젝트의 훈련 위저드(/proj/:id/experiments)가 발사한 학습 run 을 실행하는 러너로 대기합니다. 동작 흐름:

  • 위저드가 launch 하면 서버가 WS 로 train.start {run_id} 를 보냅니다. 러너는 agent 토큰으로 /api/agents/:id/runs/:runId/job 을 호출해 잡을 claim 하고 스펙(프레임워크·모델·데이터셋·하이퍼파라미터)을 받습니다.
  • 프레임워크 어댑터가 학습을 수행합니다. MVP 는 rfdetr 어댑터 하나로, 기존 rfdetr 명령의 데이터 준비/가중치/트레이너 모듈을 그대로 재사용합니다 (위저드 컨텍스트에서는 베이스 가중치가 없으면 자동으로 내려받습니다).
  • 상태·진행률·메트릭·로그는 전부 REST 로 서버에 보고합니다(메트릭은 서버가 MLflow 로 프록시). train.cancel 또는 하트비트 응답의 stop_requested 로 graceful 종료(SIGINT→SIGTERM→SIGKILL)를 트리거합니다.
  • 동시 학습은 1개이며, 결과 상태는 종료 경로와 무관하게 항상 보고됩니다.

ytdlp 명령 동작

프로젝트 화면에서 요청한 동영상 다운로드 잡을 실행하는 러너로 대기합니다. 동작 흐름:

  • 사용자가 URL 을 넣으면 서버가 잡 행을 만들고 WS 로 ytdlp.start {job_id} 를 보냅니다. WS 는 깨우기 신호일 뿐이므로, 러너는 접속 직후와 잡 종료 직후에 /api/agents/:id/ytdlp/jobs/next 를 확인해 오프라인 동안 쌓인 큐도 소화합니다.
  • 잡을 claim 하면 ~/.cache/cvp/ytdlp/ 에 uv venv 를 만들고 yt-dlp 를 설치합니다 (torch 가 없어 준비가 빠릅니다). ffmpeg 는 PATH → imageio-ffmpeg 정적 바이너리 순으로 찾고, 둘 다 없으면 병합이 필요한 화질/오디오 프리셋을 거절합니다 (CVP_YTDLP_FFMPEG 로 경로를 고정할 수 있습니다).
  • 다운로드 옵션은 허용리스트로 검증합니다. --exec·--external-downloader· -o/-P·--cookies 등 임의 명령 실행이나 출력 경로 탈취가 가능한 인자는 목록에 없어 자동 거부되며, 출력 경로는 항상 잡 전용 작업 디렉토리로 강제됩니다.
  • 각 항목은 다운로드 → 프로젝트 '파일' 페이지로 업로드 → 로컬 파일 삭제 순으로 처리합니다. 업로드는 멀티파트이고 러너는 파일 이름만 보냅니다 — 최종 스토리지 키는 서버가 잡의 대상 폴더 안에서 정합니다.
  • 상태·진행률·항목·로그는 전부 REST 로 보고합니다. ytdlp.cancel 또는 하트비트 응답의 stop_requested 로 graceful 종료(SIGINT→SIGTERM→SIGKILL)를 트리거합니다.
  • 동시 다운로드는 1개이며, 결과 상태는 종료 경로와 무관하게 정확히 한 번 보고됩니다. 재생목록에서 일부 항목만 성공하면 partial 로 마감합니다.

라이브러리로도 사용할 수 있습니다.

import {AgentClient, parseAgentToken, runModbusCommand} from '@cvprun/cli';

개발

이 패키지는 모노레포 루트(app.cvp.run)의 npm workspace로 관리됩니다. 루트에서 npm install을 한 번 실행하면 의존성이 함께 설치/링크됩니다. 빌드는 루트에서 워크스페이스 플래그로 실행합니다.

npm run build -w @cvprun/cli   # Vite 번들 + 타입 선언을 dist/ 로 출력
npm run dev   -w @cvprun/cli   # watch 모드 빌드

테스트

CLI 테스트는 루트의 jsdom 스위트와 분리된 node 환경 vitest 설정 (cli/vitest.config.ts)으로 실행합니다.

npm run test:cli:run   # 루트에서 실행 (watch: npm run test:cli)
  • 테스트·src/testing/ 하네스는 tsconfig.json exclude 로 dist 선언 출력에서 제외되며, 타입 검사는 tsconfig.test.json(빌드 스크립트에 포함)이 담당합니다.
  • 모든 테스트는 OS tmp 의 mkdtemp 하위에서만 파일을 만들고(makeTempDir), ephemeral 포트(0)만 사용하며, onTestFinished 로 리소스를 정리합니다. 2회 연속 실행해도 결과가 같아야 하고 저장소를 오염시키면 안 됩니다.

공용 테스트 하네스 (src/testing/)

| 모듈 | 용도 | | ---------------- | -------------------------------------------------------------------------- | | fake-websocket | 전역 WebSocket 주입형 in-memory 소켓 (open/message/close 를 테스트가 구동) | | fake-fetch | /api/agents/... 등 HTTP 라우트 스텁 + 호출 기록 | | tempdir | mkdtemp 임시 디렉토리 + 자동 삭제 | | env | 환경변수 설정/자동 복원 (CVP_RFDETR_DIR, CVP_UV_BIN 등) | | modbus-client | 시뮬레이터 loopback 검증용 초소형 Modbus TCP 클라이언트 | | fake-rfdetr | 실제 uv/Python 없이 @@CVP@@ 프로토콜을 재현하는 가짜 uv/python | | fake-sam2 | sam2 앱용 가짜 uv/python (fake-rfdetr 의 uv 재사용) | | fake-ytdlp | ytdlp 앱용 가짜 uv/python/ffmpeg (fake-rfdetr 의 uv 재사용) |

에이전트 앱 추가 시 테스트 체크리스트

새 앱(명령)을 추가할 때 다음을 반드시 갖춥니다.

  1. 프로토콜 동기화cli/src/protocol.tssrc/worker/lib/agent-protocol.ts 양쪽에 메시지 타입을 추가한다. protocol.sync.test.ts가 두 파일의 MessageType/CloseCode 불일치를 잡아준다 (한쪽만 고치면 실패).
  2. capability 등록 — 명령 이름과 같은 capability 를 agent.hello 로 광고하고, worker agent-socket.tsUI_TO_CVPA 화이트리스트에 UI → 에이전트 방향 메시지 타입을 추가한다 (누락 시 UI 소켓이 4102 로 끊김). 에이전트 → UI 브로드캐스트는 webSocketMessage팬아웃 접두사 조건 (modbus./log./rfdetr./sam2. ...)에 새 앱 접두사를 추가해야 동작하고, handleUiMessage 의 오프라인 오류 회신 매핑에도 앱별 error 타입 분기를 추가한다.
  3. 앱 코어 단위 테스트 — 순수 로직(파서/프레임/상태)은 fake 프로세스· in-memory 하네스로 검증한다. 무거운 외부 도구(Python 패키지 등)는 절대 실제로 설치/실행하지 않는다 (fake-rfdetr 패턴 참조).
  4. 명령 계층 테스트commands/<app>.test.ts에서 fake WS/fetch 로 명령 전체를 구동해 envelope 핸들링·오류 회신·log.subscribe·terminal close 종료(타이머/프로세스 정리)를 검증한다 (commands/modbus.test.ts 패턴). 로그 배선은 attachLogStream(client, logHub, agentId) 공용 헬퍼를 쓴다 (log.subscribe 스냅샷·log.history 파일 조회·*.log 기록·브로드캐스트 포함 — handleEnvelope 에서 두 타입을 헬퍼로 위임하면 끝). 리소스 모니터링도 같은 방식이다 — attachSysMonitor(client) 를 붙이고 capabilities 에 SYS_CAPABILITY 를 넣은 뒤, handleEnvelope 에서 sys.subscribe/sys.unsubscribe/sys.history 를 헬퍼로 넘기고 shutdown 에 sysMonitor.stop() 을 추가한다. 빠뜨리면 그 명령으로 실행한 에이전트만 리소스 탭이 비어 보인다.
  5. worker 측 테스트 — 새 서버 엔드포인트는 src/worker/api/agents.test.ts 패턴(Hono 직접 호출 + testing/supabase-stub)으로 토큰 가드·프로젝트 격리를 검증하고, 중계 규칙은 agent-socket.test.ts에 추가한다.
  6. DB — 새 RPC 는 pgTAP(90-tests.sql)과 api 래퍼 동기화 절차를 따른다 (docs/rules/directory-rules/api.md).

게시

files: ["dist"] 설정으로 이 디렉토리의 dist/ npm에 업로드됩니다 (npm 이 package.json·README.md·LICENSE 는 항상 함께 포함합니다).

prepublishOnly가 게시 직전에 build:publish를 실행합니다. 이 스크립트는 vite build --mode publish로 빌드하므로 일반 build와 달리 소스맵을 만들지 않습니다 — 배포본에 원본 TypeScript 소스가 실려 나가지 않게 하려는 것입니다. 로컬 build/dev는 디버깅용 소스맵을 그대로 남깁니다.

버전의 단일 원천은 package.jsonversion입니다. 빌드 시 vite definesrc/version.ts__CLI_VERSION__을 문자열로 치환하므로, 릴리스할 때는 package.json의 버전만 올리면 됩니다(런타임에 package.json을 읽지 않습니다).

npm version patch -w @cvprun/cli   # 버전 상향 (원천은 package.json 하나)
npm publish -w @cvprun/cli         # scoped public 패키지로 게시

게시 후에는 npx @cvprun/cli@latest <token> [command]로 실행합니다. bin 항목이 cvp 하나뿐이므로 npx 는 패키지명과 실행 파일명이 달라도 그대로 cvp를 실행합니다.

라이선스

CVP License — CVP 서비스 이용 목적의 사용만 허용하는 독점 라이선스입니다.