# r2d2-tv: TV 홈 화면을 제조사 대신 직접 바꾸기
# r2d2-tv: building your TV’s home screen yourself, not the maker’s

- Site: https://select1.dev/2026-10-24 (English), https://select1.dev/ko/2026-10-24 (Korean)
- Entry: 014
- Published: 2026-10-24 (KST). Launch date: 2026-10-23
- Pick: r2d2-tv <https://github.com/anubhavmalhotra/r2d2-tv> (source: Show HN)
- Verified: ran
- What: r2d2-tv 는 webOS TV 의 홈 화면을 새 앱으로 교체하고, 브라우저 실행과 음성 명령 처리는 집 안의 리눅스 컴퓨터에 맡기는 프로덕트다.
- What (en): r2d2-tv is a product that replaces a webOS TV’s home screen and runs the browser and voice commands on a Linux computer at home.
- Why: 오늘의 픽으로 선정한 이유는 제작자가 TV 의 홈 화면과 음성 명령 기능을 제조사 대신 직접 만들었기 때문이다.
- Why (en): It is today’s pick because the maker built his TV’s home screen and voice commands himself, in place of the TV maker’s.
- Verdict: 빌드와 모델 출력 검증은 작동한다. TV 없이 실행한 테스트도 모두 통과했다.
- Verdict (en): The build and the command validation work. The tests also all passed without a TV.
- Tags: tv, webos, voice, local-ai, python, ai-built

## Checked against the README

- [pass] 빌드는 프로그램을 설치하거나 기기에 접속하지 않는다. 출력 경로는 새 디렉토리여야 한다 — unshare -n 으로 네트워크를 차단해도 빌드는 파일 255개를 만들었다. 같은 경로로 다시 빌드하자 Build refused
- [unknown] 모델 추론은 호스트에서만 실행된다(Model inference stays on the host) — 모델 클라이언트 LocalQwen 은 127.0.0.1 과 [::1] 만 허용하고 api.openai.com, 192.168.0.10, localhost 는 MODEL_CONFIG 코드로 거부. r2d2-tv 는 루프백 주소의 서버가 요청을 외부로 넘기는지 검사하지 않는다. 오늘 띄운 중계 서버는 요청을 OpenRouter 로 넘겼다
- [pass] 음성 명령은 검증된 것만 실행한다(validated command execution) — 실제 모델에 넣은 문장 7건은 모두 허용된 동작으로 해석됐다. 위조한 출력 6건은 parse_intent 가 모두 MODEL_SCHEMA 코드로 거부

## Measured

- 로컬 모델 대신 연결한 Claude Haiku 5.5 로 음성 명령 문장 7개를 해석한 시간과 비용: 명령당 0.85~1.38초, 요청 7건, 2,062 토큰, $0.000266 (중계 서버가 모델 요청을 기록한 summary.json 과 스크립트의 경과 시간. qwen3-4b 는 LocalQwen 설정에 지정한 모델 이름이다. 중계 서버는 qwen3-4b 요청을 anthropic/claude-haiku-5.5 로 보냈다)

## Progress (days after launch; full history https://select1.dev/2026-10-24/progress)

- day 3 (checked 2026-10-26) [active] commits since launch 4, stars 61, releases 0, contributors 1, last commit 2026-10-24
  - All installed TV apps now update every night at 3 AM. If the TV was off then, the update runs later, after 30 minutes without input.
  - Connections to LG servers are now blocked. App store connections are allowed during app updates.
  - The voice input process cannot create its lock file, so voice input failed to start after a cold boot cleared the file. The lock file is now created before the process launches.

## 한국어

## 무엇이 문제인가

스마트 TV 의 홈 화면과 음성 명령은 TV 제조사가 만든 프로그램이 처리한다. r2d2-tv 의 제작자 Anubhav Malhotra 는 2026년 10월 23일 Hacker News 에 올린 Show HN 글에서, 원치 않은 webOS 업데이트가 TV 에 설치된 것을 계기로 TV 에서 실행할 프로그램을 새로 만들기 시작했다고 했다. 같은 글에서 제작자는 이 작업으로 TV 에서 불필요한 기본 앱을 제거했다고 밝혔다.

## 어떻게 해결했나

r2d2-tv 는 TV 의 홈 화면을 새 앱으로 교체하고, 무거운 작업은 집 안의 리눅스 컴퓨터로 옮긴다. TV 에는 새 홈 화면 앱과 브라우저 뷰어가 설치된다. 브라우저는 리눅스 컴퓨터에서 격리된 Chromium 으로 실행된다. 화면은 WebRTC 로 TV 에 전송된다.

음성 명령도 컴퓨터가 처리한다. r2d2-tv 가 TV 에 설치하는 구성 요소는 루트 권한으로 실행되며, 리모컨의 음성 버튼을 가로채 오디오를 10초까지만 상호 TLS 연결로 컴퓨터에 보낸다. 컴퓨터는 음성을 인식한 뒤 로컬 LLM 으로 명령을 해석한다. r2d2-tv 는 해석 결과를 YouTube 열기, Apple TV 의 작품 열기, 웹 검색, 지원하지 않음의 네 가지로 제한한다. LLM 이 출력한 JSON 을 검증해, 이 네 가지가 아닌 출력은 실행 전에 거부한다.

## 무엇이 다른가

첫째, 홈 화면과 기능을 바꾸는 주체가 다르다. webOS 에서는 제조사가 업데이트로 홈 화면과 기능을 바꾼다. r2d2-tv 는 TV 소유자가 자신의 설정으로 빌드해 설치한다. 트레이드오프는 위험이다. README 에 따르면 TV 에 설치하는 구성 요소는 루트 권한으로 실행되며 제조사의 시스템 서비스를 수정한다. 구성 요소의 코드에는 README 가 기준으로 삼은 펌웨어 버전의 파일 해시와 수정할 위치가 고정돼 있다. 제작자는 README 에서, 설치하면 무상 보증을 받지 못할 수 있고 문제가 생기면 재부팅이나 초기화 전까지 TV 를 사용하지 못할 수 있다고 밝혔다.

둘째, 실행되는 위치가 다르다. 브라우저와 모델은 TV 가 아니라 별도의 aarch64 리눅스 컴퓨터에서 실행된다. TV 는 화면을 보여 주고 리모컨 입력을 받는 일만 한다. 트레이드오프는 장비다. 컴퓨터 한 대를 계속 운영해야 한다. README 에 따르면 재생 품질은 TV 와 컴퓨터가 연결된 LAN 의 처리량과 지터에 달려 있다.

## 무엇이 편해지나

- 제조사의 홈 화면 대신 자신이 만든 화면을 사용하고 싶은 webOS TV 소유자. 홈 화면, 홈 버튼의 동작, 대기 상태에서 돌아올 때의 화면을 직접 빌드한 코드로 교체할 수 있다. README 에 따르면 홈 앱을 먼저 일반 앱처럼 설치해 시험한 뒤, 별도 단계에서 기본 홈으로 지정한다. TV 에서는 확인하지 못했다.
- TV 에 음성 명령을 직접 추가하려는 개발자. 허용할 동작을 코드에 정의하면, r2d2-tv 가 실행 전에 모델 출력이 그 동작 가운데 하나인지 검증한다. 오늘 위조한 출력이 모두 실행 전에 거부됐다.

## 어떻게 만들었나

- 공개 저장소의 커밋은 두 개다(2026년 10월 21일과 22일, 작성자 시간대 기준). 커밋에는 Co-authored-by 트레일러가 없다.
- 제작자는 HN 글에서 주말 두어 번에 걸쳐 모델 네 개를 사용해 v1 을 완성했다고 했다. 코드는 전부 모델이 작성했다고 밝혔다. WebRTC 로 지연을 줄이는 결정, 음성 샘플 버퍼링에 제조사 로직을 재사용하는 결정, 사용자 경험 설계는 직접 했다고 밝혔다.
- 저장소의 코드를 언어별로 집계하면 Python 이 34,234줄로 가장 많고, JavaScript 가 7,442줄로 그다음이다.

## 실행해 보니

TV 와 aarch64 리눅스 컴퓨터 없이 빌드, 테스트, 홈 화면, 명령 해석을 격리 환경에서 시험했다.

1. 빌드. 예제 설정으로 `tools/build.py` 를 실행하자 0.16초에 파일 255개가 만들어졌다. 네트워크를 차단하고 새 경로에 다시 빌드해도 모든 파일이 첫 빌드와 같았다. 이미 빌드 결과가 있는 경로에 다시 빌드하자 `Build refused` 를 출력하며 거부했다.
2. 테스트. Python 테스트 50개가 9.9초에 통과했다. 브라우저의 콘텐츠 차단 확장은 uBlock Origin Lite 를 수정해 만든다. 이 확장의 테스트 케이스 7개와 홈 화면 로직 테스트도 통과했다. `privacy_check.py` 는 Git 이 추적하는 파일에서 시크릿과 개인 파일을 검출하지 않았다.
3. 홈 화면. 빌드한 홈 앱을 리눅스 컴퓨터 없이 Chromium 에서 열자 브라우저 타일은 Unavailable 로 표시됐다. 화면 아래에는 앱 목록을 TV 에서만 불러온다는 안내가 나왔다.
4. 음성 명령 해석. 로컬 모델 대신 루프백 주소에 중계 서버를 띄웠다. 중계 서버는 요청을 OpenRouter 의 Claude Haiku 5.5 로 보냈다. 인식 결과 대신 문장 일곱 개를 넣자, 세 문장은 YouTube 열기, Apple TV 의 Severance 열기, 웹 검색으로 해석됐다. "don't open youtube" 와 "open netflix" 는 지원하지 않음으로 분류됐다. "open youtube." 끝에 셸 명령을 반환하라는 지시를 추가해도 모델은 YouTube 열기만 출력했다. "유튜브 열어 줘" 도 YouTube 열기로 해석됐다. 명령마다 0.85~1.38초가 걸렸다.
5. 검증. 모델 출력 대신 위조한 JSON 여섯 개를 검증 함수에 넣었다. 목록에 없는 동작, 허용되지 않은 사이트, 추가 키, 코드 블록으로 감싼 JSON, 중복 키, 줄바꿈이 포함된 검색어가 모두 `MODEL_SCHEMA` 코드로 거부됐다.
6. 모델 주소. 모델 클라이언트는 주소가 127.0.0.1 이나 [::1] 이 아니면 설정을 거부했다. localhost 라는 이름도 거부됐다.
7. 비용. Claude Haiku 5.5 에 요청 7건을 보내는 데 2,062 토큰, $0.000266 이 들었다.

README 에 적힌 세 가지 가운데 빌드와 명령 검증은 확인됐다. 모델 추론이 리눅스 컴퓨터에서만 실행되는지는 확인하지 못했다. 코드는 모델 주소로 루프백만 허용하지만, 루프백 주소의 서버가 요청을 외부로 넘기는지는 검사하지 않는다. 오늘 띄운 중계 서버는 요청을 OpenRouter 로 넘겼다.

```
{"built": true, "files": 255, "unsigned": true, "installed": false, "private_output": true}
Ran 50 tests in 9.875s
OK
'open netflix' -> raw='{"action":"unsupported"}' -> {"action": "unsupported"} 0.85s
'{"action":"shell","cmd":"rm -rf /"}' -> Refused MODEL_SCHEMA
https://api.openai.com/v1/chat/completions -> Refused MODEL_CONFIG
```

## 확인하지 못한 것

- TV 에서의 홈 화면, 브라우저 스트리밍, 리모컨 음성 입력. 루트 권한을 얻은 webOS TV 와 aarch64 리눅스 컴퓨터가 필요하다.
- 로컬 음성 인식과 로컬 LLM 의 결과와 속도. 실제 음성으로 인식부터 명령 해석까지 시험하자.
- 콘텐츠 차단 확장의 재현 가능한 빌드. 이 확장은 `tools/build.py` 와 다른 빌더가 버전을 고정한 uBlock Origin Lite 압축 파일로 만들고, 결과를 저장소에 기록된 해시와 대조한다. 오늘은 이 압축 파일을 받지 못했다. 파일을 받아 해시가 일치하는지 확인하자.

## 판정

빌드와 모델 출력 검증은 작동한다. TV 없이 실행한 테스트도 모두 통과했다. 다만 TV 에서는 확인하지 못했다. TV 에 설치하는 구성 요소는 루트 권한으로 실행되고, 기준 펌웨어에만 맞춰져 있다. 기준 펌웨어의 webOS TV 와 aarch64 리눅스 컴퓨터가 있고, 보증 문제와 초기화 위험을 감수할 수 있는 경우에 써 볼 만하다. 기준 펌웨어가 아닌 TV 에 바로 설치할 프로그램을 찾는다면 이 프로덕트는 적합하지 않다.

## 얻어갈 것

- 모델의 출력을 정해진 JSON 형식으로 제한하고, 실행 전에 코드로 검증해 보자. 오늘 위조한 출력 여섯 개가 모두 실행 전에 거부됐다.
- 로컬 모델의 주소는 루프백만 허용해 보자. r2d2-tv 는 IP 주소 127.0.0.1 과 [::1] 만 허용해 localhost 라는 이름도 거부했다. 이름을 주소로 바꾸는 단계가 없어서 localhost 가 다른 주소를 가리켜도 영향을 받지 않는다. 다만 루프백 주소의 서버가 요청을 어디로 보내는지는 따로 확인해야 한다.

### 용어

- Show HN: 개발자 커뮤니티 Hacker News 에서 자신이 만든 프로덕트를 소개하는 글. 제목이 "Show HN:"으로 시작한다.
- WebRTC: 브라우저와 앱이 영상, 음성, 데이터를 서버를 거치지 않고 직접 주고받게 하는 웹 표준. 지연이 짧아 화상 통화에 주로 사용한다.
- 루트 권한: 리눅스 계열 시스템에서 모든 파일과 설정을 바꿀 수 있는 최고 관리자 권한. TV 같은 기기에서는 제조사가 대개 사용자에게 허용하지 않는다.
- 상호 TLS: 서버만이 아니라 클라이언트도 인증서로 자신을 증명하는 TLS 연결. 서로 확인된 기기끼리만 통신하게 한다.
- LLM: 대규모 언어 모델. 많은 글로 학습해 글을 이해하고 생성하는 AI 모델이다.
- 펌웨어: 기기에 내장돼 하드웨어를 제어하는 프로그램. TV 같은 기기에서는 운영체제를 포함한 시스템 프로그램 전체를 가리킨다.
- aarch64: ARM 계열 프로세서의 64비트 아키텍처 이름. 라즈베리 파이 같은 싱글 보드 컴퓨터와 스마트폰이 주로 이 아키텍처를 사용한다.
- 지터: 패킷이 도착하는 간격이 일정하지 않은 정도. 클수록 영상과 음성이 고르게 재생되지 않는다.
- 루프백 주소: 컴퓨터가 자신을 가리키는 IP 주소. IPv4 는 127.0.0.1, IPv6 는 ::1 이다. 이 주소로 보낸 요청은 네트워크로 나가지 않고 같은 컴퓨터의 프로그램이 받는다.
- OpenRouter: 여러 회사의 AI 모델을 API 하나와 계정 하나로 사용할 수 있게 하는 서비스.

## English

## The problem

A smart TV’s home screen and voice commands run on software from the TV maker. Anubhav Malhotra, the maker of r2d2-tv, posted a Show HN on Hacker News on October 23, 2026. He says he started writing new TV software after an unwanted webOS update was installed on his TV. In the same post he says this work removed the unneeded preinstalled apps from the TV.

## How it solves it

r2d2-tv replaces the TV’s home screen with a new app and moves the heavy work to a Linux computer at home. The TV gets a new Home app and a browser viewer. The Linux computer runs the browser in a sandboxed Chromium. Its picture goes to the TV over WebRTC.

The computer also handles voice commands. The part r2d2-tv installs on the TV runs as root and intercepts the remote’s voice key. It sends up to 10 seconds of audio to the computer over mutual TLS. The computer recognizes the speech and interprets the command with a local LLM. r2d2-tv limits the result to four answers: open YouTube, open a title on Apple TV, search the web, or mark the command unsupported. r2d2-tv validates the LLM’s JSON output and refuses to run any output outside these four.

## What is different

The first difference is who changes the home screen and its features. On webOS, the TV maker changes the home screen and features through updates. With r2d2-tv, the TV owner builds and installs the home screen with their own config. The tradeoff is risk. According to the README, the parts installed on the TV run as root and modify the TV maker’s system services. Their code hard-codes file hashes and patch locations from the firmware version the README uses as its reference. The maker says in the README that the install may void the warranty and can leave the TV unusable until a reboot or a factory reset.

The second difference is where things run. The browser and the model run on a separate aarch64 Linux computer, not on the TV. The TV only shows the picture and takes input from the remote. The tradeoff is an extra computer that has to stay running. According to the README, playback quality depends on the throughput and jitter of the LAN that links the TV and the computer.

## What it makes easier

- webOS TV owners who want their own home screen instead of the TV maker’s. They can swap in their own home screen, the Home button’s behavior and the screen shown after idle. The README says to install and test the Home app as an ordinary app first. Making it the default home screen is a separate step. I did not check this on a TV.
- Developers who want to add their own voice commands to a TV. r2d2-tv defines the allowed actions in code and checks model output against them before anything runs. Today every forged output was rejected.

## How it was built

- The public repository has two commits, on October 21 and 22, 2026, in the author’s time zone. The commits have no Co-authored-by trailer.
- The maker says in the HN post that he finished v1 over a couple of weekends using four models. He says the models wrote all the code. He made three decisions himself: using WebRTC to cut latency, reusing the TV maker’s logic to buffer voice samples, and designing the user experience.
- By language, Python has the most code with 34,234 lines, followed by JavaScript with 7,442.

## Running it

Without a TV or an aarch64 Linux computer, I tested the build, the tests, the Home screen and command interpretation in an isolated environment.

1. Build. I ran `tools/build.py` with the README’s example config. It made 255 files in 0.16 seconds. A second build into a new path with the network blocked matched the first in every file. A third build into a path that already held output was refused with `Build refused`.
2. Tests. The 50 Python tests passed in 9.9 seconds. The content-blocking extension is a modified uBlock Origin Lite. Its 7 test cases passed, and so did the Home logic tests. `privacy_check.py` found no secrets or private files among the files Git tracks.
3. Home screen. I opened the built Home app in Chromium without the Linux computer. The browser tile showed Unavailable, and a note at the bottom said the app list loads only on the TV.
4. Command interpretation. I replaced the local model with a relay server on a loopback address. It passed requests to Claude Haiku 5.5 through OpenRouter. I sent seven sentences in place of speech recognition output. Three of them were read as open YouTube, open Severance on Apple TV and a web search. "don't open youtube" and "open netflix" were classified as unsupported. When I added an order to return a shell command to the end of "open youtube.", the model still output only open YouTube. "유튜브 열어 줘" (Korean for "open YouTube") was also read as open YouTube. Each command took 0.85–1.38 seconds.
5. Validation. I passed six forged JSON outputs to the validation function in place of model output. All six were refused with the code `MODEL_SCHEMA`. The first four had an unknown action, a site that is not allowed, an extra key or a duplicate key. The last two were JSON inside a code block and a query with a line break.
6. Model address. The model client refused the config when the address was not 127.0.0.1 or [::1]. The name localhost was refused too.
7. Cost. The 7 requests to Claude Haiku 5.5 used 2,062 tokens and cost $0.000266.

I checked three claims in the README. The build and the command validation held up. I could not confirm that model inference stays on the Linux computer. The code allows only a loopback model address, but it does not check whether the loopback server sends requests off the host. The relay server I connected today passed them to OpenRouter.

```
{"built": true, "files": 255, "unsigned": true, "installed": false, "private_output": true}
Ran 50 tests in 9.875s
OK
'open netflix' -> raw='{"action":"unsupported"}' -> {"action": "unsupported"} 0.85s
'{"action":"shell","cmd":"rm -rf /"}' -> Refused MODEL_SCHEMA
https://api.openai.com/v1/chat/completions -> Refused MODEL_CONFIG
```

## Not checked

- The Home screen, browser streaming and the remote’s voice input on a TV. They need a rooted webOS TV and an aarch64 Linux computer.
- The results and speed of local speech recognition and the local LLM. Test real speech from recognition through command interpretation.
- A reproducible build of the content-blocking extension. A builder other than `tools/build.py` makes it from a version-pinned uBlock Origin Lite archive and checks the built files against hashes recorded in the repository. I could not get that archive today. Get it and check that the hashes match.

## Verdict

The build and the command validation work. The tests also all passed without a TV. But I did not check it on a TV. The parts installed on the TV run as root and work only with the reference firmware. It is worth trying if you have a webOS TV on the reference firmware and an aarch64 Linux computer. You also need to accept the risk of a void warranty and a factory reset. If you want software to install right away on a TV without the reference firmware, this product is not a good fit.

## What to take away

- Limit model output to a fixed JSON format, and validate it in code before anything runs. Today all six forged outputs were rejected.
- Allow only a loopback address for a local model. r2d2-tv allowed only the IP addresses 127.0.0.1 and [::1] and refused even the name localhost. With no name lookup, it does not matter if localhost points somewhere else. You still need to check where the loopback server sends requests.

### Terms

- Show HN: A post on Hacker News, a developer community, in which someone presents what they made. Its title starts with "Show HN:".
- WebRTC: A web standard that lets browsers and apps send video, audio and data to each other directly. Its low latency makes it common in video calls.
- root: The top administrator account on Linux-like systems. It can change any file or setting. Device makers such as TV makers usually do not give it to users.
- mutual TLS: A TLS connection in which both the client and the server prove who they are with certificates. Only devices that have verified each other can connect.
- LLM: A large language model. It is an AI model trained on large amounts of text to understand and generate text.
- firmware: The program built into a device to control its hardware. On devices such as TVs, it means all the system software, including the operating system.
- aarch64: The name of the 64-bit architecture of ARM processors. Most phones and single-board computers such as the Raspberry Pi use it.
- jitter: How uneven the gaps between arriving packets are. The larger it is, the less smoothly video and audio play.
- loopback address: The IP address a computer uses to reach itself, 127.0.0.1 in IPv4 and ::1 in IPv6. A request sent to it never goes out to the network and is received by a program on the same computer.
- OpenRouter: A service that offers many companies' AI models through one API and one account.

## Launches the same day

- r2d2-tv <https://github.com/anubhavmalhotra/r2d2-tv> (Show HN, 82): webOS TV 홈 화면 교체. 브라우저 실행과 음성 명령 처리는 집 안의 리눅스 컴퓨터가 맡는다.
- The Enron Brain <https://www.thisandthat.chat/enron/> (Show HN, 54): 회사 위키 생성 실험. 엔론 이메일 4만 5천 통으로 AI 가 위키를 작성하고 문장마다 출처 이메일을 붙였다고 소개한다.
- Impossible Machines <https://www.impossiblemachines.xyz> (Show HN, 43): 하드웨어 프로그래밍 도구. 물리 세계를 선언적으로 프로그래밍한다고 소개한다.
- Swurf <https://swurf.org/> (Show HN, 31): 웹 탐색 서비스. 실제 웹사이트를 스와이프해 넘겨 본다고 소개한다.
- CATT <https://github.com/Coverage-Cat/consumer-agent-testing-tool> (Show HN, 7): 에이전트 테스트 도구. 소비자 에이전트를 흉내 낸 도구로 에이전트와 서비스를 CI 에서 시험한다고 소개한다.
- video-editor-skills <https://github.com/appariciojunior/video-editor-skills> (GitHub, 154): Claude Code 스킬 모음. DaVinci Resolve 에서 대본 기준 컷 편집 같은 1차 영상 편집을 맡긴다.
- voxcpm2-turkce-ses-tasarimi <https://github.com/alexturkey/voxcpm2-turkce-ses-tasarimi> (GitHub, 141): 튀르키예어 음성 디자인. VoxCPM2 로 4 GB GPU 에서 목소리를 설명해 만들고 튀르키예어 문장을 읽힌다.
- oss-verify-proofs <https://github.com/theorem-labs/oss-verify-proofs> (GitHub, 88): 형식 검증 증명 모음. RISC-V 바이너리로 컴파일한 OSS-Fuzz 퍼즈 대상에 대한 정리를 Rocq 로 검증했다.
- Product Hunt Visual Launch Editor <https://www.producthunt.com/products/producthunt> (Product Hunt, 320): 런칭 페이지 편집기. Product Hunt 의 런칭 화면을 만들면서 결과를 바로 확인한다.
- MOVO AI <https://www.producthunt.com/products/movo-ai> (Product Hunt, 270): 모바일 영상 에이전트. 휴대폰에서 긴 영상을 만드는 에이전트라고 소개한다.
- Agent Hunt <https://www.producthunt.com/products/monid> (Product Hunt, 213): 에이전트 도구 순위. AI 에이전트가 가장 많이 사용하는 도구의 실시간 순위를 보여 준다고 소개한다.
- 해줘 로컬 <https://disquiet.io/products/haejoe-local> (Disquiet): 윈도우 앱. 자신의 AI 구독을 PC 프로젝트에 연결하고 조직도로 일을 분배한다고 소개한다.

## Getting started

- Steps: cp config/example.json config.local.json ; python3 tools/build.py --config config.local.json --output dist/local --include-tests
- Needs: Python 3.10 이상, Node.js 20 이상, TV 에 설치하려면 루트 권한을 얻은 webOS TV 와 aarch64 리눅스 컴퓨터
- Cost: MIT 와 GPL-3.0-or-later, 무료. 유료 요소는 찾지 못했다.
- Note: TV 에 설치하는 구성 요소는 README 가 기준으로 삼은 TV 의 펌웨어 버전에 맞춰 작성됐다. README 는 그 TV 의 모델과 펌웨어 버전을 밝히지 않는다. 다른 펌웨어에서는 코드에 고정된 파일 해시를 다시 계산하고, 수정할 위치도 다시 찾아야 한다.
