Skip to content

Add configuration file support for CLI#562

Closed
sij411 wants to merge 28 commits intofedify-dev:mainfrom
sij411:feat/cli-config
Closed

Add configuration file support for CLI#562
sij411 wants to merge 28 commits intofedify-dev:mainfrom
sij411:feat/cli-config

Conversation

@sij411
Copy link
Contributor

@sij411 sij411 commented Feb 10, 2026

Summary

  • Added TOML configuration file support for persisting CLI options
  • Configuration files are loaded hierarchically from system, user, and project directories
  • Added --config (-C) option to specify a custom configuration file path
  • Added --ignore-config option to skip loading configuration files
  • Integrated bindConfig from @optique/config for commands: lookup, webfinger, tunnel, relay, inbox, and nodeinfo

Closes #265

File changes

New files

  • packages/cli/src/config.ts - Configuration schema and loading logic using Valibot

Modified files

  • packages/cli/src/mod.ts - Integrated runWithConfig for hierarchical config loading
  • packages/cli/src/options.ts - Added --config and --ignore-config options, wrapped options with bindConfig
  • packages/cli/src/lookup.ts - Bound lookup options with config
  • packages/cli/src/lookup.test.ts - Added tests for authorizedFetchOption with config
  • packages/cli/src/nodeinfo.ts - Bound nodeinfo options with config
  • packages/cli/src/inbox.tsx - Bound inbox options with config
  • packages/cli/src/relay.ts - Bound relay options with config
  • packages/cli/src/tunnel.ts - Updated tunnel command
  • packages/cli/src/webfinger/command.ts - Bound webfinger options with config
  • packages/cli/src/webfinger/mod.test.ts - Updated tests for bindConfig compatibility
  • packages/cli/deno.json - Added @optique/config dependencies
  • packages/cli/package.json - Added @optique/config dependencies
  • docs/cli.md - Added configuration file documentation
  • CHANGES.md - Added changelog entry for Version 2.0.0

Removed files

  • packages/cli/src/globals.ts - Relocated contents to appropriate modules

Test plan

  • Verify configuration file loading from all hierarchical locations
  • Test --config option with custom config file path
  • Test --ignore-config option skips all config files
  • Verify CLI arguments take precedence over config file values
  • Run deno task test in packages/cli to verify all tests pass

🤖 Generated with Claude Code

@issues-auto-labeler issues-auto-labeler bot added component/build Build system and packaging component/cli CLI tools related labels Feb 10, 2026
@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello @sij411, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request significantly enhances the Fedify CLI by introducing robust configuration file support. Users can now define default options for various commands using TOML files, which are loaded hierarchically. This change streamlines the CLI experience by reducing the need for repetitive command-line arguments and improves reproducibility. The integration leverages new configuration management libraries and includes comprehensive documentation and testing.

Highlights

  • CLI Configuration File Support: Introduced support for TOML configuration files to persist CLI options across different commands. Configuration files are loaded hierarchically from system, user, and project directories, with later files taking precedence.
  • New CLI Options for Configuration Management: Added --config (-C) to specify a custom configuration file path and --ignore-config to bypass all configuration files, providing greater control over CLI behavior.
  • Integration with CLI Commands: Integrated configuration binding for lookup, webfinger, tunnel, relay, inbox, and nodeinfo commands, allowing their options to be configured via TOML files.
  • Dependency Updates and Refactoring: Updated various package dependencies, including the addition of @optique/config, smol-toml, and valibot for configuration handling. Refactored global options and logging configuration into dedicated modules.
  • Improved Collection Traversal: Enhanced the traverseCollection() function to correctly handle inline-paged collections where CollectionPage objects are embedded without explicit IDs, improving compatibility with platforms like Mastodon.
Changelog
  • CHANGES.md
    • Added a changelog entry for Version 2.0.0 detailing the new TOML configuration file support for CLI options, including hierarchical loading, --config, and --ignore-config options, and integration with lookup, webfinger, tunnel, and relay commands.
  • docs/cli.md
    • Added extensive documentation for the new configuration file feature, including file locations, usage of --config and --ignore-config options, and an example TOML structure for various CLI commands.
  • docs/package.json
    • Updated workspace: dependency specifiers to workspace:^.
  • examples/cloudflare-workers/package.json
    • Updated workspace: dependency specifiers to workspace:^.
  • examples/elysia/package.json
    • Updated workspace: dependency specifiers to workspace:^.
  • examples/express/package.json
    • Updated workspace: dependency specifiers to workspace:^.
  • examples/fastify/package.json
    • Updated workspace: dependency specifiers to workspace:^.
  • examples/koa/package.json
    • Updated workspace: dependency specifiers to workspace:^.
  • examples/next-integration/package.json
    • Updated workspace: dependency specifiers to workspace:^.
  • examples/next14-app-router/package.json
    • Updated workspace: dependency specifiers to workspace:^.
  • examples/next15-app-router/package.json
    • Updated workspace: dependency specifiers to workspace:^.
  • examples/sveltekit-sample/package.json
    • Updated workspace: dependency specifiers to workspace:^.
  • mise.toml
    • Added a new task check:manifest:workspace-protocol to enforce the use of workspace:^ or workspace:~ in package.json files.
  • packages/amqp/deno.json
    • Updated the package version from 2.0.0 to 1.10.3.
    • Expanded the publish.exclude array for better file exclusion.
  • packages/amqp/package.json
    • Updated the package version from 2.0.0 to 1.10.3.
  • packages/cfworkers/deno.json
    • Updated the package version from 2.0.0 to 1.10.3.
  • packages/cfworkers/package.json
    • Updated the package version from 2.0.0 to 1.10.3.
  • packages/cli/deno.json
    • Updated the package version from 2.0.0 to 1.10.3.
    • Added new imports for @optique/config, es-toolkit, smol-toml, and valibot.
    • Expanded the exclude list to include package.json, src/install.mjs, and src/run.mjs.
  • packages/cli/package.json
    • Updated the package version from 2.0.0 to 1.10.3.
    • Added type, files, bin, scripts, engines, os, and cpu fields.
    • Moved existing type, engines, and bin fields to new locations.
    • Added new dependencies for @optique/config, smol-toml, and valibot.
  • packages/cli/src/config.ts
    • Added a new file defining the configuration schema for CLI commands using Valibot and a utility function tryLoadToml for parsing TOML files.
  • packages/cli/src/globals.ts
    • Removed the file, relocating its contents to other modules.
  • packages/cli/src/inbox.tsx
    • Imported bindConfig and configContext.
    • Updated follow, acceptFollow, actorName, actorSummary, and authorizedFetch options to use bindConfig for configuration file integration.
    • Replaced tunnelOption with createTunnelOption.
  • packages/cli/src/init/command.ts
    • Updated the import path for debugOption.
  • packages/cli/src/log.ts
    • Reordered imports for consistency.
    • Moved the configureLogging function from globals.ts to this module.
  • packages/cli/src/lookup.test.ts
    • Added new test cases for authorizedFetchOption to verify its behavior with and without configuration files, including firstKnock and tunnelService defaults.
  • packages/cli/src/lookup.ts
    • Imported bindConfig and configContext.
    • Updated authorizedFetchOption, traverseOption, format, separator, and timeout to use bindConfig for configuration file integration.
    • Added userAgentOption to the command definition.
    • Adjusted firstKnock default value handling.
  • packages/cli/src/mod.ts
    • Imported runWithConfig, configOption, envPaths, deepMerge, readFileSync, join, parseToml, configContext, and tryLoadToml.
    • Modified the main command execution to use runWithConfig for hierarchical configuration loading.
    • Updated help option handling to exit on show.
  • packages/cli/src/nodeinfo.ts
    • Imported bindConfig and configContext.
    • Updated nodeInfoOption (raw, bestEffort, noFavicon, metadata) to use bindConfig for configuration file integration.
    • Updated import paths for debugOption and userAgentOption.
    • Simplified conditional checks for raw, bestEffort, and metadata options.
  • packages/cli/src/options.ts
    • Imported bindConfig, getUserAgent, Config, and configContext.
    • Refactored tunnelServiceOption to use bindConfig.
    • Introduced createTunnelOption for command-specific tunnel configurations.
    • Defined debugOption and userAgentOption using bindConfig.
    • Added configOption to handle --config and --ignore-config arguments.
  • packages/cli/src/relay.ts
    • Imported bindConfig and configContext.
    • Updated protocol, persistent, port, name, acceptFollow, and rejectFollow options to use bindConfig for configuration file integration.
    • Replaced tunnelOption with createTunnelOption.
  • packages/cli/src/tunnel.ts
    • Updated import paths for configureLogging and debugOption.
  • packages/cli/src/webfinger/command.ts
    • Imported bindConfig and configContext.
    • Updated allowPrivateAddresses and maxRedirection options to use bindConfig for configuration file integration.
    • Added userAgentOption to the command definition.
  • packages/cli/src/webfinger/mod.test.ts
    • Updated test cases for webFingerCommand to reflect changes in default values and bindConfig behavior, specifically how invalid option values now fall back to defaults instead of causing parse failures.
  • packages/denokv/deno.json
    • Updated the package version from 2.0.0 to 1.10.3.
    • Expanded the publish.exclude array for better file exclusion.
  • packages/elysia/deno.json
    • Updated the package version from 2.0.0 to 1.10.3.
    • Expanded the publish.exclude array for better file exclusion.
  • packages/elysia/package.json
    • Updated the package version from 2.0.0 to 1.10.3.
  • packages/express/deno.json
    • Updated the package version from 2.0.0 to 1.10.3.
    • Expanded the publish.exclude array for better file exclusion.
  • packages/express/package.json
    • Updated the package version from 2.0.0 to 1.10.3.
  • packages/fastify/deno.json
    • Updated the package version from 2.0.0 to 1.10.3.
    • Expanded the publish.exclude array for better file exclusion.
  • packages/fastify/package.json
    • Updated the package version from 2.0.0 to 1.10.3.
    • Updated workspace: dependency specifiers to workspace:^.
  • packages/fedify/deno.json
    • Updated the package version from 2.0.0 to 1.10.3.
    • Added a new export entry for ./vocab.
  • packages/fedify/package.json
    • Updated the package version from 2.0.0 to 1.10.3.
    • Added a new export entry for ./vocab.
  • packages/fedify/src/federation/idempotency.test.ts
    • Added a test case to confirm that Federation.setInboxListeners() defaults to a 'per-inbox' idempotency strategy.
  • packages/fedify/src/vocab/mod.ts
    • Added a new module that re-exports from @fedify/vocab and marks itself as deprecated, guiding users to the dedicated @fedify/vocab package.
  • packages/fedify/tsdown.config.ts
    • Added src/vocab/mod.ts to the list of entry points for the build configuration.
  • packages/fixture/deno.json
    • Updated the package version from 2.0.0 to 1.10.3.
  • packages/fixture/src/fixtures/example.com/inline-paged-collection.json
    • Added a new fixture file representing an inline-paged ActivityPub collection.
  • packages/fixture/src/fixtures/example.com/inline-paged/a.json
    • Added a new fixture file representing a page within an inline-paged ActivityPub collection.
  • packages/fresh/deno.json
    • Updated the package version from 2.0.0 to 1.10.3.
    • Expanded the publish.exclude array for better file exclusion.
  • packages/h3/deno.json
    • Updated the package version from 2.0.0 to 1.10.3.
    • Expanded the publish.exclude array for better file exclusion.
  • packages/h3/package.json
    • Updated the package version from 2.0.0 to 1.10.3.
  • packages/hono/deno.json
    • Updated the package version from 2.0.0 to 1.10.3.
    • Expanded the publish.exclude array for better file exclusion.
  • packages/hono/package.json
    • Updated the package version from 2.0.0 to 1.10.3.
  • packages/koa/deno.json
    • Updated the package version from 2.0.0 to 1.10.3.
    • Expanded the publish.exclude array for better file exclusion.
  • packages/koa/package.json
    • Updated the package version from 2.0.0 to 1.10.3.
  • packages/lint/deno.json
    • Updated the package version from 2.0.0 to 1.10.3.
    • Expanded the publish.exclude array for better file exclusion.
  • packages/lint/package.json
    • Updated the package version from 2.0.0 to 1.10.3.
  • packages/nestjs/package.json
    • Updated the package version from 2.0.0 to 1.10.3.
  • packages/next/package.json
    • Updated the package version from 2.0.0 to 1.10.3.
  • packages/postgres/deno.json
    • Updated the package version from 2.0.0 to 1.10.3.
  • packages/postgres/package.json
    • Updated the package version from 2.0.0 to 1.10.3.
  • packages/redis/deno.json
    • Updated the package version from 2.0.0 to 1.10.3.
  • packages/redis/package.json
    • Updated the package version from 2.0.0 to 1.10.3.
  • packages/relay/deno.json
    • Updated the package version from 2.0.0 to 1.10.3.
    • Expanded the publish.exclude array for better file exclusion.
  • packages/relay/package.json
    • Updated the package version from 2.0.0 to 1.10.3.
  • packages/sqlite/deno.json
    • Updated the package version from 2.0.0 to 1.10.3.
  • packages/sqlite/package.json
    • Updated the package version from 2.0.0 to 1.10.3.
  • packages/sveltekit/deno.json
    • Updated the package version from 2.0.0 to 1.10.3.
    • Expanded the publish.exclude array for better file exclusion.
  • packages/sveltekit/package.json
    • Updated the package version from 2.0.0 to 1.10.3.
  • packages/testing/deno.json
    • Updated the package version from 2.0.0 to 1.10.3.
  • packages/testing/package.json
    • Updated the package version from 2.0.0 to 1.10.3.
  • packages/vocab-runtime/deno.json
    • Updated the package version from 2.0.0 to 1.10.3.
    • Expanded the publish.exclude array for better file exclusion.
  • packages/vocab-runtime/package.json
    • Updated the package version from 2.0.0 to 1.10.3.
  • packages/vocab-tools/deno.json
    • Updated the package version from 2.0.0 to 1.10.3.
    • Expanded the publish.exclude array for better file exclusion.
  • packages/vocab-tools/package.json
    • Updated the package version from 2.0.0 to 1.10.3.
  • packages/vocab/deno.json
    • Updated the package version from 2.0.0 to 1.10.3.
    • Expanded the publish.exclude array for better file exclusion.
  • packages/vocab/package.json
    • Updated the package version from 2.0.0 to 1.10.3.
  • packages/vocab/src/lookup.test.ts
    • Added a new test case for traverseCollection to verify its behavior with inline-paged collections.
  • packages/vocab/src/lookup.ts
    • Modified the traverseCollection function to correctly handle collections where the first property contains an inline CollectionPage without an explicit id.
  • packages/webfinger/deno.json
    • Updated the package version from 2.0.0 to 1.10.3.
    • Expanded the publish.exclude array for better file exclusion.
  • packages/webfinger/package.json
    • Updated the package version from 2.0.0 to 1.10.3.
  • pnpm-lock.yaml
    • Updated various dependency versions, including @optique/config, smol-toml, and valibot.
    • Changed workspace: specifiers to workspace:^ across multiple packages.
Activity
  • The pull request introduces a new feature for CLI configuration file support.
  • New files were added to define the configuration schema and loading logic.
  • Existing CLI command modules were modified to integrate with the new configuration system.
  • Documentation for the CLI was updated to include details about the new configuration feature.
  • Test cases were added and updated to ensure the correct behavior of configuration loading and option binding.
  • Dependency management files (deno.json, package.json, pnpm-lock.yaml) were updated to reflect new dependencies and versioning conventions.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces configuration file support for the CLI, which is a great enhancement for user experience. The implementation uses @optique/config and valibot for schema validation, which is a solid approach. I've found a few areas for improvement, including a logic issue in how a configuration option is handled, some inconsistencies in default values and documentation, and a recurring pattern in the usage of bindConfig that could be simplified for better maintainability. All original comments have been retained as they do not contradict the provided rules.

@sij411 sij411 force-pushed the feat/cli-config branch 2 times, most recently from 2e3b62a to 40e1964 Compare February 12, 2026 08:56
@codecov
Copy link

codecov bot commented Feb 12, 2026

Codecov Report

❌ Patch coverage is 84.61538% with 48 lines in your changes missing coverage. Please review.
✅ All tests successful. No failed tests found.

Files with missing lines Patch % Lines
packages/cli/src/options.ts 71.01% 20 Missing ⚠️
packages/cli/src/lookup.ts 87.83% 9 Missing ⚠️
packages/cli/src/nodeinfo.ts 80.85% 9 Missing ⚠️
packages/cli/src/config.ts 89.85% 7 Missing ⚠️
packages/cli/src/webfinger/command.ts 89.47% 2 Missing ⚠️
packages/cli/src/log.ts 96.87% 1 Missing ⚠️
Files with missing lines Coverage Δ
packages/cli/src/tunnel.ts 93.18% <100.00%> (ø)
packages/cli/src/log.ts 82.92% <96.87%> (+7.92%) ⬆️
packages/cli/src/webfinger/command.ts 96.36% <89.47%> (-3.64%) ⬇️
packages/cli/src/config.ts 89.85% <89.85%> (ø)
packages/cli/src/lookup.ts 42.08% <87.83%> (+2.66%) ⬆️
packages/cli/src/nodeinfo.ts 43.82% <80.85%> (+1.23%) ⬆️
packages/cli/src/options.ts 77.65% <71.01%> (-17.08%) ⬇️
🚀 New features to boost your workflow:
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

sij411 and others added 22 commits February 12, 2026 20:36
The globals.ts file mixed unrelated concerns: CLI option definitions and
logging configuration. This refactoring improves code organization by moving
each piece to its natural home:

 -  debugOption moved to options.ts, where all other CLI options are defined
 -  configureLogging() moved to log.ts, where recordingSink and other logging
    utilities already reside

This eliminates globals.ts entirely and makes the codebase easier to navigate
by grouping related functionality together.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Introduce config.ts that consolidates configuration handling:

 -  Valibot schemas for validating config structure (global debug option,
    command-specific sections for webfinger, lookup, inbox, relay, nodeinfo)
 -  TOML parsing via smol-toml library
 -  Hierarchical config loading from system (/etc/fedify/config.toml),
    user (~/.config/fedify/config.toml), and project (.fedify.toml) levels
 -  Recursive merging where later configs override earlier ones

This lays the groundwork for issue fedify-dev#265.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Introduce configOption with two mutually exclusive flags:

 -  -c, --config PATH: loads an additional configuration file on top of the
    standard hierarchy (system, user, project)
 -  -I, --ignore-config: skips all configuration files entirely, useful for
    CI environments requiring reproducible behavior

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The config module now delegates file loading and merging to @optique/config
instead of implementing custom logic. This removes:

- Manual config file path resolution
- Multi-file loading and merging logic
- Custom TOML parsing with error handling

The configOption now uses withDefault() to properly handle the case when
neither --ignore-config nor --config is specified.

Also removed short flags (-I, -c) to keep only long flags (--ignore-config,
--config) for clarity.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Implement config file loading that merges multiple sources in order:

1. /etc/fedify/config.toml (system-wide, silently skipped if missing)
2. ~/.config/fedify/config.toml (user config)
3. ./.fedify.toml (project config)
4. --config PATH (custom, throws on error if specified but missing)

Use Optique's runWithConfig with load callback for two-pass parsing,
and es-toolkit's merge for deep merging config objects.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
[ci skip]
🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Integrate Optique's bindConfig() to allow CLI options to fall back to
config file values. Uses type assertion on the key function return type
to properly narrow types when defaults are provided.

Commands updated:

-   relay: protocol, port, name
-   inbox: actorName, actorSummary, authorizedFetch
-   webfinger: userAgent, allowPrivateAddress, maxRedirection
-   lookup: userAgent, timeout
-   nodeinfo: userAgent

Also fixes version mismatches across workspace packages (1.10.3).

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add tunnel section to config schema and wrap the service option with
bindConfig() to allow tunnel service to be configured via config file.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add missing fields to config schema:
- lookup: firstKnock, defaultFormat, separator
- relay: persistent, acceptFollow, rejectFollow
- nodeinfo: raw, bestEffort, noFavicon, metadata

Add bindConfig() for:
- lookup: separator
- relay: persistent

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Extend config file support for more CLI options:

- lookup: authorizedFetch, traverse, suppressErrors, format (defaultFormat)
- nodeinfo: raw, bestEffort, noFavicon, metadata

The nodeinfo options were restructured from an or() discriminated union to
a flat object structure to enable bindConfig integration. This simplifies
the runtime checks from `"raw" in command && command.raw` to `command.raw`.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This version includes a fix for type inference with bindConfig and
multiple() for array options.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Refine config schema to only support fields listed in the issue spec:

- Global settings: debug, userAgent, logFile, tunnelService
- webfinger: allowPrivateAddress, maxRedirection
- lookup: authorizedFetch, firstKnock, traverse, suppressErrors,
  defaultFormat, separator, timeout
- inbox: actorName, actorSummary, authorizedFetch, noTunnel, follow,
  acceptFollow
- relay: protocol, port, name, persistent, noTunnel, acceptFollow,
  rejectFollow
- nodeinfo: raw, bestEffort, showFavicon, showMetadata

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Bind follow and acceptFollow arrays with config defaults
- Fix actorName/actorSummary to use ?? fallback instead of type cast
- Fix authorizedFetch to have proper boolean default
- Use createTunnelOption("inbox") for tunnel options

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Bind userAgent to global config.userAgent (optional)
- Bind allowPrivateAddresses with default false
- Bind maxRedirection without default (optional)
- Remove type casts in favor of proper undefined handling

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Bind authorizedFetch, firstKnock, traverse, suppressErrors with defaults
- Bind format (defaultFormat) and separator with defaults
- Bind timeout without default (optional)
- Add shared userAgentOption from options.ts
- Replace type casts with ?? fallbacks for type safety

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Upgrade @optique/config, @optique/core, @optique/run to 0.10.0-dev.348
which fixes a bug where bindConfig.complete crashed with undefined state
when no CLI args were consumed.

Update test expectations to reflect bindConfig behavior:

 -  userAgent now returns default value instead of undefined
 -  Invalid option values fall back to default instead of failing

See: dahlia/optique#94

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
sij411 and others added 5 commits February 12, 2026 20:36
Documents the new TOML configuration file feature for @fedify/cli in
the Version 2.0.0 section.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The noFavicon option was incorrectly reading showFavicon from config.
When showFavicon was true, noFavicon would also be true, which is inverted.
Changed to use strict equality check (=== false) so noFavicon is only true
when showFavicon is explicitly set to false.

Also updated CHANGES.md to include inbox and nodeinfo in the list of
commands with configuration support.

Additionally simplified some bindConfig key functions:

 -  Removed redundant type assertion in lookup.ts firstKnock
 -  Removed redundant nullish coalescing in determineSpec
 -  Changed `as number` to `?? default` for port and maxRedirection

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@sij411 sij411 marked this pull request as ready for review February 12, 2026 12:43
@sij411
Copy link
Contributor Author

sij411 commented Feb 12, 2026

/gemini review

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces TOML configuration file support for the CLI, which is a great enhancement for usability. The implementation is solid, using @optique/config to bind options and a hierarchical loading system. I've identified a couple of areas for improvement in error handling to make the new feature more robust and user-friendly. I also found a small typo in package.json that could affect Deno users. Overall, great work on this feature.

"engines": {
"node": ">=20.0.0",
"bun": ">=1.2.0",
"denp": ">=2.0.0"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The engines field contains "denp", which appears to be a typo for "deno". This could prevent engine checks from working correctly in Deno environments.

Suggested change
"denp": ">=2.0.0"
"deno": ">=2.0.0"

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what -_-

Comment on lines +50 to +52
const custom = parsed.configPath
? parseToml(readFileSync(parsed.configPath, "utf-8"))
: {};
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

When a user provides a custom configuration file via --config that is invalid (e.g., doesn't exist, is unreadable, or contains invalid TOML), the application currently crashes with an unhandled exception. It would be better to catch this error and provide a more user-friendly message before exiting. Re-throwing a more descriptive error will allow runWithConfig to handle it gracefully.

      const custom = (() => {
        if (!parsed.configPath) return {};
        try {
          return parseToml(readFileSync(parsed.configPath, "utf-8"));
        } catch (error) {
          const message = error instanceof Error ? error.message : String(error);
          throw new Error(
            `Failed to load or parse config file "${parsed.configPath}": ${message}`,
          );
        }
      })();

Comment on lines +110 to +112
} catch {
return {};
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The current catch block swallows all errors silently, including syntax errors in the TOML file or file permission issues. This can make it difficult for users to debug their configuration. It would be more user-friendly to log a warning for errors other than "file not found" (ENOENT), which is an expected case for optional config files.

  } catch (error) {
    if (error instanceof Error && "code" in error && error.code === "ENOENT") {
      // File not found is not an error in this context.
      return {};
    }
    const message = error instanceof Error ? error.message : String(error);
    console.error(`Warning: Could not load or parse config file at "${path}": ${message}`);
    return {};
  }

@sij411 sij411 closed this Feb 12, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

component/build Build system and packaging component/cli CLI tools related

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add configuration file support to Fedify CLI

3 participants