Communitygithub.com

host0: AI 에이전트로 앱/사이트 배포

host0을 사용하면 AI 에이전트가 만든 웹사이트와 앱을 몇 초 만에 라이브 URL로 게시할 수 있습니다. 폴더 하나를 게시하면 https://{slug}.host0.app 형태의 URL이 생성되며, 기본적으로 비공개이고, 원하는 사람에게만 링크로 공유(unlisted)하거나 웹에 공개할 수 있습니다.

사이트 배포란 무엇인가요?

host0은 AI 에이전트(Claude Code, Cursor, Codex 등)가 만든 결과물을 즉시 호스팅할 수 있는 플랫폼입니다. HTML, PDF, 이미지, 마크다운 등 어떤 파일이든 폴더째로 게시하면 랜덤 슬러그의 라이브 URL이 생성됩니다. 정적 파일뿐 아니라 `h0.json` 파일로 레코드 컬렉션을 선언하면 서버 코드 없이 동일한 오리진에서 공유 데이터베이스를 사용할 수 있어, 작은 팀 도구(할 일 목록, 트래커, 신청 시트)를 만드는 데 유용합니다. 게시된 앱은 기본적으로 비공개이며, `--visibility link` 옵션으로 링크를 아는 모든 사람이 볼 수 있도록(unlisted) 설정하거나 `--visibility public`으로 검색 엔진에 노출할 수 있습니다. 또한 버전 관리와 롤백, URL 변경, 초대 기능을 제공하며, 베타 기간 동안 무료로 사용할 수 있습니다(하단에 'Hosted on host0' 배지 표시).

지원 대상✓Claude Code✓Codex CLI✓Cursor✓Gemini CLI
npx skills add https://github.com/host0-ai/skills/tree/HEAD/skills/host0

즐겨 사용하는 AI에게 물어보기

이 에이전트 스킬이 미리 로드된 새 채팅을 엽니다.

문서

host0

host0은 AI 에이전트가 만든 모든 것(HTML, 사이트, 공유 데이터베이스가 있는 앱, 마크다운, PDF 등)을 구글 문서처럼 쉽게 공유할 수 있는 링크로 호스팅합니다. 모든 에이전트와 호환됩니다.

핵심 개념은 앱입니다: 파일이나 폴더(정적 파일 디렉토리, 또는 브라우저에서 열리는 단일 파일(PDF, 이미지, 단일 HTML 페이지, 비디오, 오디오, 마크다운, CSV, 텍스트)를 게시하면 https://{slug}.host0.app/ (로컬 개발: http://{slug}.localhost:3000/) 형태의 라이브 URL을 얻습니다. 압축 파일이나 다운로드 전용 파일은 거부됩니다(zip 파일은 압축을 풀고 폴더를 게시하세요). 모든 앱은 기본적으로 비공개입니다 — 소유자(host0에 로그인한 사용자)와 이메일로 초대된 사람만 열 수 있습니다. URL을 아는 모든 사람이 (로그인 없이, unlisted 상태로, 색인되지 않음) 열 수 있도록 하려면 --visibility link를 사용합니다. --visibility public은 한 단계 더 나아가 웹에서 공개되고 검색 엔진이 색인할 수 있도록 하며, 사용자가 검색에서 찾을 수 있길 원하는 경우에만 사용합니다. 새 앱의 URL은 랜덤(k3x9q2m7ta.host0.app)이며, 사용자가 더 보기 좋은 링크를 원할 때는 읽기 좋은 이름(team-todo.host0.app)으로 변경할 수 있습니다 (아래 "URL 이름 변경" 참조).

앱은 공유 데이터도 보유할 수 있습니다: h0.json 파일에 레코드 컬렉션을 선언하면 프론트엔드가 동일한 오리진에서 데이터베이스를 얻을 수 있으며, 서버 코드가 필요하지 않습니다. 아래 "공유 데이터"를 참조하세요 — 이것이 페이지를 팀이 함께 사용하는 도구로 바꾸는 방법입니다.

현재 문서

전체 문서는 **https://host0.ai/docs**에 있습니다 — 사용자가 특정 기능의 작동 방식이나 가능 여부를 물어보거나, 지원되지 않는 기능이 있다고 말하기 전에 문서를 읽어보세요.

API는 스스로를 설명합니다. 기계가 읽을 수 있는 인덱스:

curl -sS {base}/api/v1

이 명령어는 현재 엔드포인트 목록, 파일 제한, 플랫폼 계약(host0이 현재 제공하는 것)을 반환합니다. API 키(-H "authorization: bearer $HOST0_API_KEY")를 보내면 limits와 plan은 사용자 자신의 것입니다 — 제한은 계정의 플랜에 따라 다릅니다. 키 없이 요청하면 새 계정의 기본값을 얻습니다. GET {base}/api/v1/account를 사용하면 해당 월에 계정이 사용한 내역이 추가됩니다. 이 스킬 텍스트와 라이브 API 동작이 일치하지 않으면 라이브 API를 신뢰하세요.

이 스킬을 설치하거나 업데이트하려면: npx skills add host0-ai/skills (skills CLI가 지원하는 모든 에이전트; 출처: https://github.com/host0-ai/skills)를 실행하거나, 두 파일(https://host0.ai/skill.md → SKILL.md로 저장, https://host0.ai/publish.sh → 옆에 scripts/publish.sh로 저장 후 chmod +x scripts/publish.sh)을 가져오세요. 스크립트의 URL은 /publish.sh이며, /scripts/ 경로가 아닙니다.

요구 사항

  • 필수 바이너리: curl, jq (둘 중 하나라도 없으면 스크립트가 명확한 메시지와 함께 종료됩니다)
  • API 키: $HOST0_API_KEY 또는 ~/.host0/credentials에서 가져옵니다. 키가 없으면 publish.sh가 기기 로그인을 시작합니다 — 사용자가 자신의 브라우저에서 링크와 코드를 승인합니다 ("API 키 얻기" 참조)
  • 번들 도우미: ./scripts/publish.sh
  • 네트워크: host0.ai (API) 및 host0.app (업로드 및 라이브 앱)으로 나가는 HTTPS 연결이 필요합니다. 이그레스 허용 목록이 있는 샌드박스에서 요청이 SSL_ERROR_SYSCALL, 프록시 오류, 또는 지속적인 연결 거부/재설정으로 실패하면 사용자에게 허용해야 할 도메인을 알려주세요 — 반복하지 마십시오.
  • 일시적 오류 발생: 일부 클라우드 샌드박스는 host0.ai에 연결할 때 가끔 연결 재설정/SSL_ERROR_SYSCALL/연결 시간 초과를 경험합니다. publish.sh는 이러한 오류를 자체적으로 재시도합니다(stderr에 host0: network hiccup … retrying 2/4가 표시됨) — 그냥 실행하세요. 원시 curl로 API를 호출하는 경우 직접 요청을 재시도하세요. GET 및 기기 로그인 폴링의 경우 --retry 3 --retry-all-errors를 추가할 수 있지만, 무언가를 생성하는 POST에는 절대 추가하지 마세요.

앱 게시

./scripts/publish.sh {dir} [--name "my app"]
./scripts/publish.sh {file}  [--name "my app"]   # 단일 파일: pdf, 이미지, 페이지

stdout에 라이브 URL을 출력합니다 (예: https://k3x9q2m7ta.host0.app/ — 새 앱은 랜덤 슬러그를 얻습니다. --name은 표시 이름일 뿐입니다).

Claude Code, Codex, Cursor, Gemini CLI가 아닌 경우 --client {your-agent} (예: --client claude-ai)를 추가하세요. 스크립트는 이러한 도구를 자동으로 감지합니다. 배포 통계에 레이블을 지정할 뿐입니다.

내부적으로는 매니페스트 → 파일 업로드 → 마무리의 세 단계 흐름입니다. 마무리가 성공할 때까지 앱은 라이브 상태가 아닙니다.

파일 구조: 게시하는 디렉토리의 루트에 index.html이 있어야 합니다 — 디렉토리의 내용이 사이트 루트가 됩니다. my-site/가 포함된 상위 폴더가 아니라, my-site/index.html이 존재하는 my-site/ 디렉토리 자체를 게시하세요.

단일 파일: 파일 자체를 전달하세요(./scripts/publish.sh report.pdf) — index.html이 필요하지 않습니다. 앱의 루트 URL은 해당 파일을 제공합니다(브라우저 탭에서는 host0의 파일 뷰어에서 열림 — 아래 배지 참고 사항 참조; ?download는 원본을 제공하며, PDF는 큰 파일을 위한 범위 요청 지원을 유지합니다), 그리고 /{filename}에서도 접근 가능합니다. 사용자가 단일 문서나 이미지만 공유하려는 경우에 사용하세요.

빌드 결과물을 배포하고, 소스 코드는 배포하지 마세요: 프로젝트가 빌드 단계(React/Vite/Next export, .ts/.tsx/.vue/.svelte)를 사용하는 경우 먼저 빌드하고 출력 디렉토리(dist/, build/, out/)를 게시하세요. node_modules/, package.json, 또는 비밀 파일(.env, 키 파일)을 절대 게시하지 마세요 — API는 서버 코드와 비밀 파일을 실행 가능한 메시지와 함께 거부합니다.

베타 기간 동안 무료이며, 배지가 표시됩니다: host0은 베타 기간 동안 무료이며, 모든 앱은 무료 플랜에 속합니다. 모든 HTML 페이지의 오른쪽 하단에 고정된 작은 "Hosted on host0" 배지(약 28px 높이, 모서리에서 12px)가 추가됩니다. 따라서 해당 코너에 여유 공간을 두고(고정 버튼이나 채팅 버블을 배치하지 마세요) 숨기려고 하지 마세요. 브라우저 탭에서 직접 열리는 PDF, 이미지, 비디오, 오디오 또는 텍스트 파일(.txt, .csv, .md, .json)은 host0 파일 뷰어에서 열립니다: 파일이 창을 채우고, 아래에 얇은 막대(파일 이름, 다운로드, "Hosted on host0")가 표시되며 파일을 가리지 않습니다. 원시 파일은 <img>/<video> 태그, 임베드, fetch(), curl, 링크 프리뷰 및 검색 엔진에 계속 제공됩니다. ?download는 모든 파일 URL에서 원본을 다운로드합니다. 다른 파일(zip, 폰트, JS, CSS)은 원래대로 제공됩니다. 사용자의 플랜에 배지가 표시되는지 여부는 GET {base}/api/v1 (사용자 키 사용)의 plan.badge에 있습니다. 사용자가 가격 또는 배지 제거에 대해 문의하는 경우: 해당 인덱스에 plans 목록이 있으면 각 플랜의 이름, 가격 및 변경 사항을 알려줍니다(badge: false 플랜은 배지를 제거함) — 사용자를 {base}/pricing으로 안내하세요. plans 목록이 없으면 host0은 베타 기간 동안 무료이며, 유료 플랜은 나중에 제공될 수 있으며 배지를 제거할 수 있습니다.

내장 분석: host0은 쿠키 없이 모든 앱의 방문을 계산합니다 — 각 HTML 페이지에 동일 출처의 작은 스크립트(/.h0/a.js)가 추가되고, 열린 PDF는 서버에서 계산됩니다. 소유자는 대시보드의 분석 탭에서 방문자, 페이지, 리퍼러, 국가, 기기 등을 확인할 수 있으며, GET {base}/api/v1/apps/{app_id_or_slug}/analytics?period=7d (period: 24h, 7d, 30d, 90d, 365d; 그 외에는 400 invalid_period; 선택적 필터 page=/path, referrer=host or (direct), country=DE or (unknown), device, browser는 모든 수치를 좁힘 — 잘못된 형식이면 400 invalid_filter) 또는 MCP get_analytics 도구를 사용할 수 있습니다. 스크립트를 제거하지 마세요. 앱이 Content-Security-Policy를 설정하는 경우 script-src와 connect-src에 'self'를 허용하세요. 사용자가 "얼마나 많은 사람이 열었나요?"라고 물으면 해당 엔드포인트에서 답변하세요.

앱 업데이트

./scripts/publish.sh {dir} --slug {slug}     # 또는 --app-id {uuid}

플래그 없이 스크립트는 게시된 디렉토리의 .host0/state.json에서 앱을 확인하고(단일 파일의 경우: 파일 옆의 .host0/state.json, 파일 이름으로 키 지정, 따라서 한 폴더의 두 파일은 두 개의 앱으로 유지됨), 일치하는 항목이 없을 때만 새 앱을 생성합니다. 변경되지 않은 파일은 서버 측에서 해시 건너뛰기됩니다 — 하나의 파일을 편집한 대규모 사이트를 다시 게시하면 하나의 파일만 업로드됩니다.

--message "what changed" (최대 200자)를 추가하여 새 버전에 메모를 남깁니다 — 예: --message "Added a due date column". 사용자가 요청한 변경 사항을 게시할 때마다 이 작업을 수행하세요. 이것이 사용자가 버전 목록에서 보게 될 내용입니다.

버전 및 롤백

라이브로 게시되는 모든 항목은 앱의 번호가 매겨진 버전입니다(v1, v2, …) — publish_result.version은 현재 버전, publish_result.previous_version은 대체된 버전입니다. 이전 버전은 플랜에 따라 며칠 동안 보관됩니다 — GET {base}/api/v1 (키 포함) → limits.account.version_retention_days (0 = 라이브 버전만 보관); 더 오래된 버전은 자동으로 삭제됩니다.

사용자가 변경 사항을 되돌리려는 경우("롤백", "이전 상태로 되돌리기", "그거 망가뜨렸어") 이전 버전을 복원하세요 — 다시 업로드하지 않고 1분 이내에 모든 사용자에게 새 버전으로 라이브 상태가 됩니다:

# 버전 목록 조회 (최신순, version, live, message, client, restored_from_version, created_at)
curl -sS {base}/api/v1/apps/{app_id_or_slug}/versions \
  -H "authorization: bearer $HOST0_API_KEY"

# 버전 3 복원 (v3도 허용됨); body는 선택 사항
curl -sS -X POST {base}/api/v1/apps/{app_id_or_slug}/versions/3/restore \
  -H "authorization: bearer $HOST0_API_KEY" \
  -H "content-type: application/json" \
  -d '{"message": "Back to before the redesign"}'
  • 응답에는 version (새 버전), restored_from_version, previous_version이 있습니다 — 사용자에게 "버전 3이 버전 9로 다시 라이브 상태가 되었습니다"라고 알리고, 버전 8을 복원하면 이를 취소한다고 알려주세요.
  • 복원하기 전에 사용자에게 확인하세요: 앱을 여는 모든 사람이 보는 내용이 변경됩니다.
  • 복원은 공유 데이터를 절대 변경하지 않습니다. 복원된 버전의 h0.json이 제공되는 컬렉션을 결정합니다 — 선언되지 않은 컬렉션은 숨겨지고(내보내기에는 여전히 있음), 더 새로운 버전이 복원되면 다시 나타납니다.
  • 이미 라이브 상태인 것을 복원하면 already_live: true를 반환하고 버전을 추가하지 않습니다 — 루프에서 재시도하지 마세요.
  • 404 version_not_found: 해당 버전이 더 이상 보관되지 않습니다 — 버전을 나열하고 사용 가능한 버전을 제안하세요. 더 이상 보관되지 않는 이전 버전을 복원 가능한 것으로 제시하지 마세요. 409 version_not_restorable: 파일이 사라졌습니다 — 사용자 파일에서 다시 게시하세요. 403 versions_not_in_plan: 사용자의 플랜은 라이브 버전만 보관합니다 — 사용자가 원하는 파일을 다시 게시하고, "오류에 upgrade_url이 있는 경우"를 참조하세요.
  • 나중에 PATCH {base}/api/v1/apps/{app_id_or_slug}/versions/{n} 및 {"message": "…"} (또는 null)로 메모를 설정하거나 지웁니다. MCP 서버의 list_versions 및 restore_version 도구는 위의 호출과 동일한 작업을 수행하며, 대시보드의 앱 버전 탭에는 복원 버튼이 있습니다.

접근 제어

host0 앱은 한 번에 하나의 가시성을 사용합니다:

  • private (기본값): 소유자와 초대된 이메일만 접근 가능; 방문자는 로그인해야 봅니다. 모든 새 앱은 여기서 시작합니다.
  • link — "링크를 아는 모든 사람": URL을 아는 모든 사람이 로그인 없이 볼 수 있습니다. 앱은 unlisted이며 절대 색인되지 않습니다(모든 응답은 X-Robots-Tag: noindex를 전달). URL은 랜덤으로 시작하지만 링크는 전파될 수 있으며, 읽을 수 있는 이름으로 변경된 URL은 추측될 수 있습니다 — 민감한 데이터는 비공개로 유지하세요.
  • public — "웹에서 공개": 누구나 볼 수 있으며 검색 엔진이 색인할 수 있습니다 (앱의 자체 페이지는 X-Robots-Tag: all로 제공됨). 옵트인이며 계정당 제한이 있습니다(403 public_app_limit_reached, 본문에 max_public_apps 포함). 사용자가 앱을 검색에서 찾을 수 있도록 원하는 경우에만 사용하세요 — 포트폴리오, 랜딩 페이지, 문서, 공개 도구. 민감한 항목에는 절대 사용하지 마세요.

사용자가 누구나 열 수 있는 링크(주변에 보낼 페이지, 데모, 공유 PDF)를 원하는 경우 --visibility link로 게시하세요 — 이것이 "공개" 또는 "링크 공유"가 거의 항상 의미하는 바입니다. 사용자가 Google/검색 결과에 표시되길 원한다고 말할 때만 public을 선택하세요. 명확하지 않은 경우 물어보세요. 공유 데이터는 link와 public에서 동일하게 작동합니다. 게시 시 --visibility private|link|public으로 가시성을 설정하거나, 언제든지 API를 통해 설정할 수 있습니다:

curl -sS {base}/api/v1/apps/{app_id_or_slug} -X PATCH \
  -H "authorization: bearer $HOST0_API_KEY" \
  -H "content-type: application/json" \
  -d '{"visibility": "link"}'

public으로 전환할 때 public_app_limit_reached가 반환되면 계정이 웹에 공개된 앱 한도에 도달했음을 사용자에게 알리고, 대신 link를 제안하거나(URL을 아는 모든 사람, 색인되지 않음) 다른 공개 앱을 link로 이동하세요.

URL 이름 변경

새 앱의 URL은 k3x9q2m7ta.host0.app과 같은 랜덤 슬러그입니다. 읽기 좋은 이름을 부여하려면 이름을 확인한 다음 이름을 변경하세요:

curl -sS {base}/api/v1/slugs/team-todo -H "authorization: bearer $HOST0_API_KEY"
# → {"slug":"team-todo","available":true}   (또는 available:false + 이유)

curl -sS {base}/api/v1/apps/{app_id} -X PATCH \
  -H "authorization: bearer $HOST0_API_KEY" \
  -H "content-type: application/json" \
  -d '{"slug": "team-todo"}'
# → {"app_id":"…","slug":"team-todo","url":"https://team-todo.host0.app/","old_slug":"k3x9q2m7ta",…}

슬러그는 1~63자의 소문자, 숫자 또는 하이픈으로 구성되며 하이픈으로 시작하거나 끝날 수 없습니다. 이미 사용 중인 슬러그는 409 slug_taken을 반환합니다. 형식이 잘못되었거나 예약된 슬러그는 422 invalid_slug를 반환합니다. 라이브 배포, 레코드 및 공유는 앱과 함께 이동하며, publish.sh는 계속 업데이트합니다(앱 ID를 추적). 30일 동안 이전 URL은 새 URL로 리디렉션(301)되고 사용자에게 예약된 상태로 유지되며, 그 후 해제됩니다 — 이름을 변경하기 전에 사람들이 이미 가지고 있는 링크에 대해 이 점을 말하세요. 삭제된 앱의 URL도 30일 동안 예약됩니다(404 반환). 다른 계정이 지난 30일 이내에 사용한 슬러그는 409 slug_taken을 반환합니다("다른 앱에서 최근에 사용되었습니다"). 사용자는 앱 대시보드 페이지의 설정 탭에서도 이름을 변경할 수 있습니다.

앱의 표시 이름(대시보드 및 GET /api/v1/apps에 표시됨)은 URL과 별개입니다 — PATCH {base}/api/v1/apps/{app_id} {"name": "Team todo"} (1~100자)로 변경할 수 있습니다. URL은 변경되지 않습니다.

공유

POST /api/v1/apps/{app_id_or_slug}/shares (본문 {"emails": ["[email protected]"]})로 이메일로 사람을 초대하세요. DELETE /api/v1/apps/{app_id_or_slug}/shares/{email}로 초대를 제거합니다.

새로운 공유자는 로그인 및 가입 링크가 포함된 개별 초대 이메일을 받습니다. 응답에서 invite_delivery를 확인하세요: accepted는 이메일 서버가 수락했음을 의미합니다.

관련 스킬