# Bazel rule extensions

DevFeed: [Bazel rule extensions](<https://devfeed.tech/articles/bazel-rule-extensions-25413.md>)

Original publisher: [Read original article](<https://smileykeith.com/2025/10/31/bazel-rule-extensions/>)

Author: Keith Smiley

Published: 2025-10-31T17:00:00Z

Content type: tutorial

Language: en

Sources: [Keith Smiley](<https://devfeed.tech/sources/keith-smiley.md>)

Topics: [Programming](<https://devfeed.tech/topics/programming.md>), [Code](<https://devfeed.tech/topics/code.md>), [Polymorphism](<https://devfeed.tech/topics/polymorphism.md>)

Tags: [bazel](<https://devfeed.tech/tags/bazel.md>), [extensions](<https://devfeed.tech/tags/extensions.md>), [inheritance](<https://devfeed.tech/tags/inheritance.md>)

## AI overview

This article explains Bazel 8.0 rule extensions, which let developers inherit and modify the behavior of existing rules without reimplementing them or maintaining a fork. It presents examples of post-processing rule outputs and manipulating providers, including a use case for consistent debug information across macOS and Linux.

## Source excerpt

One of Bazel's best features is being able to easily write custom rules specific to your project. This is great for many use cases, but when what you really want is to enhance the behavior of existing rules, historically your options have been limited. What you would often do is wrap the existing rule in a macro, and add some number of custom rules to try and achieve the desired effect. When really what you want is to edit the existing rule, without having to re-implement all of its functionality (or maintain a fork). With Bazel 8.0, Googlers added a few new ways to extend existing rules that can help with this use case. In this post we will look at the aptly named rule extensions feature and some practical use cases I have found for it. Basic rule extensions Rule extensions allow you to inherit the behavior of an existing rule, similar to class inheritance in object-oriented programming. Importantly you can make a few modifications to augment the behavior of the rule to your liking. Let's say you have a rule that concatenates the given srcs: def _foo_impl(ctx): output = ctx.actions.declare_file("output.txt") ctx.actions.run_shell( inputs = ctx.files.srcs, outputs = [output], command = "cat {} > {}".format(" ".join([src.path for src in ctx.files.srcs]), output.path), ) return [DefaultInfo(files = depset([output]))] foo = rule( implementation = _foo_impl, attrs = { "srcs": attr.label_list(allow_files = True), }, ) Now let's assume in your project, you want the output file to be sorted. If you own the original rule you could of course change _foo_impl to handle that for you, but if you are relying on a more complex upstream rule, you may not have that luxury. Here's how we can extend this to post-process the file it produces: def _bar_impl(ctx): providers = ctx.super() # Invoke 'foo' and get the providers # NOTE: This assumes there's always only the provider we want. original_output = providers[0].files.to_list()[0] new_output = ctx.actions.declare_file("new_output.tx