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

洪 民憙 (Hong Minhee) :nonbinary:

@hongminhee@hollo.social · 986 following · 1354 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 메인테이너. , , , 等으로 自由 소프트웨어 만듦.

()

Jazz de Ville – Jazz's avatar
Jazz de Ville – Jazz

@jdv_jazz@mastodon.nl

Cannonball Adderley & The Bossa Rio Sextet - Batida Diferentes (Feat. Sergio Mendes)

Cover: Cannonball Adderley & The Bossa Rio Sextet - Batida Diferentes (Feat. Sergio Mendes)
ALT text detailsCover: Cannonball Adderley & The Bossa Rio Sextet - Batida Diferentes (Feat. Sergio Mendes)
Masanori Ogino 𓀁's avatar
Masanori Ogino 𓀁

@omasanori@mstdn.maud.io · Reply to Masanori Ogino 𓀁's post

先に書いておくと、RDFのシリアライズ形式は必ずしもXMLでなければならないわけではなく、Turtleなど、JSONくらい《軽い》文法もあります。

kanzaki.com/memo/2006/02/21-1

Masanori Ogino 𓀁's avatar
Masanori Ogino 𓀁

@omasanori@mstdn.maud.io

そんなことをしたら流行ってないのは承知の上で、JSON-LDではなくRDFを使ったActivityPubの世界をみたいかも。

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

@hongminhee@hollo.social

Released Optique 0.8.0, a type-safe CLI parser for TypeScript.

This version adds conditional() for branching based on a discriminator option, passThrough() for forwarding unknown options to underlying tools, and a new @optique/logtape package for configuring LogTape via CLI.

https://hackers.pub/@hongminhee/2025/optique-080

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

@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.

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

@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.

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

@hongminhee@hollo.social · Reply to Carlana :v_trans:​'s post

@carlana Haha, maybe, but I haven't heard of these word yet!

Kagami is they/them 🏳️‍⚧️'s avatar
Kagami is they/them 🏳️‍⚧️

@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...

Fireside Fedi's avatar
Fireside Fedi

@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/

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

@hongminhee@hollo.social

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

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

@hongminhee@hollo.social · Reply to 洪 民憙 (Hong Minhee) :nonbinary:'s post

오늘 liftIO 2025에서 發表(발표)한 〈Optique: TypeScript의 타입 推論(추론)으로 CLI 有效性(유효성) 檢査(검사)代替(대체)하기〉의 發表(발표) 資料(자료)共有(공유)합니다! 들어주신 모든 분들께 感謝(감사) 드립니다.

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

@hongminhee@hollo.social

내 트리를 꾸며줘!

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

@hongminhee@hollo.social · Reply to Jaeyeol Lee (a.k.a. kodingwarrior) :vim:'s post

@kodingwarrior 아니면 버티컬 마우스는 어떠세요? 저는 버티컬 마우스랑 같이 써요. ABKO에서 나오는 이런 거 하나 싸게 사시면… (저도 저거 쓰고 있습니다.)

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

@hongminhee@hackers.pub

내일은 liftIO 2025에서 발표… 떨린다…

Jaeyeol Lee's avatar
Jaeyeol Lee

@kodingwarrior@hackers.pub

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



RE: https://hackers.pub/@kodingwarrior/019abed2-f2e0-79fe-ada8-6b150ae0d840

Jaeyeol Lee's avatar
Jaeyeol Lee

@kodingwarrior@hackers.pub

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

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

많은 관심 부탁드립니다~

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

@hongminhee@hollo.social · Reply to Jaeyeol Lee (a.k.a. kodingwarrior) :vim:'s post

@kodingwarrior 麻婆丼(마보돈) 먹고 싶네요…

현준's avatar
현준

@yihyunjoon@hackers.pub · Reply to 洪 民憙 (Hong Minhee) :nonbinary:'s post

@hongminhee 저요저요~

bgl gwyng's avatar
bgl gwyng

@bgl@hackers.pub · Reply to 洪 民憙 (Hong Minhee) :nonbinary:'s post

@hongminhee 저 가요~

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

@hongminhee@hollo.social · Reply to 초무's post

@2chanhaeng I'm not interested in ergo keyboards… 😂

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

@hongminhee@hollo.social

() () 土曜日(토요일)liftIO 2025에 오시는 분 계신가요?

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

@hongminhee@hollo.social · Reply to wwj's post

@z9mb1 :blobcateyes:

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

@hongminhee@hollo.social

Lately, I've been wanting to get a new, full aluminum keyboard with an HHKB layout. I'm holding back though, since I already have so many keyboards at home…

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

@hongminhee@hollo.social · Reply to radioactivestardust's post

@bookstardust @dokuwiki Okay, I'm looking into it!

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

@hongminhee@hollo.social · Reply to Christian Westrom's post

@wildwestrom 귀찮음…? 😂

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

@hongminhee@hollo.social

올해를 마무리하는 블로그 글을 쓰고 있는데, 올해 뭔가 한 게 많긴 하구나…

Jürgen Hubert's avatar
Jürgen Hubert

@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 detailsA 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"
洪 民憙 (Hong Minhee) :nonbinary:'s avatar
洪 民憙 (Hong Minhee) :nonbinary:

@hongminhee@hollo.social

겨울 되니까 意欲(의욕) 全般(전반)이 다 低下(저하)된다… 오늘도 () 거 안 하고 時間(시간)만 보냈네… 😩

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

@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 detailsA 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's avatar
TypeScript

@TypeScript@fosstodon.org

We've got some updates on TypeScript 7! The new native port

- can type-check any project
- supports --build and --incremental
- has rich editor features implemented
- is still 10x faster

and is ready for you to try today!

devblogs.microsoft.com/typescr

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

@hongminhee@hollo.social

12月中旬、弟と一緒に、1ヶ月間の出張に行っている妻に会いに東京へ行くことにした。

pkg update's avatar
pkg update

@pkgupdt@hl.pkgu.net

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

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