튜사에서 Nix 오리엔테이션을 열어볼까 생각이 드는데 수요가 있을라나
bgl gwyng
OpenClaw 인기 얻는거 보고있으면 사람들은 내용이 뭐가 됐건 기계가 자신을 위해서 하루종일 뭔가 열심히하면 그것만으로 행복해지는거 같다
확실친 않은데 클로드가 스폰하는 경량 모델을 쓰는 서브에이전트가 zat을 쓰려다가 실수로 cat을 쓰는거 같다? 차라리 Read 툴을 쓰지. 본체는 잘쓰는데 말이야. 혹시 비슷한 현상 보신분을 알려주세요.
fd와 zat을 합치면 repomix가 되는데, 이렇게 되게하려면 zat의 기능을 오히려 약간 줄여야한다. 그리고 생각해보니 줄이는게 맞다. UNIX 철학을 체화하는게 쉽지가 않아.
프로그래머의 일은 배관 작업과 서류 작업이 섞여 있는데, 나처럼 많은 프로그래머들이 배관 작업은 좋아하고 서류 작업은 싫어하다보니, 오히려 서류 작업의 많은 부분을 우아하게 자동화했다는게 재밌다.
예전에 만들었던 lat이 코에 점찍고 돌아왔습니다. zat이란 이름은 훑어보다라는 뜻의 일본어 ざっと (zatto)에서 따왔습니다.
CLI code outline viewer이고, zat main.ts 이렇게 하면 export 된 값들의 이름과 타입 시그니쳐 등, 코드의 인터페이스 부분에 해당하는걸 보여줍니다. 디렉토리에다가 zat src/ 해도 entry 파일들을 찾아서 적당히 잘 보여줍니다. 주로 코딩 에이전트가 쓸 것을 기대하고 만들었고, 코드 내비게이션을 할때 토큰 수를 줄이고 불필요한 정보가 컨텍스트에 미리 들어가는걸 줄여줍니다. 또 Nix 유저라면 zat 쉽게 확장해서 자기가 쓰는 언어를 지원하게 할 수 있습니다.
왜 VS Code/LSP는 심볼에 대한 레퍼런스는 쿼리할수 있으면서, 모듈(파일)에 대한 레퍼런스는 쿼리하지 못 하는걸까. 가끔 필요할때 엄청 답답하다.
잉 그동안 tree-sitter-streaming-markdown 만들고 있었는데?!
takt라는 소프트웨어를 구상중인데, 대충 어떤 거냐면. 레포에서 소스 코드는 아닌데, 그렇다고 빌드 결과물도 아닌 애매한 무언가들이 있단 말이지. 대표적으로는 README의 번역본 등이 있다. 원본은 소스 코드지만 번역본은 원본으로부터 유도되는, LLM으로 자동으로 생성할수 있는 무언가이다. 근데 그렇다고 빌드 결과물이라고 보기엔 애매하다. 빌드 결과물이면 재현 가능하고, 그래서 레포에서 뺄수 있어야하는데 그건 아니니까. 번역본을 자동으로 생성하더라도 레포엔 함께 커밋되어야 한다.
여기서 takt는 저런 애매한 녀석들을 위한 make 역할을 한다. Makefile처럼 Taktfile을 만들고, Taktfile에 의존성을 써놓으면 현재 up-to-date가 아닌 파일들을 추려낼수 있다(최신임을 마킹하는 일종의 Taktfile.lock 같은게 필요할 듯 하다). 그리고 그 파일들을 업데이트하면 되는 것이다. 번역 외에도 여러 용도로 쓸수 있을걸로 기대한다.
zat을 좀 고쳤습니다. 디렉토리 요약과 지원하지 않은 확장자에 대한 cat으로의 fallback을 제거했습니다. 대신 exitcode 1를 뱉게 해서 타 UNIX 툴과의 조합성을 개선했습니다. 가령 디렉토리 요약은 이제 다음과 같이 할수 있습니다.
fd -t f -x sh -c 'echo "## {}" && zat {}' 2>/dev/null
어차피 스크립트는 LLM이 짤테니까.. 괜찮겠죠. README.md의 새로운 프롬프트로 업데이트 하는걸 추천합니다.
- 日本語 (일본어): @bgl@hackers.pub
- English (영어): @bgl@hackers.pub
- American English (영어(미국)): @bgl@hackers.pub
문제
Nix는 설계 철학상 Nix 언어(순수 함수형 평가 언어)와 Nix store(콘텐츠 주소 기반 저장소)가 별도의 레이어로 분리되어 있다. 그러나 현실에서는 Nix 언어가 store에 대해 특권적 지위를 갖고 있으며, 이 둘 사이에 명시적인 인터페이스 경계가 존재하지 않는다.
특권적 지위의 구체적 양상- 유일한 공식 진입점: derivation을 생성하고 store에 등록하는 사실상 유일한 경로가 Nix 언어 평가기다.
nix build,nix develop등 CLI 도구도 내부적으로 Nix 평가기를 호출한다. - 생태계 종속: nixpkgs 전체가 Nix 언어로 작성되어 있고, flake 시스템도 Nix 평가기를 전제한다. 대안 언어는 항상 이등 시민이다.
- 순수성에 대한 신뢰 의존: store의 무결성이 Nix 언어의 순수성(부작용 없음, string context를 통한 의존성 추적 등)에 의존한다. 이는 언어 구현의 정확성을 믿어야 하는 취약한 신뢰 모델이다.
- Guix: Nix 언어 대신 Guile을 프론트엔드로 사용하지만, nixpkgs를 재사용하지 못하고 생태계를 처음부터 다시 구축해야 했다.
- Tvix: store를 다른 방식으로 구현하려 했지만, 결국 Nix 언어의 호환 평가기를 만드는 데 상당한 비용을 치르고 있다.
- Recursive Nix: 빌드 시점에 다른 언어에서 Nix daemon을 호출할 수 있지만, 최상위 진입점은 여전히 Nix 언어가 쥐고 있다. 탈출구는 생겼지만 그 문을 여는 열쇠는 Nix 언어에 있다.
핵심 아이디어: Nix 언어 평가기를 포함한 모든 프론트엔드 언어를, Nix sandbox 안에서 마운트된 Nix daemon 소켓을 통해서만 store와 상호작용하도록 한다.
구조 변경[현재]
Nix 언어 평가기 ──(특권적 접근)──▶ Nix Store
[제안]
┌─── Sandbox ────────────────────┐
│ Nix 언어 평가기
│ Guile / Python / Rust / ... │──(daemon 소켓)──▶ Nix Daemon ──▶ Nix Store
│ (네트워크 없음, FS 격리)
└────────────────────────────────┘
동작 방식
- 프론트엔드 언어(Nix 포함)는 sandbox 안에서 실행된다. 네트워크 접근 불가, 파일시스템 격리.
- Store 관련 모든 동작(derivation 등록, store path 조회, 빌드 요청 등)은 sandbox 안에 마운트된 Nix daemon 소켓을 통해서만 수행한다.
- Daemon이 store의 무결성을 보장하는 유일한 주체가 된다.
언어의 순수성을 신뢰할 필요가 없다. Sandbox가 커널 레벨에서 격리를 강제하므로, 어떤 언어가 sandbox 안에서 무엇을 하든 store의 무결성은 daemon이 보장한다. 언어 의미론에 의존하는 신뢰보다 OS 레벨 격리에 의존하는 신뢰가 훨씬 견고하다.
2. 언어 간 동등한 지위Nix, Guile, Python, Rust 등 어떤 언어든 sandbox 안에서 daemon 소켓 프로토콜을 사용하는 것은 동일하다. nixpkgs가 Nix로 작성되어 있다는 것은 생태계의 역사적 선택일 뿐, 아키텍처가 강제하는 것이 아니게 된다.
3. 기존 특수 케이스의 일반화- IFD(Import From Derivation): 평가 중에 빌드를 트리거하는 특수 케이스가 아니라, sandbox 안에서 daemon에게 빌드를 요청하는 일반적 동작이 된다.
- Recursive Nix: 별도 기능이 아니라 당연한 패턴이 된다.
- 평가와 빌드의 경계가 모호해져도 sandbox가 격리를 보장하므로 문제가 되지 않는다.
현재 Nix 아키텍처에서 언어 레벨의 순수성이 담당하는 보안 역할을, OS 레벨의 격리(sandbox + daemon 프로토콜)로 내리자는 것이 이 제안의 핵심이다. 이를 통해 Nix 언어의 특권적 지위가 제거되고, 모든 프론트엔드 언어가 동등한 조건에서 Nix store를 활용할 수 있게 된다.