洪 民憙 (Hong Minhee) :nonbinary:'s avatar

洪 民憙 (Hong Minhee) :nonbinary:

@hongminhee@hollo.social

1,107 following1,898 followers

An intersectionalist, feminist, and socialist living in Seoul (UTC+09:00). @tokolovesme's spouse. Who's behind @fedify, @hollo, and @botkit. Write some free software in , , , & . They/them.

서울에 사는 交叉女性主義者이자 社會主義者. 金剛兔(@tokolovesme)의 配偶者. @fedify, @hollo, @botkit 메인테이너. , , , 等으로 自由 소프트웨어 만듦.

()

Pinned

@hongminhee@hollo.social

Hello! I'm Hong Minhee (洪 民憙), an open source software engineer in my late 30s, living in Seoul, Korea. I'm bisexual and non-binary (they/them), and an enthusiastic advocate of free/open source software and the fediverse.

I work full-time on @fedify, an ActivityPub server framework in TypeScript, funded by @sovtechfund. I'm also the creator of @hollo, a single-user ActivityPub microblog; @botkit, an ActivityPub bot framework; Hackers' Pub, a fediverse platform for software developers; and LogTape, a logging library for JavaScript and TypeScript.

I have a long interest in East Asian languages (CJK) and Unicode. I post mostly in English here, though occasionally in Japanese or in mixed-script Korean (國漢文混用體), a traditional writing style that interleaves Chinese characters with the native Korean alphabet. Wanting to write in that style was actually one of the reasons I joined the fediverse. Feel free to talk to me in English, Korean, Japanese, or even Literary Chinese!

en.wikipedia.org

Korean mixed script - Wikipedia

Pinned

はじめまして!ソウル在住の30代後半のオープンソースソフトウェアエンジニア、洪 民憙ホン・ミンヒと申します。バイセクシュアル(bisexual)・ノンバイナリー(non-binary)で、自由・オープンソースソフトウェア(F/OSS)とフェディバース(fediverse)の熱烈な支持者です。

STF(@sovtechfund)の支援を受け、TypeScript用ActivityPubサーバーフレームワーク「@fedify」の開発に専念しています。他にも、おひとり様向けのActivityPubマイクロブログ「@hollo」、ActivityPubボットフレームワーク「@botkit」、ソフトウェア開発者向けフェディバースプラットフォームHackers' Pub、JavaScript・TypeScript用ロギングライブラリLogTapeなどの制作者でもあります。

東アジア言語(いわゆるCJK)とUnicodeにも興味があります。このアカウントでは主に英語で投稿していますが、時々日本語や国漢文混用体(漢字ハングル混じり文)の韓国語でも書いています。実はこの文体で書きたくてフェディバースを始めた、という経緯もあります。日本語、英語、韓国語、漢文でも気軽に話しかけてください!

speakerdeck.com

国漢文混用体からHolloまで

本発表では、韓国語の「国漢文混用体」(漢字ハングル混じり文)を自分のフェディバース投稿に実装したいという小さな目標から始まった旅路を共有します。 この目標を達成するために、ActivityPubのJSON-LDの複雑さやHTTP Signatures、WebFingerなどの仕様を理解する必要性に…

Pinned

安寧(안녕)하세요! 저는 서울에 살고 있는 30() 後半(후반)의 오픈 소스 소프트웨어 엔지니어 洪民憙(홍민희)입니다. 兩性愛者(양성애자)(bisexual)이자 논바이너리(non-binary)이며, 自由(자유)·오픈 소스 소프트웨어(F/OSS)와 聯合宇宙(연합우주)(fediverse)의 熱烈(열렬)支持者(지지자)이기도 합니다.

STF(@sovtechfund)의 支援(지원)을 받아 TypeScript() ActivityPub 서버 프레임워크 @fedify 開發(개발)專業(전업)으로 ()하고 있습니다. 그 ()에도 싱글 유저() ActivityPub 마이크로블로그 @hollo, ActivityPub 봇 프레임워크 @botkit, 소프트웨어 開發者(개발자)를 위한 聯合宇宙(연합우주) 플랫폼 Hackers' Pub, JavaScript·TypeScript() 로깅 라이브러리 LogTape ()製作者(제작자)이기도 합니다.

()아시아 言語(언어)(이른바 CJK)와 Unicode에도 關心(관심)이 많습니다. 이 計定(계정)에서는 ()英語(영어)로 포스팅하지만, 때때로 日本語(일본어)國漢文混用體(국한문 혼용체) 韓國語(한국어)로도 씁니다. 聯合宇宙(연합우주)에 오게 된 動機(동기) () 하나가 바로 國漢文混用體(국한문 혼용체)로 글을 쓰고 싶었기 때문이기도 하고요. 韓國語(한국어), 英語(영어), 日本語(일본어), 아니면 漢文(한문)으로도 말을 걸어주세요!

logtape.org

LogTape

Unobtrusive logging library with zero dependencies—library-first design for Deno, Node.js, Bun, browsers, and edge functions

@hongminhee@hackers.pub

We're excited to announce Optique 0.8.0! This release introduces powerful new features for building sophisticated CLI applications: the conditional() combinator for discriminated union patterns, the passThrough() parser for wrapper tools, and the new @optique/logtape package for seamless logging configuration.

Optique is a type-safe combinatorial CLI parser for TypeScript, providing a functional approach to building command-line interfaces with composable parsers and full type inference.

New conditional parsing with conditional()

Ever needed to enable different sets of options based on a discriminator value? The new conditional() combinator makes this pattern first-class. It creates discriminated unions where certain options only become valid when a specific discriminator value is selected.

import { conditional, object } from "@optique/core/constructs";
import { option } from "@optique/core/primitives";
import { choice, string } from "@optique/core/valueparser";

const parser = conditional(
  option("--reporter", choice(["console", "junit", "html"])),
  {
    console: object({}),
    junit: object({ outputFile: option("--output-file", string()) }),
    html: object({ outputFile: option("--output-file", string()) }),
  }
);
// Result type: ["console", {}] | ["junit", { outputFile: string }] | ...

Key features:

  • Explicit discriminator option determines which branch is selected
  • Tuple result [discriminator, branchValue] for clear type narrowing
  • Optional default branch for when discriminator is not provided
  • Clear error messages indicating which options are required for each discriminator value

The conditional() parser provides a more structured alternative to or() for discriminated union patterns. Use it when you have an explicit discriminator option that determines which set of options is valid.

See the conditional() documentation for more details and examples.

Pass-through options with passThrough()

Building wrapper CLI tools that need to forward unrecognized options to an underlying tool? The new passThrough() parser enables legitimate wrapper/proxy patterns by capturing unknown options without validation errors.

import { object } from "@optique/core/constructs";
import { option, passThrough } from "@optique/core/primitives";

const parser = object({
  debug: option("--debug"),
  extra: passThrough(),
});

// mycli --debug --foo=bar --baz=qux
// → { debug: true, extra: ["--foo=bar", "--baz=qux"] }

Key features:

  • Three capture formats: "equalsOnly" (default, safest), "nextToken" (captures --opt val pairs), and "greedy" (captures all remaining tokens)
  • Lowest priority (−10) ensures explicit parsers always match first
  • Respects -- options terminator in "equalsOnly" and "nextToken" modes
  • Works seamlessly with object(), subcommands, and other combinators

This feature is designed for building Docker-like CLIs, build tool wrappers, or any tool that proxies commands to another process.

See the passThrough() documentation for usage patterns and best practices.

LogTape logging integration

The new @optique/logtape package provides seamless integration with LogTape, enabling you to configure logging through command-line arguments with various parsing strategies.

# Deno
deno add --jsr @optique/logtape @logtape/logtape

# npm
npm add @optique/logtape @logtape/logtape

Quick start with the loggingOptions() preset:

import { loggingOptions, createLoggingConfig } from "@optique/logtape";
import { object } from "@optique/core/constructs";
import { parse } from "@optique/core/parser";
import { configure } from "@logtape/logtape";

const parser = object({
  logging: loggingOptions({ level: "verbosity" }),
});

const args = ["-vv", "--log-output=-"];
const result = parse(parser, args);
if (result.success) {
  const config = await createLoggingConfig(result.value.logging);
  await configure(config);
}

The package offers multiple approaches to control log verbosity:

  • verbosity() parser: The classic -v/-vv/-vvv pattern where each flag increases verbosity (no flags → "warning", -v"info", -vv"debug", -vvv"trace")
  • debug() parser: Simple --debug/-d flag that toggles between normal and debug levels
  • logLevel() value parser: Explicit --log-level=debug option for direct level selection
  • logOutput() parser: Log output destination with - for console or file path for file output

See the LogTape integration documentation for complete examples and configuration options.

Bug fix: negative integers now accepted

Fixed an issue where the integer() value parser rejected negative integers when using type: "number". The regex pattern has been updated from /^\d+$/ to /^-?\d+$/ to correctly handle values like -42. Note that type: "bigint" already accepted negative integers, so this change brings consistency between the two types.

Installation

# Deno
deno add jsr:@optique/core

# npm
npm add @optique/core

# pnpm
pnpm add @optique/core

# Yarn
yarn add @optique/core

# Bun
bun add @optique/core

For the LogTape integration:

# Deno
deno add --jsr @optique/logtape @logtape/logtape

# npm
npm add @optique/logtape @logtape/logtape

# pnpm
pnpm add @optique/logtape @logtape/logtape

# Yarn
yarn add @optique/logtape @logtape/logtape

# Bun
bun add @optique/logtape @logtape/logtape

Looking forward

Optique 0.8.0 continues our focus on making CLI development more expressive and type-safe. The conditional() combinator brings discriminated union patterns to the forefront, passThrough() enables new wrapper tool use cases, and the LogTape integration makes logging configuration a breeze.

As always, all new features maintain full backward compatibility—your existing parsers continue to work unchanged.

We're grateful to the community for feedback and suggestions. If you have ideas for future improvements or encounter any issues, please let us know through GitHub Issues. For more information about Optique and its features, visit the documentation or check out the full changelog.

optique.dev

Optique changelog | Optique

Type-safe combinatorial CLI parser for TypeScript

@krosylight@fosstodon.org

As a multi language speaker I'd love to have some built-in language selector in the web browser for each website. This feature shouldn't be part of the website but rather the browser...

@firesidefedi@social.firesidefedi.live

EU Commission's X account has been removed after the EU fined X for transparency failures at the tune $150,000,000. I hope someone at the EU is paying attention to X's behavior as well as our growing community here on the #fediverse .

https://www.euractiv.com/news/x-blocks-eu-commissions-advertising-account-after-e120-million-fine/

euractiv.com

X blocks EU Commission’s advertising account after €120 million fine | Euractiv

The move came after a weekend of online attacks on the EU by the social platform’s owner, Elon Musk

@hongminhee@hollo.social

韓国語でクィア(queer)を意味する言葉に、(「一般イルバン」ではないという意味で)「二般イバン」という言葉が有るのですが、本当によくできた言葉だと思います。

@kodingwarrior@hackers.pub

여기에 뒤늦게 올리지만 2차 모집도 진행중입니다! 이번엔 12월 15일(월)까지....!!

hackers.pub

Hackers Public @ Seoul 송년회 ---- 2025년의 마지막을 해커들과 함께해요. Hackers' Public @ Seoul 송년 네트워킹 밋업은 발표보다 대화, 형식보다 연결을 중심으로 진행됩니다.라이트닝 토크도 지원받습니다. 만들었던 것·배운 것·고민했던 이야기를 자유롭게 얘기해보도록 해요. 많은 관심 부탁드립니다~ 🗓 12/21(일) 14:30~18:30 🎤 라이트닝 토크 5분 자유 참여 📌 1차 모집: 11.26~12.5 (회원 대상) 신청하기 👉 https://event-us.kr/hackerspubseoul/event/117468

Hackers Public @ Seoul 송년회 ---- 2025년의 마지막을 해커들과 함께해요. Hackers' Public @ Seoul 송년 네트워킹 밋업은 발표보다 대화, 형식보다 연결을 중심으로 진행됩니다.라이트닝 토크도 지원받습니다. 만들었던 것·배운 것·고민했던 이야기를 자유롭게 얘기해보도록 해요. 많은 관심 부탁드립니다~ 🗓 12/21(일) 14:30~18:30 🎤 라이트닝 토크 5분 자유 참여 📌 1차 모집: 11.26~12.5 (회원 대상) 신청하기 👉 https://event-us.kr/hackerspubseoul/event/117468

@kodingwarrior@hackers.pub

Hackers Public @ Seoul 송년회 ---- 2025년의 마지막을 해커들과 함께해요.

Hackers' Public @ Seoul 송년 네트워킹 밋업은 발표보다 대화, 형식보다 연결을 중심으로 진행됩니다. 라이트닝 토크도 지원받습니다. 만들었던 것·배운 것·고민했던 이야기를 자유롭게 얘기해보도록 해요.

많은 관심 부탁드립니다~

event-us.kr

Hackers' Public @ Seoul 송년회 - 이벤터스

내가 원하는 행사를 개최하거나, 참여할 수 있는 플랫폼 - 이벤터스

@juergen_hubert@mementomori.social

I think I have identified a fairly significant flaw in how the currently operates. Hear me out.

The Fediverse currently consists of all sorts of different systems - , , , , , and so forth. And while they are all connected via the protocol, they all have different functionalities and different ways of presenting themselves. Which is as it should be, because Diversity Is Our Strength(TM).

However, it is here that the ActivityPub-based interactivity hits its limits - for usually, you can either experience the relevant system as it was intended, or you can interact with it, but not both - _unless_ you have an account on the same system (though not necessarily on the same instance).

Let's say that you are a Mastodon user who looks at another person's BookWyrm page. You scroll through their books, posts, and comments. Then you see some comment you want to comment on yourself, but can you do so?

Not directly. You need to figure out the URL of their comment, and then copy and paste that comment into the search bar of your Mastodon instance. Then it will show up in the same format as a Mastodon post, and you can interact with it - boost it, like it, comment on it.

Sure, it works, but it's a whole lot of tedious effort.

Or you can search for the user account in Mastodon and scroll through all their posts and comments as if they were a Mastodon user - and thus, you will miss out on all the unique user interface features of BookWyrm.

So what is missing?

Well, Mastodon already has an "Open original page" feature when looking at someone's post. What we need is an "Open original page AND AUTHENTICATE" feature. This way, the target instance (whatever software they are using) could acknowledge the viewer as an external user who could nevertheless fully interact with the local user interface, including the ability to boost, like, and make comments.

This is something that should be theoretically possible to implement, right?

A Mastodon menu that pops up when clicking on another user's post, showing the options:

"Expand this post
Open original page
Copy link to post"
ALT text

A Mastodon menu that pops up when clicking on another user's post, showing the options: "Expand this post Open original page Copy link to post"

@hongminhee@hollo.social

I asked Nano Banana to draw an ad poster for a fictional McDonald's menu item called the “McBook,” and this is the image that was generated.

A satirical advertisement poster showing a McDonald's meal where the burger has been replaced by an open laptop designed to look like a cheeseburger. The laptop lid is a sesame seed bun with a yellow Golden Arches logo, the keyboard area is a beef patty with lettuce and cheese, and green wires act as garnish. It rests on a tray with french fries and a drink in a McDonald's booth. Text on the poster reads “McBook. Served Hot.” and “I'm lovin' it. Powered by the M-Series Chip.”
ALT text

A satirical advertisement poster showing a McDonald's meal where the burger has been replaced by an open laptop designed to look like a cheeseburger. The laptop lid is a sesame seed bun with a yellow Golden Arches logo, the keyboard area is a beef patty with lettuce and cheese, and green wires act as garnish. It rests on a tray with french fries and a drink in a McDonald's booth. Text on the poster reads “McBook. Served Hot.” and “I'm lovin' it. Powered by the M-Series Chip.”

@TypeScript@fosstodon.org
@pkgupdt@hl.pkgu.net

불교기(일본어 仏旗)는 한국에서는 자주 보이지 않지만 불교 상징으로서 외국에서는 종종 보인다. 이 깃발을 채택한 세계불교도우의회(WFB: World Fellowship of Buddhists)에는 한국의 불교 종파들도 참여하고 있다.

Enrayku-ji, Mt. Hiei, Shiga-ken, Japan.
ALT text

Enrayku-ji, Mt. Hiei, Shiga-ken, Japan.

@hongminhee@hollo.social
@botkit@hollo.social · Reply to BotKit by Fedify :botkit:

BotKitは、ActivityPubボットを作るためのTypeScriptフレームワークです。既存のMastodon/Misskeyボットとの違いは、ボット自体が独立したサーバーとして動作すること。プラットフォームのアカウントは不要です。

文字数制限もなければ、APIレート制限に悩まされることもありません。

bot.onMention = async (session, message) => {
  await message.reply(text`こんにちは、${message.actor}さん!`);
};

フェデレーション、HTTP Signatures、配送キューといったActivityPub周りの処理はFedifyがすべて引き受けます。ボットのロジックを書くだけです。

DenoでもNode.jsでも動きます。

https://botkit.fedify.dev/

botkit.fedify.dev

BotKit by Fedify

A framework for creating your ActivityPub bots

@botkit@hollo.social · Reply to BotKit by Fedify :botkit:

BotKit은 ActivityPub 봇을 만드는 프레임워크입니다. 일반적인 Mastodon/Misskey 봇과 다른 점은, 봇 자체가 독립된 서버로 돌아간다는 겁니다. 플랫폼 계정이 필요 없습니다.

글자 수 제한도 없고, API 호출 제한에 시달릴 일도 없습니다.

bot.onMention = async (session, message) => {
  await message.reply(text`안녕하세요, ${message.actor}님!`);
};

연합(federation), HTTP Signatures, 메시지 전달 같은 관련 처리는 Fedify가 알아서 해줍니다. 봇 로직만 짜면 되는 거죠.

.js 둘 다 지원합니다.

https://botkit.fedify.dev/

botkit.fedify.dev

BotKit by Fedify

A framework for creating your ActivityPub bots

@botkit@hollo.social

is a framework for building bots. The difference from typical Mastodon/Misskey bots? Your bot runs as its own independent server—no platform account needed.

This means no character limits, no rate limiting headaches, no API restrictions.

bot.onMention = async (session, message) => {
  await message.reply(text`Hi, ${message.actor}!`);
};

The ActivityPub stuff (federation, HTTP Signatures, delivery queues) is handled by under the hood. You just write your bot logic.

Works with both and .js.

https://botkit.fedify.dev/

botkit.fedify.dev

BotKit by Fedify

A framework for creating your ActivityPub bots