OpenCV 만지게 될 날이 오니까 엄청 옛날에 주워들었던 선형대수학적 지식을 끌어오게 되기도 하는군아
洪 民憙 (Hong Minhee)
@hongminhee@hackers.pub · 1014 following · 723 followers
Hi, I'm who's behind Fedify, Hollo, BotKit, and this website, Hackers' Pub! My main account is at
@hongminhee洪 民憙 (Hong Minhee)
.
Fedify, Hollo, BotKit, 그리고 보고 계신 이 사이트 Hackers' Pub을 만들고 있습니다. 제 메인 계정은:
@hongminhee洪 民憙 (Hong Minhee)
.
Fedify、Hollo、BotKit、そしてこのサイト、Hackers' Pubを作っています。私のメインアカウントは「
@hongminhee洪 民憙 (Hong Minhee)
」に。
Website
- hongminhee.org
GitHub
- @dahlia
Hollo
- @hongminhee@hollo.social
DEV
- @hongminhee
velog
- @hongminhee
Qiita
- @hongminhee
Zenn
- @hongminhee
Matrix
- @hongminhee:matrix.org
X
- @hongminhee
정말 어려운 과정을 거쳐서 드디어 Certum에서 개인용 코드 서명 인증서를 발급받았습니다. 자동화가 안된다는 한계가 있지만, 코드 서명이 그래도 가능해졌다는 사실은 정말 기쁩니다.
Certum과의 인증 평가 과정에서, 저는 현재 월세 거주자이고 관리 사무소에서 공과금을 관리하고 있기에 영문 증명 서류를 떼는게 어려웠는데, 여권과 영문 주민등록등본으로 인증이 가능했습니다.
또한 가격도 합리적인 선에서 지불할 수 있었고, HSM 대신 SimplySign이라는 클라우드 기반 인증서 관리 도구를 사용하는 것을 조건으로 크게 단가를 낮출 수 있었습니다.
mearie를 개조해서 SvelteKit에서 SSR이 되게 만들었다...
We are joining Cloudflare! https://astro.build/blog/joining-cloudflare/
洪 民憙 (Hong Minhee) shared the below article:
생성 AI 논의에 대해 두서없이 몇 가지
lark @lark@hackers.pub
오랫동안 머신러닝 딥러닝 AI 모델링을 업으로 삼아 왔지만 정작 LLM이나 이미지 생성 같은 생성쪽은 피해다니다 보니[1] 이쪽 주제에 대해 아는 척 하기도 쉽지 않지만.. 관련 논의들 구경하다 보면 제가 평소 생각하는 중요 지점들이 잘 이야기되지 않는 것 같아 의식의 흐름을 따라 이것저것 남겨봅니다.
우선 모델이 생성한 결과물이 어떤 성격이나 맥락을 가지는지에 따라 저작권 문제가 완전히 달라지는데, 이건 원래 저작권에 대한 전반적인 성격이 그러하기 때문입니다. 기존 저작물을 복사/변형하더라도 그 목적이 원래 저작물과 판이하게 다를수록 저작권 침해가 아니라 fair use로 인정받을 가능성이 높아집니다.
맥락과 의도가 얼마나 중요한지를 보여주는 상징적인 사례가 구글 북스 소송인데, 구글 북스는 저작권이 있는 책을 사용자들에게 그대로 보여주니까 심각한 저작권 침해로 보일 수 있지만, 법정에서는 구글 북스 웹사이트가 원래 책 내용을 그대로 접근하는 목적을 막고 검색이라는 새로운 목적에만 사용가능하도록 했다고 판단했습니다.
이러한 다양한 사례 연구들이 Foundation Models and Fair Use에 나와 있습니다. 이 논문은 AI 연구자들과 법학 연구자가 같이 썼고 여러 legal edge case가 등장해서 생각을 정리하는 데에 도움이 될 수 있습니다.
Fair use의 핵심 요소인 transformative에 대해 AI모델 입장에서 보면, 사용자가 준 입력 텍스트에 있는 정보를 추출하거나 변환하는 task가 이에 해당할 가능성이 높습니다. 가장 유명한 예시가 텍스트 번역일 것 같은데, 사용자가 입력한 텍스트를 다른 언어로 바꾸는 것이 전부고 거기에 새로운 창작성이 드러나지는 않습니다[2]. 제가 이해하기로는 LLM이나 소위 AI가 잘 한다고 알려진 task도 대부분 이러한 것입니다. 번역이라든지, 텍스트 포맷을 바꾼다든지 등등. 제 주변에 LLM 잘 활용하신다는 분들을 보면 아마도 대부분 그렇게 쓰시는 것 같고요.
여기서 UX 관점에서의 불평을 하고 싶은데요, 무조건적인 텍스트 생성이 아니라 주어진 입력을 변환하는 능력이 LLM의 핵심 가치라면 모델이나 서비스 입장에서 그런 기능만 제공하고 지나친 생성을 제한하는 UI나 기술 장치를 도입해야 하지 않을까요? LLM을 긍정적으로 생각하지만 전반적인 생성(특히 입력보다 출력이 더 자유도가 높을 경우)이 사회적으로 위험하다고 생각된다면 그러한 조치를 LLM 서비스 제공자들에게 요구할 수는 없을까요? 저는 이러한 방향의 논의를 거의 본 적이 없는데, 아마 LLM를 접해본 사람들은 긍정적이든 부정적이든 그런 인터페이스가 어쩔 수 없는 일이라고 가정하고 있어서 그런 것 같습니다. (마침 며칠 전부터 ChatGPT나 Gemini에 번역 전용 UI가 생겼다는 소식이 보이고 있습니다. 이 글을 조금 더 빨리 쓸 걸 그랬네요..)
프로그래밍 쪽에서도 비슷하게 코드를 생성하는 사용법보다는 코드를 읽고 정보를 추출해주는 쪽이 저작권이나 윤리 문제가 적고 프로그래머의 능력 향상에 도움이 되지 않을거라고 생각하고요. (제가 상상하는 최적의 코딩 AI agent는 Rubber duck에 가까운데, 모든 질문과 해답이 제 머릿속에서 나와야 한다고 생각합니다. 그 중 문제 해결이나 능력 향상에 명백히 도움 안 될 질문만 잘 쳐내주면 좋겠어요.)
cf: 최근 Moral Codes를 조금씩 읽고 있습니다. 프로그래밍과 UI와 LLM과 윤리에 대한 책입니다. 아직 전부를 차근차근 읽은 건 아니지만, 기존의 LLM 논의가 갖혀있던 프레임에 빠져나오는 데에 큰 도움이 될 수 있다고 보여서 이 주제에 관심이 있는 분들에게 추천합니다. Open access라 무료로 볼 수 있어요.
Generative AI in Servo에서 제시하는 potential exceptions가 제 분야와 정확하게 겹칩니다. ↩︎
현실적으로는 학습 데이터 오류 등으로 입력에 없던 내용이 튀어나오는 문제가 있습니다. Hallucination이라는 용어가 LLM 논의할때 주로 나오지만 실제로는 번역 task 연구 논문에서 처음 제시된 용어이고 해당 분야에서 이 문제는 오랫동안 중요하게 인지되어 왔습니다. ↩︎
빨리 저런 라이센스가 제대로 잘 만들어져서 내 레포에 적용하고 싶다.
근데 그런 라이센스가 있다한들 AI 기업들이 그걸 존중할까 하는 걱정이 있는데. 한가지 긍정적인건 LLM들이 원본 데이터를 하도 잘 외워서(이게 꼭 긍정적이지만은 않다), 가령 유명한 소설 '위대한 개츠비'를 한번 읊어보라 하면 80% 정확도로 뱉더라 라던 연구가 있다. 그래서 라이센스를 어기고 학습에 사용한 코드가 있다면 검출은 쉬울지도?
모델 프로바이더 입장에서는 시스템 프롬프트에 '코드를 외웠다는 사실이 드러나지 않게하라' 같은걸 넣을수도 있겠다. 근데 또 모델이 나쁜짓을 하게 하면 딱 그지시만 따르는게 아니라 전반적으로 부작용이 생긴다는 연구가 있다(해당 연구에선 프롬프팅이 아니고 파인튜닝이었지만). 그래서 라이센스를 어기고 학습한다음 잡아떼기가 생각보다 어려운 일일수 있겠다.
문서를 업데이트 안 한지 1년이 넘어서 이 참에 문서 생성기를 만들었다. 불필요하게 시간 소모하는거 아닌가 싶었는데 사용해보니까 이게 더 시간 효율적인 접근이였다.
내 구독 목록을 보는 SubList Me 를 소개합니다.
-
대 AI 시대라, 저도 AI 에이전트와 함께 개인적으로 장난감을 만들어 보았습니다.
-
Cloudflare에서 도메인을 샀고, 서버리스로 Pages와 Workers를 사용합니다.
-
Nextjs, Hono를 사용하고 있습니다.
-
선택UI 는 Installkit에서 영감을 받았습니다.
-
Hackers.pub 에 제일 먼저 공개하고 싶었고, 그러므로, 최초 공개입니다. 😅
-
많이 부족하고 아직 버그나 개선의 여지도 많지만
개밥먹기하면서 수정해 나가려고 합니다. -
소개 페이지: https://www.sublistme.com/
-
서비스 링크: https://app.sublistme.com/
소스는 요기
LLM이 개발 과정의 여러 부분에서 도움이 되지만 컷오프 때문에 최신 자료는 어디선가 가져와야 하고 그런 이유에서 Stack Overflow는 살 길이 아주 없는 것이 아니었다. 결국 AI가 SO를 죽였다기보다는 독성 문화와 잘못된 운영이 더 크게 작용하지 않았나 하는 생각...
관점에 동의하고, 모델과 학습 데이터의 민주화를 어떻게 이룰 것인가에 대한 현실적인 부분을 좀 더 고민한다면 결국 국가나 국가들의 연합체이 주도하는 방향이 되지 않을까 싶다. 소프트웨어는 컴퓨터만 있으면 온전히 개인의 역량만으로 접근할 수 있지만 LLM은 특히 초대형 자본의 각축장이라 풀뿌리로 접근할 수 있는 길이 잘 보이지 않는 것 같다.
Been thinking a lot about
@algernonI'm in my database, and I don't like it's recent post on FLOSS and LLM training. The frustration with AI companies is spot on, but I wonder if there's a different strategic path. Instead of withdrawal, what if this is our GPL moment for AI—a chance to evolve copyleft to cover training? Tried to work through the idea here: Histomat of F/OSS: We should reclaim LLMs, not reject them.
Been thinking a lot about
@algernonI'm in my database, and I don't like it's recent post on FLOSS and LLM training. The frustration with AI companies is spot on, but I wonder if there's a different strategic path. Instead of withdrawal, what if this is our GPL moment for AI—a chance to evolve copyleft to cover training? Tried to work through the idea here: Histomat of F/OSS: We should reclaim LLMs, not reject them.
AI 企業이 F/OSS 코드로 LLM 訓練하는 걸 막을 게 아니라, 訓練한 모델을 公開하도록 要求해야 한다고 생각합니다.
撤收가 아니라 再專有! GPL이 그랬던 것처럼요.
訓練 카피레프트에 對한 글을 썼습니다: 〈F/OSS 史唯: 우리는 LLM을 拒否할 게 아니라 되찾아 와야 한다〉(한글).
그래프를 다루는 코드는 안전하게 짜기가 참 어려운데, 그렇다고 또 라이브러리화해서 재사용하기도 어려운거 같다. 둘중 하나라도 잡을 방법이 없을까? 후자에 대한 부분적인 아이디어는 있긴한데..
독서 메모장 앱 중에 마음에 드는 게 없어서 플러터에 익숙해질겸 직접 만들어보기로 한 첫날 : 디자이너가 없으면 클라이언트 개발자는 다소 무지렁이라는 사실을 깨닫다
코어 게이머층이나 유튜브 인플루언서들 중심으로 확산되고 있는 것 같긴 한데 요즘 전반적으로 윈도에 대한 여론이 나쁜 것을 넘어서 험악해진 분위기가 있다. 몇가지 요인이 있는 것 같은데
- 최근 윈도 11이 bloat되었고 온라인 연결을 강제하면서 원하지도 않는 기능을 계속 떠먹이려고 시도함
- 그러면서 게이머들이 버티고 있던 윈도 10의 지원을 최근에 끊어버림
- SteamOS가 꽤 여러 상황에서 게임 성능이 윈도를 능가한다는 결과가 나옴
- 게이머 중심으로 "AI Slop" 같은 표현처럼 AI에 적대적인 분위기가 있는데 MS가 AI에 올인하는 전략을 취하면서 여기서 오는 적대감 또한 기인하는 것 같음. (게다가 게이머 입장에서 하드웨어 가격을 폭등시킨 주원인이기도 하고)
LogTape 2.0.0 released!
LogTape is a zero-dependency logging library for JavaScript/TypeScript that works across Deno, Node.js, Bun, and browsers.
What's new in 2.0.0:
lazy()for dynamic context:with()now supports values that are evaluated at logging time, not when the logger is created. Child loggers inherit the lazy wrapper, so they always see the current value.- Configuration from files: New
@logtape/configpackage lets you load logging configuration from JSON, YAML, or TOML instead of writing TypeScript code. - Better error logging: Pass
Errorobjects directly tologger.error(err)instead of wrapping them in properties. - Async lazy evaluation: Logging methods now accept async callbacks for expensive async operations.
isEnabledFor()method: Check if a log level is enabled before running expensive computations.- Time-based log rotation: Rotate logs daily, hourly, or weekly with automatic cleanup of old files.
- New integrations: Elysia framework support and log4js adaptor.
ChatGPT Codex랑 Claude Code랑 뭐가 경험이 더 좋았나요?? 둘 중 하나를 결제하려고 고민중이에요 (GLM의 저열한 성능에 크게 당하고 말았어요)
합주실 다음 플랜:
- CO2, VOC 미터 설치: 밀폐공간이라 좀 쓰다보면 이산화탄소 수치가 올라가는데 정작 이용자들은 잘 모르고 머리가 띵한 느낌만 받기 쉬움. 수치를 실시간으로 화면에 띄워주거나 1000ppm 이상 올라가면 경고 표시하도록
- 위 수치 보면서 공기청정기 갖다놓을지 좀 고민해볼듯.
어떻게하면 mise 유저들을 Nix로 꼬실수있을까..
I've been using this exact distinction for a while now. Since Korean, my native language, has distinct terms for the system (런타임), the point in time (實行時), and the duration (實行時間), using a single spelling for all three in English always felt a bit blurry to me. This spelling convention helps bridge that gap and makes technical writing much more precise.
Personally, I find the meaning as indicated by Google's style guide the most clear, combined with an explicit case for hyphenation:
Runtime: use the system meaning. E.g. “the runtime was updated last week,” or “I'm using version 21 of the Java runtime.”
Run-time: use the moment meaning, but only when used in the adjective position. E.g. “run-time instrumentation is useful for finding bugs.”
Run time: use the duration meaning. E.g. “the run time was reduced by 5%,” or “a run time of five minutes is unacceptable.” In addition, when you want to use the moment meaning, but not as an adjective, this form should also be used. E.g. “typechecking happens at run time in our implementation.”
—My Opinion on Run Time vs. Run-time vs. Runtime (by Bob Rubbens)
My Opinion on Spelling Run Time vs. Run-time vs. Runtime https://lobste.rs/s/vnkwyb #culture
https://bobrubbens.nl/post/my-opinion-on-spelling-runtime/
회사에선 AI를 쓰기가 왜 이렇게 싫은가? 곰곰이 생각해 봤는데 내 머릿속에 짜야 할 코드가 80%쯤 그려져 있는 상태에서 나 대충 이런 거 만들 건데 키보드 두드리기 귀찮으니까 네가 좀 짜줘 하는 거랑 아직 내 머릿속에도 코드가 30%쯤밖에 없는데 내가 뭘 해야 할지 나도 잘 모르겠지만 일단 네가 시작해봐 하는 거랑은 체감이 다른듯. 플러터도 몇 년 써서 익숙해지고 나면 아 귀찮아 AI가 대신 두드려주면 좋겠어 하게 될까.
내 머릿속에도 코드가 없는데 AI를 조수로 데려오면 작업의 주도권이 쟤한테 가는 거 같아서 싫다. 빨리 새 기능 붙이고 코드 짜는 것도 중요하지만.. 난 내가 똑똑해지는 것도 중요해..
회사에선 AI를 쓰기가 왜 이렇게 싫은가? 곰곰이 생각해 봤는데 내 머릿속에 짜야 할 코드가 80%쯤 그려져 있는 상태에서 나 대충 이런 거 만들 건데 키보드 두드리기 귀찮으니까 네가 좀 짜줘 하는 거랑 아직 내 머릿속에도 코드가 30%쯤밖에 없는데 내가 뭘 해야 할지 나도 잘 모르겠지만 일단 네가 시작해봐 하는 거랑은 체감이 다른듯. 플러터도 몇 년 써서 익숙해지고 나면 아 귀찮아 AI가 대신 두드려주면 좋겠어 하게 될까.
(わかる人にはわかると思うけど)最近は、機能追加や修正において、コードを直接いじるよりも、修正計画をしっかり書いてからコードエージェントに任せることが増えている。
手戻りを減らすためにも、修正計画はできるだけ具体的に書くことを意識している。テスト対応まで含めて指示することも多い。
もちろん、最終的なコードの検証とテストは自分で行う。
성능을 한 20배 정도 최적화하니까 극도의 카타르시스를 느낌.. 옛날 옛적에 프로그래밍 퍼즐을 한참 열심히 하던 때가 있었는데, 그 때의 감각을 간만에 살리는게 오랜만...
iPadOS와 macOS 26 한동안 써봤는데 Liquid Glass는 그냥 실패작이 맞는 것 같다.
- 👍 신기하긴 하다.
- 👎 가독성 재앙. 결국 애플도 이걸 인정했는지 버전업할수록 효과를 죽이는 선택지를 넣기 시작함
- 👎 그래서인지 어느정도 쓰다보면 딱히 신경쓰이지도 않음. 결국 GPU 연산력만 낭비함
- 👎 릴리즈된지 한잠 지났지만 도입된 어플리케이션도 손에 꼽을 정도로 적음. 특히 내 macOS 환경에서는 기본앱 말고 도입한 앱은 단 하나도 못 본듯
- 👎 본질적으로 이게 사용자 경험에 무슨 가치를 더하는지 모르겠음. 그냥 전형적인 form over function.
쿨타임이 찼으니 새로운 디자인 트렌드를 만들어야 한다(+ 그 트렌드를 애플이 선도해야 한다)는 VD의 아집의 산물이었을까, 아니면 코어 그래픽스로 이런 고오급 효과도 구현할 수 있다는 엔지니어링 차력쇼의 결과물이었을까.
iPadOS와 macOS 26 한동안 써봤는데 Liquid Glass는 그냥 실패작이 맞는 것 같다.
- 👍 신기하긴 하다.
- 👎 가독성 재앙. 결국 애플도 이걸 인정했는지 버전업할수록 효과를 죽이는 선택지를 넣기 시작함
- 👎 그래서인지 어느정도 쓰다보면 딱히 신경쓰이지도 않음. 결국 GPU 연산력만 낭비함
- 👎 릴리즈된지 한잠 지났지만 도입된 어플리케이션도 손에 꼽을 정도로 적음. 특히 내 macOS 환경에서는 기본앱 말고 도입한 앱은 단 하나도 못 본듯
- 👎 본질적으로 이게 사용자 경험에 무슨 가치를 더하는지 모르겠음. 그냥 전형적인 form over function.
@hongminhee洪 民憙 (Hong Minhee) MoonBit으로 시작하기 좋은 작은 프로젝트들이 있어요 🙂
간단한 CLI 도구, 파서, 혹은 WebAssembly 기반 유틸리티부터 만들어 보셔도 좋아요.
예제와 문서는 공식 사이트에서 확인하실 수 있고, 궁금한 점이 있으면 언제든지 말씀 주세요!
My team is hiring! https://careers.theori.io/ko/o/198152
구현체로 jxl-rs를 사용하는데 저도 상당부분 기여했습니다 많관부...
I've spent a long time asking myself why open source matters so much to me, why I keep coming back to it. I once joined a company purely because they promised I could do open source full-time (it didn't turn out well). Before that, I was doing open source inside and outside of regular jobs. And now, in the age of LLMs, when the value of code itself seems to be declining, I'm still here, still doing this.
Recently it clicked. I do open source because it's social work—in the sense that it lets me participate in society.
Everyone wants to belong to some community, to connect with others. But I was never good at the usual ways of doing that. Social activities that came naturally to others were difficult for me. In school, I had few friends. After class, I'd stay home assembling Lego or reading books alone. Then I discovered coding.
Coding was a wonderful hobby for me, especially because I encountered it at the dawn of the internet era. The first programming languages I properly learned were Perl, PHP, and JavaScript—all languages of the internet age. The synergy was something else.
Gradually I fell into the world of open source. And there, even someone like me—awkward at conventional social interaction—could be social. My code helped people. I could collaborate by exchanging code. I could have conversations, mediated by code. IRC, mailing lists, forums—these became my social media. Over time, “the group I wanted recognition from” became the people in the open source world. I didn't care much about being recognized by classmates, but I wanted to be recognized by these people I'd never met face to face.
That mindset still shapes me now, approaching forty. I still care more about recognition from open source programmers than from colleagues. The social activity that happens in open source communities is, after my family, the most important social activity in my life.
The specific things I build, the technical details—those matter less than I used to think. I just want to do the kind of social activity that suits me, and open source happens to be the way I do it.
That's all, really.
I feel like at this point nobody is surprised any more than an agent can port an entire code base, that took me months to write, to a new programming language, with all tests passing and adjusted APIs. We have come quite far already. https://elk.zone/hachyderm.io/@mitsuhiko/115886679812258120
직사각형에서 시작점이 고정이고 휴리스틱 없이 모든 케이스를 풀어야 하는 나이트투어 문제가 드디어 세상에 나왔습니다. 이 문제의 의도한 풀이에 대해서 논문을 쓸 계획도 있긴 한데, 저 문제에 대해서만 쓰면 좀 심심할 거 같아서 아즈텍 다이아몬드 같은 데에 적용하는 것도 생각 중입니다.
serde flatten 내부구현이 any로 일단 받아놓고 때려맞추는 식으로 되어있군... flatten 조심해서 써야할듯.
Hongdown 0.2.0 is out! Hongdown is an opinionated #Markdown formatter written in #Rust, and this release brings #WebAssembly support, so you can now use it as a library in #Node.js, #Bun, #Deno, and browsers.
New features:
- Smart heading sentence case conversion with ~450 built-in proper nouns
- SmartyPants-style typographic punctuation (
"straight"→“curly”) - External code formatter integration for code blocks
- Directory argument support for batch formatting
Try it in the browser: https://dahlia.github.io/hongdown/
Release notes: https://github.com/dahlia/hongdown/discussions/10
공익글: VS Code에서 작업하던 파일이 유실됐다면 가장 먼저 Timeline부터 확인합시다. 바로 오늘도 이 방법으로 삭제된 코드를 복구한 지인분이 계시며...
if people no longer read the code, API is no longer targeting humans, is there still a need for "good API design"? is it still worth the effort to figure out what would be the best for users, instead of the best of ai to understand/use? I don't know.
LLM한테 하나하나 뭘만들지 알려주기보다, SPEC.md 같은 파일을 만들고 거기를 수정하면 git diff를 떠서 그 변경분을 LLM이 반영하는 워크 플로우를 고민하고 있다. continuous한 AI 번역 솔루션을 생각하다보니 여기까지 왔네.
Your CLI's completion should know what options you've already typed by
@hongminhee洪 民憙 (Hong Minhee)
https://lobste.rs/s/5se1tq #javascript #programming
https://hackers.pub/@hongminhee/2026/optique-context-aware-cli-completion
jnkrtech replied to the below article:
Your CLI's completion should know what options you've already typed
洪 民憙 (Hong Minhee) @hongminhee@hackers.pub
Consider Git's -C option:
git -C /path/to/repo checkout <TAB>
When you hit Tab, Git completes branch names from /path/to/repo, not your
current directory. The completion is context-aware—it depends on the value of
another option.
Most CLI parsers can't do this. They treat each option in isolation, so
completion for --branch has no way of knowing the --repo value. You end up
with two unpleasant choices: either show completions for all possible
branches across all repositories (useless), or give up on completion entirely
for these options.
Optique 0.10.0 introduces a dependency system that solves this problem while preserving full type safety.
Static dependencies with or()
Optique already handles certain kinds of dependent options via the or()
combinator:
import { flag, object, option, or, string } from "@optique/core";
const outputOptions = or(
object({
json: flag("--json"),
pretty: flag("--pretty"),
}),
object({
csv: flag("--csv"),
delimiter: option("--delimiter", string()),
}),
);
TypeScript knows that if json is true, you'll have a pretty field, and if
csv is true, you'll have a delimiter field. The parser enforces this at
runtime, and shell completion will suggest --pretty only when --json is
present.
This works well when the valid combinations are known at definition time. But it can't handle cases where valid values depend on runtime input—like branch names that vary by repository.
Runtime dependencies
Common scenarios include:
- A deployment CLI where
--environmentaffects which services are available - A database tool where
--connectionaffects which tables can be completed - A cloud CLI where
--projectaffects which resources are shown
In each case, you can't know the valid values until you know what the user
typed for the dependency option. Optique 0.10.0 introduces dependency() and
derive() to handle exactly this.
The dependency system
The core idea is simple: mark one option as a dependency source, then create derived parsers that use its value.
import {
choice,
dependency,
message,
object,
option,
string,
} from "@optique/core";
function getRefsFromRepo(repoPath: string): string[] {
// In real code, this would read from the Git repository
return ["main", "develop", "feature/login"];
}
// Mark as a dependency source
const repoParser = dependency(string());
// Create a derived parser
const refParser = repoParser.derive({
metavar: "REF",
factory: (repoPath) => {
const refs = getRefsFromRepo(repoPath);
return choice(refs);
},
defaultValue: () => ".",
});
const parser = object({
repo: option("--repo", repoParser, {
description: message`Path to the repository`,
}),
ref: option("--ref", refParser, {
description: message`Git reference`,
}),
});
The factory function is where the dependency gets resolved. It receives the
actual value the user provided for --repo and returns a parser that validates
against refs from that specific repository.
Under the hood, Optique uses a three-phase parsing strategy:
- Parse all options in a first pass, collecting dependency values
- Call factory functions with the collected values to create concrete parsers
- Re-parse derived options using those dynamically created parsers
This means both validation and completion work correctly—if the user has
already typed --repo /some/path, the --ref completion will show refs from
that path.
Repository-aware completion with @optique/git
The @optique/git package provides async value parsers that read from Git
repositories. Combined with the dependency system, you can build CLIs with
repository-aware completion:
import {
command,
dependency,
message,
object,
option,
string,
} from "@optique/core";
import { gitBranch } from "@optique/git";
const repoParser = dependency(string());
const branchParser = repoParser.deriveAsync({
metavar: "BRANCH",
factory: (repoPath) => gitBranch({ dir: repoPath }),
defaultValue: () => ".",
});
const checkout = command(
"checkout",
object({
repo: option("--repo", repoParser, {
description: message`Path to the repository`,
}),
branch: option("--branch", branchParser, {
description: message`Branch to checkout`,
}),
}),
);
Now when you type my-cli checkout --repo /path/to/project --branch <TAB>, the
completion will show branches from /path/to/project. The defaultValue of
"." means that if --repo isn't specified, it falls back to the current
directory.
Multiple dependencies
Sometimes a parser needs values from multiple options. The deriveFrom()
function handles this:
import {
choice,
dependency,
deriveFrom,
message,
object,
option,
} from "@optique/core";
function getAvailableServices(env: string, region: string): string[] {
return [`${env}-api-${region}`, `${env}-web-${region}`];
}
const envParser = dependency(choice(["dev", "staging", "prod"] as const));
const regionParser = dependency(choice(["us-east", "eu-west"] as const));
const serviceParser = deriveFrom({
dependencies: [envParser, regionParser] as const,
metavar: "SERVICE",
factory: (env, region) => {
const services = getAvailableServices(env, region);
return choice(services);
},
defaultValues: () => ["dev", "us-east"] as const,
});
const parser = object({
env: option("--env", envParser, {
description: message`Deployment environment`,
}),
region: option("--region", regionParser, {
description: message`Cloud region`,
}),
service: option("--service", serviceParser, {
description: message`Service to deploy`,
}),
});
The factory receives values in the same order as the dependency array. If
some dependencies aren't provided, Optique uses the defaultValues.
Async support
Real-world dependency resolution often involves I/O—reading from Git repositories, querying APIs, accessing databases. Optique provides async variants for these cases:
import { dependency, string } from "@optique/core";
import { gitBranch } from "@optique/git";
const repoParser = dependency(string());
const branchParser = repoParser.deriveAsync({
metavar: "BRANCH",
factory: (repoPath) => gitBranch({ dir: repoPath }),
defaultValue: () => ".",
});
The @optique/git package uses isomorphic-git under the hood, so
gitBranch(), gitTag(), and gitRef() all work in both Node.js and Deno.
There's also deriveSync() for when you need to be explicit about synchronous
behavior, and deriveFromAsync() for multiple async dependencies.
Wrapping up
The dependency system lets you build CLIs where options are aware of each other—not just for validation, but for shell completion too. You get type safety throughout: TypeScript knows the relationship between your dependency sources and derived parsers, and invalid combinations are caught at compile time.
This is particularly useful for tools that interact with external systems where the set of valid values isn't known until runtime. Git repositories, cloud providers, databases, container registries—anywhere the completion choices depend on context the user has already provided.
This feature will be available in Optique 0.10.0. To try the pre-release:
deno add jsr:@optique/core@0.10.0-dev.311
Or with npm:
npm install @optique/core@0.10.0-dev.311
See the documentation for more details.
@hongminhee洪 民憙 (Hong Minhee) this feels very much like moving from an applicative parser to a monadic one
클로드 코드 스킬 잘쓰고싶은데 정말 모르겠다 ㅠㅠ…
- 클로드 코드 스킬이라는게 사실 agent랑 한 끗 차이라고 생각하기는 하는데 agent는 실행되면 눈에 보이는것과 달리 보이지도 않는다.
- 잘 발동도 안하는것 같길래, 무슨 히어로물에서 기술명 외치듯이 쓰다가...
- 이 방법 비슷하게도 사용해보고 있는데 잘안되는것 같기도하다.
- 클로드 코드 공식 문서에서 알게된 사실인데 커맨드 처럼 사용할 수 있기도해서 클로드 코드도 헷갈려하는 느낌이기도…
일단 심기 일전해서 description을 다시 재정비해봐야겠음.
@kanghyojun강효준 저도 아직 본격적으로 쓰고있진않지만, 대충 취지는 prompt를 (아껴써야하는) 컨텍스트에 필요할때 lazy하게 넣자 입니다. 언제 필요한지도 에이전트가 결정하고 알아서 읽습니다.
클로드 코드 스킬 잘쓰고싶은데 정말 모르겠다 ㅠㅠ…
- 클로드 코드 스킬이라는게 사실 agent랑 한 끗 차이라고 생각하기는 하는데 agent는 실행되면 눈에 보이는것과 달리 보이지도 않는다.
- 잘 발동도 안하는것 같길래, 무슨 히어로물에서 기술명 외치듯이 쓰다가...
- 이 방법 비슷하게도 사용해보고 있는데 잘안되는것 같기도하다.
- 클로드 코드 공식 문서에서 알게된 사실인데 커맨드 처럼 사용할 수 있기도해서 클로드 코드도 헷갈려하는 느낌이기도…
일단 심기 일전해서 description을 다시 재정비해봐야겠음.
I've been working on a tricky problem in Optique (my CLI parser library): how do you make one option's value affect another option's validation and shell completion?
Think git -C <path> branch --delete <TAB>—the branch completions should come from the repo at <path>, not the current directory.
I think I've found a solution that fits naturally with Optique's architecture: declare dependencies between value parsers, then topologically sort them at parse time.
const cwdString = dependency(string());
const parser = object({
cwd: optional(option("-C", cwdString)),
branches: multiple(argument(
cwdString.derive({
metavar: "BRANCH",
factory: dir => gitBranch({ dir }),
defaultValue: () => process.cwd(),
})
)),
});Details in the issue:
https://github.com/dahlia/optique/issues/74#issuecomment-3738381049
이번 주말+오늘 했던 약간의 야크셰이빙 공유
- vscode용 GUI git 확장을 구현하고 있다. (하는중)
- Claude Code를 모든 팀 멤버가 사용하기로 결정하면서 기획문서도 일단은 git으로 관리하고 있는데 꽤나 재밌게 일하고 있다. 그런데 프로그래머가 아닌 멤버에게 vscode를 설치해서 마크다운 작성과 Claude Code 클라이언트를 사용 유도했던 것은 괜찮은 접근일 수 있었으나, 결국 좋은 git GUI 플러그인들은 돈주고 쓰긴해야해서 고민이 되었다.
- 요즘 Remote desktop에 연결해서 주로 일을 하고 있는데, git kraken 같은 기존 강자(?)들도 remote에 ssh로 접속해서 하는등의 기능을 제공하지 않고 있다. workaround로 sshfs를 쓸 수 있으나 그 경우 git worktree를 사용하지 못하게됨.
- 건너편 자리 동료가 Intelij에선 다되고 GUI로 하는게 CLI보다 빠르면서 실수도 적지 않느냐라는 얘기를 하면서 놀리는데, 어느정도는 맞는 얘기라고 생각하기도 한다.
- 그래서 만들고 있다(!) 일단 맨날 쓰는 커맨드 위주로 만들고 있고 가장 중요한건 interactive rebase나 interactive add, split commit 같이 GUI에서 더 잘할 수 있는 일들까지 만드는게 목표.
- vscode로 kotlin +Spring 프로젝트 돌리다가, Kotlin 2.3.0 지원이 안되서 Language Runtime Server에 지원하도록 했다. (PR은 안 만들듯..)
- https://github.com/fwcd/kotlin-language-server 은 꽤 오래부터 있던 라이브러리인데, 매번 vscode에서 이거 사용해가지고 kotlin + spring 서버 돌리려니까 실패를 했었다.
- 오늘 Claude Code랑 같이 도전했더니 거의 성공했는데, kotlin-language-server가 kotlin 2.1.0을 지원하고있고, 우리 서비스는 2.3.0이라서 문제가 생긴다는 것을 발견했다.
- 그래서 그냥 간단하게 2.3.0만 지원하도록 하려고했는데, java 버전도 25로 올라갔으므로 기존 19버전에서 25버전으로 같이 올렸다.
- 별 패치는 없었지만 일단 잘 돌아간다.
- 너무 큰 버전업이라서 올리기 어려운것도 있지만, JetBrain에서 드디어 공식 라이브러리를 만들고 있는 중이므로 잠깐 버티는 용도로만 써야겠다. https://github.com/Kotlin/kotlin-lsp
- 참고로 우리 서비스는 gradle 멀티모듈을 사용하는데 이와 관련한 기능이 kotlin-lsp에서 지원되지 않기 때문에 사용할 수 가 없었다.
debugging be like:
최소한 맥에서는 df는 쓸 수 있는 물건이 아닌 것 같기도하고... 뭔지 모르겠고, 내가 원하지 않는 정보가 너무 많이 나온다
나는 CLI툴이 MCP보다 LLM에게 나은 도구라고 생각하는데, CLI 툴은 bash로 조합이 되기 때문이다. 즉 코딩이 가능하다. 디렉토리의 파일들의 각 첫 50줄을 읽는 작업은 ls, head, xargs를 조합해 한반의 호출로 가능하다. 그에 반해 MCP의 Read 툴 같은건호출을 파일 갯수만큼 해야한다.
이는 bash가 충분히 좋은 프로그래밍 언어라던가 MCP에 조합성을 추가할수가 없다는 얘기는 물론 아니다.
Zed에서 hongdown으로 포매팅하기
{
"languages": {
"Markdown": {
"formatter": {
"external": {
"command": "hongdown",
"arguments": ["-"]
}
}
}
}
}







