Hello, I'm an open source software engineer in my late 30s living in #Seoul, #Korea, and an avid advocate of #FLOSS and the #fediverse.
I'm the creator of @fedify, an #ActivityPub server framework in #TypeScript, @hollo, an ActivityPub-enabled microblogging software for single users, and @botkit, a simple ActivityPub bot framework.
We're excited to announce Optique 0.4.0, which brings significant improvements
to help text organization, enhanced documentation capabilities, and introduces
comprehensive Temporal API support.
Optique is a type-safe combinatorial CLI parser for TypeScript that makes
building command-line interfaces intuitive and maintainable. This release
focuses on making your CLI applications more user-friendly and maintainable.
Better help text organization
One of the most visible improvements in Optique 0.4.0 is the enhanced help text
organization. You can now label and group your options more effectively, making
complex CLIs much more approachable for users.
Labeled merge groups
The merge() combinator now accepts an optional label parameter, solving
a common pain point where developers had to choose between clean code structure
and organized help output:
// Before: unlabeled merged options appeared scatteredconst config = merge(connectionOptions, performanceOptions);// Now: group related options under a clear sectionconst config = merge( "Server Configuration", // New label parameter connectionOptions, performanceOptions);
This simple addition makes a huge difference in help text readability,
especially for CLIs with many options spread across multiple reusable modules.
The resulting help output clearly organizes options under
the Server Configuration section:
Demo app showcasing labeled merge groupsUsage: demo-merge.ts --host STRING --port INTEGER --timeout INTEGER --retries INTEGERServer Configuration: --host STRING Server hostname or IP address --port INTEGER Port number for the connection --timeout INTEGER Connection timeout in seconds --retries INTEGER Number of retry attempts
The new group() combinator
For cases where merge() doesn't apply, the new group()
combinator lets you wrap any parser with a documentation label:
// Group mutually exclusive options under a clear sectionconst outputFormat = group( "Output Format", or( map(flag("--json"), () => "json"), map(flag("--yaml"), () => "yaml"), map(flag("--xml"), () => "xml"), ));
This is particularly useful for organizing mutually exclusive flags, multiple
inputs, or any parser that doesn't natively support labeling. The resulting
help text becomes much more scannable and user-friendly.
Here's how the grouped output format options appear in the help text:
Demo app showcasing group combinatorUsage: demo-group.ts --json demo-group.ts --yaml demo-group.ts --xmlOutput Format: --json Output in JSON format --yaml Output in YAML format --xml Output in XML format
Rich documentation support
Optique 0.4.0 introduces comprehensive documentation fields that can be added
directly through the run() function, eliminating the need to modify parser
definitions for documentation purposes.
Brief descriptions, detailed explanations, and footers
Both @optique/core/facade and @optique/run now support brief,
description, and footer options through the run() function:
import { run } from "@optique/run";import { message } from "@optique/core/message";const result = run(parser, { brief: message`A powerful data processing tool`, description: message`This tool provides comprehensive data processing capabilities with support for multiple formats and transformations. It can handle JSON, YAML, and CSV files with automatic format detection.`, footer: message`Examples: myapp process data.json --format yaml myapp validate config.toml --strictFor more information, visit https://example.com/docs`, help: "option"});
These documentation fields appear in both help output and error messages
(when configured), providing consistent context throughout your CLI's user
experience.
The complete help output demonstrates the rich documentation features with brief
description, detailed explanation, option descriptions, default values,
and footer information:
A powerful data processing toolUsage: demo-rich-docs.ts [--port INTEGER] [--format STRING] --verbose STRINGThis tool provides comprehensive data processing capabilities with support formultiple formats and transformations. It can handle JSON, YAML, and CSV fileswith automatic format detection. --port INTEGER Server port number [3000] --format STRING Output format [json] --verbose STRING Verbosity levelExamples: myapp process data.json --format yaml myapp validate config.toml --strictFor more information, visit https://example.com/docs
These documentation fields appear in both help output and error messages
(when configured), providing consistent context throughout your CLI's user
experience.
Display default values
A frequently requested feature is now available: showing default values
directly in help text. Enable this with the new showDefault option when
using withDefault():
Default values are automatically dimmed when colors are enabled, making them
visually distinct while remaining readable.
The help output shows default values clearly marked next to each option:
Usage: demo-defaults.ts [--port INTEGER] [--format STRING] --port INTEGER Server port number [3000] --format STRING Output format [json]
Temporal API support
Optique 0.4.0 introduces a new package, @optique/temporal, providing
comprehensive support for the modern Temporal API. This brings type-safe
parsing for dates, times, durations, and time zones:
import { instant, duration, zonedDateTime } from "@optique/temporal";import { option } from "@optique/core/parser";const parser = object({ // Parse ISO 8601 timestamps timestamp: option("--at", instant()), // Parse durations like "PT30M" or "P1DT2H" timeout: option("--timeout", duration()), // Parse zoned datetime with timezone info meeting: option("--meeting", zonedDateTime()),});
The temporal parsers return native Temporal objects with full functionality:
The merge() combinator now supports up to 10 parsers (previously 5), and
the tuple() parser has improved type inference using TypeScript's const
type parameter. These enhancements enable more complex CLI structures while
maintaining perfect type safety.
Breaking changes
While we've maintained backward compatibility for most APIs, there are a few
changes to be aware of:
The Parser.getDocFragments() method now uses DocState<TState> instead
of direct state values (only affects custom parser implementations)
The merge() combinator now enforces stricter type
constraints at compile time, rejecting non-object-producing parsers
Learn more
For a complete list of changes, bug fixes, and improvements, see the
full changelog.
We hope these improvements make building CLI applications with Optique even
more enjoyable. As always, we welcome your feedback and contributions on
GitHub.
We're excited to announce Optique 0.4.0, which brings significant improvements
to help text organization, enhanced documentation capabilities, and introduces
comprehensive Temporal API support.
Optique is a type-safe combinatorial CLI parser for TypeScript that makes
building command-line interfaces intuitive and maintainable. This release
focuses on making your CLI applications more user-friendly and maintainable.
Better help text organization
One of the most visible improvements in Optique 0.4.0 is the enhanced help text
organization. You can now label and group your options more effectively, making
complex CLIs much more approachable for users.
Labeled merge groups
The merge() combinator now accepts an optional label parameter, solving
a common pain point where developers had to choose between clean code structure
and organized help output:
// Before: unlabeled merged options appeared scatteredconst config = merge(connectionOptions, performanceOptions);// Now: group related options under a clear sectionconst config = merge( "Server Configuration", // New label parameter connectionOptions, performanceOptions);
This simple addition makes a huge difference in help text readability,
especially for CLIs with many options spread across multiple reusable modules.
The resulting help output clearly organizes options under
the Server Configuration section:
Demo app showcasing labeled merge groupsUsage: demo-merge.ts --host STRING --port INTEGER --timeout INTEGER --retries INTEGERServer Configuration: --host STRING Server hostname or IP address --port INTEGER Port number for the connection --timeout INTEGER Connection timeout in seconds --retries INTEGER Number of retry attempts
The new group() combinator
For cases where merge() doesn't apply, the new group()
combinator lets you wrap any parser with a documentation label:
// Group mutually exclusive options under a clear sectionconst outputFormat = group( "Output Format", or( map(flag("--json"), () => "json"), map(flag("--yaml"), () => "yaml"), map(flag("--xml"), () => "xml"), ));
This is particularly useful for organizing mutually exclusive flags, multiple
inputs, or any parser that doesn't natively support labeling. The resulting
help text becomes much more scannable and user-friendly.
Here's how the grouped output format options appear in the help text:
Demo app showcasing group combinatorUsage: demo-group.ts --json demo-group.ts --yaml demo-group.ts --xmlOutput Format: --json Output in JSON format --yaml Output in YAML format --xml Output in XML format
Rich documentation support
Optique 0.4.0 introduces comprehensive documentation fields that can be added
directly through the run() function, eliminating the need to modify parser
definitions for documentation purposes.
Brief descriptions, detailed explanations, and footers
Both @optique/core/facade and @optique/run now support brief,
description, and footer options through the run() function:
import { run } from "@optique/run";import { message } from "@optique/core/message";const result = run(parser, { brief: message`A powerful data processing tool`, description: message`This tool provides comprehensive data processing capabilities with support for multiple formats and transformations. It can handle JSON, YAML, and CSV files with automatic format detection.`, footer: message`Examples: myapp process data.json --format yaml myapp validate config.toml --strictFor more information, visit https://example.com/docs`, help: "option"});
These documentation fields appear in both help output and error messages
(when configured), providing consistent context throughout your CLI's user
experience.
The complete help output demonstrates the rich documentation features with brief
description, detailed explanation, option descriptions, default values,
and footer information:
A powerful data processing toolUsage: demo-rich-docs.ts [--port INTEGER] [--format STRING] --verbose STRINGThis tool provides comprehensive data processing capabilities with support formultiple formats and transformations. It can handle JSON, YAML, and CSV fileswith automatic format detection. --port INTEGER Server port number [3000] --format STRING Output format [json] --verbose STRING Verbosity levelExamples: myapp process data.json --format yaml myapp validate config.toml --strictFor more information, visit https://example.com/docs
These documentation fields appear in both help output and error messages
(when configured), providing consistent context throughout your CLI's user
experience.
Display default values
A frequently requested feature is now available: showing default values
directly in help text. Enable this with the new showDefault option when
using withDefault():
Default values are automatically dimmed when colors are enabled, making them
visually distinct while remaining readable.
The help output shows default values clearly marked next to each option:
Usage: demo-defaults.ts [--port INTEGER] [--format STRING] --port INTEGER Server port number [3000] --format STRING Output format [json]
Temporal API support
Optique 0.4.0 introduces a new package, @optique/temporal, providing
comprehensive support for the modern Temporal API. This brings type-safe
parsing for dates, times, durations, and time zones:
import { instant, duration, zonedDateTime } from "@optique/temporal";import { option } from "@optique/core/parser";const parser = object({ // Parse ISO 8601 timestamps timestamp: option("--at", instant()), // Parse durations like "PT30M" or "P1DT2H" timeout: option("--timeout", duration()), // Parse zoned datetime with timezone info meeting: option("--meeting", zonedDateTime()),});
The temporal parsers return native Temporal objects with full functionality:
The merge() combinator now supports up to 10 parsers (previously 5), and
the tuple() parser has improved type inference using TypeScript's const
type parameter. These enhancements enable more complex CLI structures while
maintaining perfect type safety.
Breaking changes
While we've maintained backward compatibility for most APIs, there are a few
changes to be aware of:
The Parser.getDocFragments() method now uses DocState<TState> instead
of direct state values (only affects custom parser implementations)
The merge() combinator now enforces stricter type
constraints at compile time, rejecting non-object-producing parsers
Learn more
For a complete list of changes, bug fixes, and improvements, see the
full changelog.
We hope these improvements make building CLI applications with Optique even
more enjoyable. As always, we welcome your feedback and contributions on
GitHub.
In #WebFinger, are there any relations that use the template property instead of the href property, excluding the http://ostatus.org/schema/1.0/subscribe relation?
Fediverse Auxiliary Service Providers(FASP) は、Fediverseサーバーソフトウェアと連携し、サーバー内に存在しない機能を補完する独立したサービスプロバイダーの仕組みです。これらのサービスは、単一のサーバーでは実現困難な機能や、サーバーソフトウェアに含まれていない機能を提供することを目的としています。[1]
- Mark push notifications as supported @luckkerr - Added an example of a TootSDK graphical client using SharingGRDB https://github.com/thinkpractice - Add a new example for an app @konstantin - Cross-flavour feature requirements, target fediverse servers @konstantin - [BREAKING] Allow caching and restoring TootClient without calling connect() @konstantin
서론
해외에서는 새 기기를 켜고 액티베이션 마법사만 따라가면 eSIM이 자동으로 이전되는 경험이 보편화되어 있습니다. 반면 한국은 여전히 IMEI/EID 전산 등록과 재다운로드 수수료(2,750원)가 당연한 절차로 남아 있습니다. 저는 이 구조가 보안 명분을 앞세운 과도한 통제이며, 결과적으로 소비자에게 비용과 불편을 전가한다고 판단합니다.
1) 자동 이전이 ‘가능한 […]
서론
해외에서는 새 기기를 켜고 액티베이션 마법사만 따라가면 eSIM이 자동으로 이전되는 경험이 보편화되어 있습니다. 반면 한국은 여전히 IMEI/EID 전산 등록과 재다운로드 수수료(2,750원)가 당연한 절차로 남아 있습니다. 저는 이 구조가 보안 명분을 앞세운 과도한 통제이며, 결과적으로 소비자에게 비용과 불편을 전가한다고 판단합니다.
1) 자동 이전이 ‘가능한 기술’인데, 왜 한국에서는 막혀 있습니까
애플은 공식 문서에서 eSIM Quick Transfer/Carrier Activation으로 설정 중 자동 이전을 지원한다고 명시합니다. 즉, 통신사가 지원만 하면 사용자는 추가 절차 없이 새 기기로 번호를 옮길 수 있습니다. 한국에서 이 기능이 실사용 단계에서 일반화되지 못한 현실은, 기술의 한계가 아니라 정책 선택의 결과입니다.
2) ‘보안’이라는 이유로 강제되는 IMEI/EID 전산 등록
국내 통신사들은 개통·교체 전에 IMEI와 EID 확인·입력을 전제로 안내합니다. 이는 해외에서 QR 스캔만으로 개통되는 일반적 경험과 정면으로 어긋납니다. 보안 통제를 위해 장치와 회선을 강하게 전산 매핑해 놓은 탓에, 사용자는 기기 교체 때마다 통신사 절차를 다시 밟아야 합니다.
3) 소비자에게 전가되는 2,750원 재다운로드 비용
eSIM은 원격 발급이 본질인데, 한국에서는 재다운로드 때마다 2,750원이 청구됩니다. 일부 사업자는 다운로드 시마다 비용 발생을 명시하고, 이동·교체 시에도 추가 비용을 예고합니다. 간혹 특정 이슈 대응으로 한시적 1회 면제를 운영하기도 하지만, 구조 자체는 유료 재발급에 고정되어 있습니다. 이 비용 모델은 국제적 사용자 경험과 거꾸로 가는 대표 사례입니다.
4) ‘동일 명의’ 강제와 타인 USIM 장착 불가 고지
국내 안내에는 동일 명의 사용만 허용하고, 타인 명의 USIM 장착 시 사용 불가를 명시하는 조항들이 반복됩니다. 범죄 악용 방지를 위한 취지라 하더라도, 결과적으로 합법적·정상적 이용자의 유연성을 지나치게 훼손합니다. eSIM의 장점인 멀티 프로파일·유연한 전환은 사실상 반쪽으로 전락합니다.
5) ‘보이스피싱 방지’ 명분, 정말 최선의 방법입니까
보이스피싱이 심각한 것은 사실입니다. 그러나 전면적 전산 매핑 + 반복 수수료가 최적의 해법이라고 보기는 어렵습니다.
해외는 자동 이전을 허용하되, 위험 징후를 행동 기반 탐지와 계정·기기 평판으로 관리합니다.
한국은 원천 봉쇄와 비용 장벽을 우선시해 정상 이용자에게 과도한 마찰을 강요합니다.
그 결과, 같은 기술을 쓰면서도 한국만 유독 불편하고 비싸게 쓰게 됩니다.
6) 국제 표준과 사용자 기대에 역행하는 정책 선택
GSMA가 설계한 원격 발급 생태계의 요체는 원격·즉시·반복 가능한 프로비저닝입니다. 한국의 현재 운영 방식은 이 철학과 엇갈립니다. 자동 이전을 지원하는 제조사 생태계가 이미 존재하는데도, 우리는 통신사 전산 절차와 비용에 발목이 잡혀 있습니다. 그 피해는 사용자 시간·비용·호환성으로 귀결됩니다.
7) 무엇을 바꾸어야 합니까 — 구체적 제언
자동 이전(Quick Transfer) 전면 지원: 제조사 표준 워크플로를 국내에서도 기본값으로 허용해야 합니다.
재다운로드 수수료 폐지: 원격 발급 특성상 반복 과금은 설득력이 약합니다. 최소한 무상 재발급을 기본으로 전환해야 합니다.
전산 매핑의 탄력 운용: 실명·명의 관리는 유지하되, 정상 이용자 시나리오(새 기기 교체, 임시 기기 사용)를 자동 이전으로 흡수해야 합니다.
위험 기반 보안으로의 전환: 일괄 차단·전면 신고식 대신, 행동·패턴 기반 탐지와 사후 추적을 강화하는 편이 사용자 불편을 최소화합니다.
해외 단말·자급제 차별 해소: “해외향 단말 제외” 같은 조항은 글로벌 사용자 경험을 훼손합니다. 합리적 검증 절차 후 개통 허용으로 가야 합니다.
결론
한국의 eSIM 제도는 기술이 아니라 정책의 문제입니다. 통신사가 자동 이전을 막고전산 매핑과 수수료를 계속 고집하는 한, 우리는 불필요한 절차와 비용을 감당해야 합니다. 보이스피싱 방지라는 대의를 폄하할 생각은 없지만, 그 목표를 위해 정상 사용자 경험을 이 정도로 훼손하는 것은 과잉 규제입니다. 이제는 국제 표준과 사용자 기대에 맞춰 자동 이전을 기본값으로, 수수료는 예외로 재설계할 때입니다.
ALT text details이미지에는 스마트폰과 함께 배치된 SIM 카드가 보입니다. SIM 카드는 하얀색 테두리에 금색 접촉 부분이 있는 형태로, 스마트폰의 SIM 슬롯에 삽입될 수 있습니다.