Skip to content

buf format should accept multiple file paths as positional arguments #4233

@julioz

Description

@julioz

Feature

Summary

The buf format command currently accepts only a single <source> positional argument. This makes it incompatible with tools like lint-staged, which pass multiple file paths as positional arguments to formatters. Supporting multiple file paths would greatly improve the developer experience for teams using buf format in pre-commit hooks.

Current Behavior

$ buf format -w file1.proto file2.proto file3.proto
# Error: accepts at most 1 arg(s), received 3

The command fails when given multiple files as positional arguments.

Expected Behavior

$ buf format -w file1.proto file2.proto file3.proto
# Successfully formats all three files

The command should accept multiple file paths and format each of them.

Use Case

Many teams use lint-staged with husky (or similar tools like pre-commit) to run formatters only on staged files during git commits. This is a common pattern for maintaining code quality without formatting the entire codebase on every commit.

lint-staged works by passing the list of staged files as positional arguments to the configured command:

{
  "**/*.proto": "buf format -w"
}

When multiple .proto files are staged, lint-staged executes:

buf format -w path/to/file1.proto path/to/file2.proto path/to/file3.proto

This pattern works out-of-the-box with most formatters:

  • prettier --write
  • biome check --write
  • eslint --fix
  • black (Python) ✅
  • gofmt -w
  • buf format -w

Current Workaround

The workaround is to use a bash wrapper that converts positional arguments to --path flags:

{
  "**/*.proto": "bash -c 'args=(); for f in \"$@\"; do args+=(--path \"$f\"); done; buf format -w . \"${args[@]}\"' _"
}

While functional, this workaround:

  • Is not intuitive or discoverable
  • Adds complexity to the configuration
  • May not work on all platforms (Windows without bash)
  • Requires understanding of bash array manipulation

Proposed Solution

Accept multiple file paths as positional arguments:

# Format multiple specific files
buf format -w file1.proto file2.proto file3.proto

# Equivalent to current behavior with --path
buf format -w . --path file1.proto --path file2.proto --path file3.proto

Alternative: Accept files via stdin

Another option would be to accept file paths from stdin, similar to xargs:

echo "file1.proto file2.proto" | buf format -w --stdin

Additional Context

This is a common pattern request for CLI tools that integrate with the JavaScript/TypeScript ecosystem's pre-commit tooling. The lint-staged project has over 13k GitHub stars and is widely used, so improving compatibility would benefit many developers working with Protocol Buffers.

Related tools that have addressed similar requests:

  • Prettier accepts multiple files: prettier --write file1 file2 file3
  • ESLint accepts multiple files: eslint --fix file1 file2 file3
  • Biome accepts multiple files: biome check --write file1 file2 file3

Metadata

Metadata

Assignees

No one assigned

    Labels

    FeatureNew feature or request

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions