Final preparations before the first release. (#122)

diff --git a/README.md b/README.md
index ebdbddc..1950c07 100644
--- a/README.md
+++ b/README.md
@@ -1,101 +1,43 @@
 # Bazel Rules for Fuzz Tests
 
-## Overview
-
 This repository contains [Bazel](https://bazel.build/) [Starlark extensions](https://docs.bazel.build/versions/master/skylark/concepts.html) for defining fuzz tests in Bazel projects.
 
-Fuzzing is an effective technique for uncovering security and stability bugs in software. Fuzzing works by invoking the code under test (e.g., a library API) with automatically generated data, and observing its execution to discover incorrect behavior, such as memory corruption or failed invariants. Covering fuzzing in detail is outside the scope of this document. Read more [here](https://github.com/google/fuzzing) about fuzzing best practices, additional examples, and other resources.
+[Fuzzing](https://en.wikipedia.org/wiki/Fuzzing) is an effective technique for uncovering security and stability bugs in software. Fuzzing works by invoking the code under test (e.g., a library API) with automatically generated data, and observing its execution to discover incorrect behavior, such as memory corruption or failed invariants. Read more [here](https://github.com/google/fuzzing) about fuzzing, additional examples, best practices, and other resources.
 
-This rule library provides support for writing *in-process* fuzz tests, which consist of a driver function that receives a generated input string and feeds it to the API under test. To make a complete fuzz test executable, the driver is linked with a fuzzing engine, which implements the test generation logic. The rule library provides out-of-the-box support for the most popular fuzzing engines (e.g., [libFuzzer](https://llvm.org/docs/LibFuzzer.html) and [Honggfuzz](https://github.com/google/honggfuzz)), and an extension mechanism to define new fuzzing engines.
+## Features at a glance
 
-The goal of the fuzzing rules is to provide an easy-to-use interface for developers to specify, build, and run fuzz tests, without worrying about the details of each fuzzing engine. A fuzzing rule wraps a raw fuzz test executable and provides additional tools, such as the specification of a corpus and dictionary and a launcher that knows how to invoke the fuzzing engine with the appropriate set of flags.
+* Multiple fuzzing engines out of the box:
+  * [libFuzzer][libfuzzer-doc]
+  * [Honggfuzz][honggfuzz-doc]
+* Multiple sanitizer configurations:
+  * [Address Sanitizer][asan-doc]
+  * [Memory Sanitizer][msan-doc]
+* Corpora and dictionaries.
+* Simple "bazel run/test" commands to build and run the fuzz tests.
+  * No need to understand the details of each fuzzing engine.
+  * No need to explicitly manage its corpus or dictionary.
+* Out-of-the-box [OSS-Fuzz](https://github.com/google/oss-fuzz) support that [substantially simplifies][bazel-oss-fuzz] the project integration effort.
+* Regression testing support, useful in continuous integration.
+* Customization options:
+  * Defining additional fuzzing engines
+  * Customizing the behavior of the fuzz test rule.
 
 The rule library currently provides support for C++ fuzz tests. Support for additional languages may be added in the future.
 
-## Prerequisites
-
-C++ fuzz tests require a Clang compiler. The libFuzzer engine requires at least Clang 6.0.
-
-In addition, the Honggfuzz engine requires the `libunwind-dev` and `libblocksruntime-dev` packages.
+Contributions are welcome! Please read the [contribution guidelines](/docs/contributing.md).
 
 ## Getting started
 
-The fastest way to get a sense of the fuzzing rules is through the examples provided in this repository. Assuming the current directory points to a local clone of this repository, let's explore some of the features provided by the Bazel rules.
+This section will walk you through the steps to set up fuzzing in your Bazel project and write your first fuzz test. We assume Bazel [is installed](https://docs.bazel.build/versions/4.0.0/install.html) on your machine.
 
-### Defining fuzz tests
+### Prerequisites
 
-A fuzz test is specified using a [`cc_fuzz_test` rule](/docs/cc-fuzzing-rules.md#cc_fuzz_test). In the most basic form, a fuzz test requires a source file that implements the fuzz driver entry point. Let's consider a simple example that fuzzes the [RE2](https://github.com/google/re2) regular expression library:
-
-```python
-# BUILD file.
-
-load("@rules_fuzzing//fuzzing:cc_deps.bzl", "cc_fuzz_test")
-
-cc_fuzz_test(
-    name = "re2_fuzz_test",
-    srcs = ["re2_fuzz_test.cc"],
-    deps = [
-        "@re2",
-    ],
-)
-```
-
-The fuzz driver implements the special `LLVMFuzzerTestOneInput` function that receives the fuzzer-generated string and uses it to drive the API under test:
-
-```cpp
-// Implementation file.
-
-#include <cstdint>
-#include <cstddef>
-#include <string>
-
-#include "re2/re2.h"
-
-extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
-    RE2 re(std::string(reinterpret_cast<const char*>(data), size), RE2::Quiet);
-    return 0;
-}
-```
-
-### Building and running
-
-To build a fuzz test, you need to specify which fuzzing engine and what instrumentation to use for tracking errors during the execution of the fuzzer. Let's build the RE2 fuzz test using [libFuzzer](https://llvm.org/docs/LibFuzzer.html) and the [Address Sanitizer (ASAN)](https://clang.llvm.org/docs/AddressSanitizer.html) instrumentation, which catches memory errors such as buffer overflows and use-after-frees:
+The fuzz tests require a Clang compiler. The libFuzzer engine requires at least Clang 6.0. In addition, the Honggfuzz engine requires the `libunwind-dev` and `libblocksruntime-dev` packages:
 
 ```sh
-$ bazel build -c opt --config=asan-libfuzzer //examples:re2_fuzz_test
+$ sudo apt-get install clang libunwind-dev libblocksruntime-dev
 ```
 
-You can directly invoke this fuzz test executable if you know libFuzzer's command line interface. But in practice, you don't have to. For each fuzz test `<name>`, the rules library generates a number of additional targets that provide higher-level functionality to simplify the interaction with the fuzz test.
-
-One such target is `<name>_run`, which provides a simple engine-agnostic interface for invoking fuzz tests. Let's run our libFuzzer example:
-
-```sh
-$ bazel run -c opt --config=asan-libfuzzer //examples:re2_fuzz_test_run
-```
-
-The fuzz test will start running locally, and write the generated tests under a temporary path under `/tmp/fuzzing`. By default, the generated tests persist across runs, in order to make it easy to stop and resume runs (possibly under different engines and configurations).
-
-Let's interrupt the fuzz test execution (Ctrl-C), and resume it using the Honggfuzz engine:
-
-```sh
-$ bazel run -c opt --config=asan-honggfuzz //examples:re2_fuzz_test_run
-```
-
-The `<name>_run` target accepts a number of engine-agnostic flags. For example, the following command runs the fuzz test with an execution timeout and on a clean slate (removing any previously generated tests). Note the extra `--` separator between Bazel's own flags and the launcher flags:
-
-```sh
-$ bazel run -c opt --config=asan-libfuzzer //examples:re2_fuzz_test_run \
-      -- --clean --timeout_secs=30
-```
-
-### Additional examples
-
-Check out the [`examples/`](examples/) directory, which showcases additional features of the `cc_fuzz_test` rule.
-
-## Using the rules in your project
-
-To use the fuzzing rules in your project, you will need to load and set them up in your workspace. We also recommend creating `--config` commands in your `.bazelrc` file for the fuzzing engine + sanitizer configurations you wish to use in your project.
-
 ### Configuring the WORKSPACE
 
 Add the following to your `WORKSPACE` file:
@@ -105,58 +47,114 @@
 
 http_archive(
     name = "rules_fuzzing",
-    sha256 = "a1cde2a5ccc05bdeb75bd0f4c62c6df966134a50278492468bd03ea8ffcaa133",
-    strip_prefix = "rules_fuzzing-4de19aafba32cd586abf1bd66ebd3f8d2ea98350",
-    urls = ["https://github.com/bazelbuild/rules_fuzzing/archive/4de19aafba32cd586abf1bd66ebd3f8d2ea98350.zip"],
+    sha256 = "4558405e729ee01f98bc6b7bb97f056b31724afbd00147728c0ada65a1476d63",
+    strip_prefix = "rules_fuzzing-f6062a88d83463e2900e47bc218547ba046dad44",
+    urls = ["https://github.com/bazelbuild/rules_fuzzing/archive/f6062a88d83463e2900e47bc218547ba046dad44.zip"],
 )
 
 load("@rules_fuzzing//fuzzing:repositories.bzl", "rules_fuzzing_dependencies")
 
 rules_fuzzing_dependencies()
 
-load("@rules_fuzzing//fuzzing:dependency_imports.bzl", "fuzzing_dependency_imports")
+load("@rules_fuzzing//fuzzing:init.bzl", "rules_fuzzing_init")
 
-fuzzing_dependency_imports()
+rules_fuzzing_init()
 ```
 
-The project is still under active development, so you many need to change the `urls` and `sha256` attributes to get the latest features implemented at `HEAD`.
+> NOTE: The project is still under active development, so you may need to change the `urls` and `sha256` attributes to get the latest features implemented at `HEAD`.
+
 
 ### Configuring the .bazelrc file
 
-Each fuzz test is built with a fuzzing engine and instrumentation specified in a number of build settings, available as flags on the Bazel command line. The most common are:
+It is best to create command shorthands for the fuzzing configurations you will use during development. In our case, let's create a configuration for libFuzzer + Address Sanitizer. In your `.bazelrc` file, add the following:
 
-* `--@rules_fuzzing//fuzzing:cc_engine` points to the `cc_fuzzing_engine` target of the fuzzing engine to use.
-* `--@rules_fuzzing//fuzzing:cc_engine_instrumentation` specifies the compiler instrumentation to use (for example, libFuzzer or Honggfuzz).
-* `--@rules_fuzzing//fuzzing:cc_engine_sanitizer` specifies the sanitizer configuration used to detect bugs (for example, ASAN or MSAN).
+```
+# Force the use of Clang for C++ builds.
+build --action_env=CC=clang
+build --action_env=CXX=clang++
 
-To simplify specifying these settings on the command line, we recommend combining them as `--config` settings in your project's [`.bazelrc` file](https://docs.bazel.build/versions/master/guide.html#bazelrc-the-bazel-configuration-file). You can copy and paste the [`.bazelrc` file of this repository](/.bazelrc) as a starting point, which defines the following configurations:
+# Define the --config=asan-libfuzzer configuration.
+build:asan-libfuzzer --@rules_fuzzing//fuzzing:cc_engine=@rules_fuzzing//fuzzing/engines:libfuzzer
+build:asan-libfuzzer --@rules_fuzzing//fuzzing:cc_engine_instrumentation=libfuzzer
+build:asan-libfuzzer --@rules_fuzzing//fuzzing:cc_engine_sanitizer=asan
+```
 
-| Configuration             | Fuzzing engine | Sanitizer                |
-|---------------------------|----------------|--------------------------|
-| `--config=asan-fuzzer`    | libFuzzer      | Address Sanitizer (ASAN) |
-| `--config=msan-fuzzer`    | libFuzzer      | Memory Sanitizer (MSAN)  |
-| `--config=asan-honggfuzz` | Honggfuzz      | Address Sanitizer (ASAN) |
+### Defining the fuzz test
 
-You should similarly create additional `--config` entries for any [fuzzing engines defined](#defining-fuzzing-engines) in your own repository.
+A fuzz test is specified using a [`cc_fuzz_test` rule](/docs/cc-fuzzing-rules.md#cc_fuzz_test). In the most basic form, a fuzz test requires a source file that implements the fuzz driver entry point.
 
-## Defining fuzzing engines
+Let's create a fuzz test that exhibits a buffer overflow. Create a `fuzz_test.cc` file in your workspace root, as follows:
 
-> TODO: Fill in the missing documentation here.
+```cpp
+#include <cstddef>
+#include <cstdint>
+#include <cstdio>
 
-A fuzzing engine launcher script receives configuration through the following environment variables:
+void TriggerBufferOverflow(const uint8_t *data, size_t size) {
+  if (size >= 3 && data[0] == 'F' && data[1] == 'U' && data[2] == 'Z' &&
+      data[size] == 'Z') {
+    fprintf(stderr, "BUFFER OVERFLOW!\n");
+  }
+}
 
-| Variable                   | Description |
-|----------------------------|-------------|
-| `FUZZER_BINARY`            | The path to the fuzz target executable. |
-| `FUZZER_TIMEOUT_SECS`      | If set, a positive integer representing the timeout in seconds for the entire fuzzer run. |
-| `FUZZER_IS_REGRESSION`     | Set to `1` if the fuzzer should run in regression mode (just execute the input tests), or `0` if this is a continuous fuzzer run. |
-| `FUZZER_DICTIONARY_PATH`   | If set, provides a path to a fuzzing dictionary file. |
-| `FUZZER_SEED_CORPUS_DIR`   | If set, provides a directory path to a seed corpus. |
-| `FUZZER_OUTPUT_ROOT`       | A writable path that can be used by the fuzzer during its execution (e.g., as a workspace or for generated artifacts). See the variables below for specific categories of output. |
-| `FUZZER_OUTPUT_CORPUS_DIR` | A path under `FUZZER_OUTPUT_ROOT` where the new generated tests should be stored. |
-| `FUZZER_ARTIFACTS_DIR`     | A path under `FUZZER_OUTPUT_ROOT` where generated crashes and other relevant artifacts should be stored. |
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
+  TriggerBufferOverflow(data, size);
+  return 0;
+}
+```
 
-## Rule reference
+Let's now define its build target in the `BUILD` file:
 
-* [`cc_fuzz_test`](/docs/cc-fuzzing-rules.md#cc_fuzz_test)
-* [`cc_fuzzing_engine`](/docs/cc-fuzzing-rules.md#cc_fuzzing_engine)
+```python
+load("@rules_fuzzing//fuzzing:cc_defs.bzl", "cc_fuzz_test")
+
+cc_fuzz_test(
+    name = "fuzz_test",
+    srcs = ["fuzz_test.cc"],
+)
+```
+
+### Running the fuzz test
+
+You can now build and run the fuzz test. For each fuzz test `<name>` defined, the framework automatically generates a launcher tool `<name>_run` that will build and run the fuzz test according to the configuration specified:
+
+```sh
+$ bazel run --config=asan-libfuzzer //:fuzz_test_run
+```
+
+Our libFuzzer test will start running and immediately discover the buffer overflow issue in the code:
+
+```
+INFO: Seed: 2957541205
+INFO: Loaded 1 modules   (8 inline 8-bit counters): 8 [0x5aab10, 0x5aab18), 
+INFO: Loaded 1 PC tables (8 PCs): 8 [0x5aab18,0x5aab98), 
+INFO:      755 files found in /tmp/fuzzing/corpus
+INFO:        0 files found in fuzz_test_corpus
+INFO: -max_len is not provided; libFuzzer will not generate inputs larger than 35982 bytes
+INFO: seed corpus: files: 755 min: 1b max: 35982b total: 252654b rss: 35Mb
+#756    INITED cov: 6 ft: 7 corp: 4/10b exec/s: 0 rss: 47Mb
+=================================================================
+==724294==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x602000047a74 at pc 0x0000005512d9 bp 0x7fff3049d270 sp 0x7fff3049d268
+```
+
+The crash is saved under `/tmp/fuzzing/artifacts` and can be further inspected.
+
+### OSS-Fuzz integration
+
+Once you wrote and tested the fuzz test, you should run it on continuous fuzzing infrastructure so it starts generating tests and finding new crashes in your code.
+
+The fuzzing rules provide out-of-the-box support for [OSS-Fuzz](https://github.com/google/oss-fuzz), free continuous fuzzing infrastructure from Google for open source projects. Read its [Bazel project guide][bazel-oss-fuzz] for detailed instructions.
+
+## Where to go from here?
+
+Congratulations, you have built and run your first fuzz test with the Bazel rules!
+
+Check out the [`examples/`](examples/) directory, which showcases additional features. Read the [User Guide](/docs/guide.md) for detailed usage instructions.
+
+<!-- Links -->
+
+[asan-doc]: https://clang.llvm.org/docs/AddressSanitizer.html
+[bazel-oss-fuzz]: https://google.github.io/oss-fuzz/getting-started/new-project-guide/bazel/
+[honggfuzz-doc]: https://github.com/google/honggfuzz
+[libfuzzer-doc]: https://llvm.org/docs/LibFuzzer.html
+[msan-doc]: https://clang.llvm.org/docs/MemorySanitizer.html
diff --git a/WORKSPACE b/WORKSPACE
index 9dbdd6d..696988e 100644
--- a/WORKSPACE
+++ b/WORKSPACE
@@ -18,24 +18,13 @@
 
 # Load all external library dependencies.
 
-load(
-    "@rules_fuzzing//fuzzing:repositories.bzl",
-    "honggfuzz_dependencies",
-    "oss_fuzz_dependencies",
-    "rules_fuzzing_dependencies",
-)
+load("@rules_fuzzing//fuzzing:repositories.bzl", "rules_fuzzing_dependencies")
 
 rules_fuzzing_dependencies()
 
-honggfuzz_dependencies()
+load("@rules_fuzzing//fuzzing:init.bzl", "rules_fuzzing_init")
 
-oss_fuzz_dependencies()
-
-# Initialize Bazel Skylib.
-
-load("@bazel_skylib//:workspace.bzl", "bazel_skylib_workspace")
-
-bazel_skylib_workspace()
+rules_fuzzing_init()
 
 # The support for running the examples and unit tests.
 
@@ -53,19 +42,6 @@
     urls = ["https://github.com/google/googletest/archive/389cb68b87193358358ae87cc56d257fd0d80189.zip"],
 )
 
-# Python dependencies.
-
-load("@rules_python//python:pip.bzl", "pip_install")
-load("@rules_python//python:repositories.bzl", "py_repositories")
-
-py_repositories()
-
-pip_install(
-    name = "fuzzing_py_deps",
-    extra_pip_args = ["--require-hashes"],
-    requirements = "@rules_fuzzing//fuzzing:requirements.txt",
-)
-
 # Stardoc dependencies.
 
 http_archive(
diff --git a/docs/BUILD b/docs/BUILD
index 6967a10..d414368 100644
--- a/docs/BUILD
+++ b/docs/BUILD
@@ -36,7 +36,7 @@
 bzl_library(
     name = "cc_fuzzing_rules",
     srcs = [
-        "//fuzzing:cc_deps.bzl",
+        "//fuzzing:cc_defs.bzl",
         "//fuzzing:instrum_opts.bzl",
         "//fuzzing/private:binary.bzl",
         "//fuzzing/private:common.bzl",
@@ -55,7 +55,7 @@
 stardoc(
     name = "cc_fuzzing_docs",
     out = "cc-fuzzing-rules.md",
-    input = "//fuzzing:cc_deps.bzl",
+    input = "//fuzzing:cc_defs.bzl",
     deps = [
         ":cc_fuzzing_rules",
     ],
diff --git a/docs/cc-fuzzing-rules.md b/docs/cc-fuzzing-rules.md
index a869934..31867ca 100755
--- a/docs/cc-fuzzing-rules.md
+++ b/docs/cc-fuzzing-rules.md
@@ -39,7 +39,7 @@
 
 * `<name>`: A test that executes the fuzzer binary against the seed corpus
   (or on an empty input if no corpus is specified).
-* `<name>_instrum`: The instrumented fuzz test executable. Use this target
+* `<name>_bin`: The instrumented fuzz test executable. Use this target
   for debugging or for accessing the complete command line interface of the
   fuzzing engine. Most developers should only need to use this target
   rarely.
@@ -51,9 +51,6 @@
   directory of an OSS-Fuzz build. This target can be used inside the
   `build.sh` script of an OSS-Fuzz project.
 
-> TODO: Document here the command line interface of the `<name>_run`
-targets.
-
 
 **PARAMETERS**
 
diff --git a/docs/guide.md b/docs/guide.md
new file mode 100644
index 0000000..ae9d189
--- /dev/null
+++ b/docs/guide.md
@@ -0,0 +1,214 @@
+# Bazel Rules User Guide
+
+## Contents
+
+* [Defining fuzz tests](#defining-fuzz-tests)
+* [Integrating in your project](#integrating-in-your-project)
+* [Advanced topics](#advanced-topics)
+  * [Defining fuzzing engines](#defining-fuzzing-engines)
+  * [Customizing fuzz tests](#customizing-fuzz-tests)
+* [Rule reference](#rule-reference)
+
+## Defining fuzz tests
+
+The rule library provides support for writing *in-process* fuzz tests, which consist of a driver function that receives a generated input string and feeds it to the API under test. To make a complete fuzz test executable, the driver is linked with a fuzzing engine, which implements the test generation logic. The rule library provides out-of-the-box support for the most popular fuzzing engines (e.g., [libFuzzer][libfuzzer-doc] and [Honggfuzz][honggfuzz-doc]), and an extension mechanism to define new fuzzing engines.
+
+A fuzzing rule wraps a raw fuzz test executable and provides additional tools, such as the specification of a corpus and dictionary and a launcher that knows how to invoke the fuzzing engine with the appropriate set of flags.
+
+### Defining fuzz tests
+
+A fuzz test is specified using a [`cc_fuzz_test` rule](/docs/cc-fuzzing-rules.md#cc_fuzz_test). In the most basic form, a fuzz test requires a source file that implements the fuzz driver entry point. Let's consider a simple example that fuzzes the [RE2](https://github.com/google/re2) regular expression library:
+
+```python
+# BUILD file.
+
+load("@rules_fuzzing//fuzzing:cc_defs.bzl", "cc_fuzz_test")
+
+cc_fuzz_test(
+    name = "re2_fuzz_test",
+    srcs = ["re2_fuzz_test.cc"],
+    deps = [
+        "@re2",
+    ],
+)
+```
+
+The fuzz driver implements the special `LLVMFuzzerTestOneInput` function that receives the fuzzer-generated string and uses it to drive the API under test:
+
+```cpp
+// Implementation file.
+
+#include <cstdint>
+#include <cstddef>
+#include <string>
+
+#include "re2/re2.h"
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+    RE2 re(std::string(reinterpret_cast<const char*>(data), size), RE2::Quiet);
+    return 0;
+}
+```
+
+### Building and running
+
+To build a fuzz test, you need to specify which fuzzing engine and what instrumentation to use for tracking errors during the execution of the fuzzer. Let's build the RE2 fuzz test using [libFuzzer][libfuzzer-doc] and the [Address Sanitizer (ASAN)][asan-doc] instrumentation, which catches memory errors such as buffer overflows and use-after-frees:
+
+```sh
+$ bazel build -c opt --config=asan-libfuzzer //examples:re2_fuzz_test
+```
+
+You can directly invoke this fuzz test executable if you know libFuzzer's command line interface. But in practice, you don't have to. For each fuzz test `<name>`, the rules library generates a number of additional targets that provide higher-level functionality to simplify the interaction with the fuzz test.
+
+One such target is `<name>_run`, which provides a simple engine-agnostic interface for invoking fuzz tests. Let's run our libFuzzer example:
+
+```sh
+$ bazel run -c opt --config=asan-libfuzzer //examples:re2_fuzz_test_run
+```
+
+The fuzz test will start running locally, and write the generated tests under a temporary path under `/tmp/fuzzing`. By default, the generated tests persist across runs, in order to make it easy to stop and resume runs (possibly under different engines and configurations).
+
+Let's interrupt the fuzz test execution (Ctrl-C), and resume it using the Honggfuzz engine:
+
+```sh
+$ bazel run -c opt --config=asan-honggfuzz //examples:re2_fuzz_test_run
+```
+
+The `<name>_run` target accepts a number of engine-agnostic flags. For example, the following command runs the fuzz test with an execution timeout and on a clean slate (removing any previously generated tests). Note the extra `--` separator between Bazel's own flags and the launcher flags:
+
+```sh
+$ bazel run -c opt --config=asan-libfuzzer //examples:re2_fuzz_test_run \
+      -- --clean --timeout_secs=30
+```
+
+### Specifying seed corpora
+
+You can use the `corpus` attribute to specify a set of files that the fuzz test can use as a seed corpus when running in continuous fuzzing mode. The following example shows how to include all the files in a directory in the seed corpus:
+
+```python
+cc_fuzz_test(
+    name = "fuzz_test",
+    srcs = ["fuzz_test.cc"],
+    corpus = glob(["fuzz_test_corpus/**"]),
+)
+```
+
+Specifying a seed corpus is a [best practice][seed-corpus] that helps the fuzzer make progress faster.
+
+### Specifying dictionaries
+
+Similarly, you can speed up fuzzing by specifying a dictionary using the `dicts` attribute. A dictionary is a set of string tokens that the fuzzer can use to construct and mutate test inputs. The attribute accepts a list of files with one dictionary token per line specified in the [AFL/libFuzzer format](http://llvm.org/docs/LibFuzzer.html#dictionaries):
+
+```python
+cc_fuzz_test(
+    name = "fuzz_test",
+    srcs = ["fuzz_test.cc"],
+)
+```
+
+### The fuzz test launcher
+
+Each fuzz test `<fuzz_test>` gets a `<fuzz_test>_run` target that can be used to launch the fuzzing executable in "continuous fuzzing" mode. The launcher provides a uniform command line interface regardless of the fuzzing engine or sanitizer used.
+
+Currently, the launcher offers the following options:
+
+* `--[no]clean`: If set, cleans up the output directory of the target before fuzzing (default: 'false').
+* `--fuzzing_output_root`: The root directory for storing all generated artifacts during fuzzing. (default: '/tmp/fuzzing')
+* `--[no]regression`: If set, the script will trigger the target as a regression test. (default: 'false')
+* `--timeout_secs`: The maximum duration, in seconds, of the fuzzer run launched. (default: '0', a non-negative integer)
+
+### Built-in fuzzing engines
+
+* `@rules_fuzzing//fuzzing/engines:libfuzzer` provides libFuzzer support. Must be used with the `libfuzzer` engine instrumentation.
+
+* `@rules_fuzzing//fuzzing/engines:honggfuzz` provides Honggfuzz support. Must be used with the `honggfuzz` engine instrumentation. Requires importing its dependencies using the `honggfuzz_dependencies()` WORKSPACE function.
+
+* `@rules_fuzzing//fuzzing/engines:replay` provides a simple engine that just executes a set of test files. It can be combined with a sanitizer and can be used for regression tests or replaying crashes.
+
+* `@rules_fuzzing_oss_fuzz//:oss_fuzz_engine` provides a fuzzing engine that reflects the environment configuration of an [OSS-Fuzz build][bazel-oss-fuzz]. This engine is useful in the `build.sh` script of an OSS-Fuzz project. Requires importing its dependencies using the `oss_fuzz_dependencies()` WORKSPACE function.
+
+### Configuration flags
+
+The fuzzing rules library defines the following Bazel configuration flags that affect how a fuzz test is built:
+
+* `--@rules_fuzzing//fuzzing:cc_engine` specifies the fuzzing engine used to build and run the fuzz test. This flag should point to a `cc_fuzzing_engine` target.
+
+* `--@rules_fuzzing//fuzzing:cc_engine_instrumentation` specifies the engine-specific instrumentation to use. Valid values are:
+   * `none`: No instrumentation.
+   * `libfuzzer`: The libFuzzer-specific instrumentation. It should be used in conjunction with the `@rules_fuzzing//fuzzing/engines:libfuzzer` engine.
+   * `honggfuzz`: The Honggfuzz-specific instrumentation. It should be used in conjunction with the `@rules_fuzzing//fuzzing/engines:honggfuzz` engine.
+   * `oss-fuzz`: The instrumentation captured from the environment during an [OSS-Fuzz build][bazel-oss-fuzz]. It uses the `$FUZZING_CFLAGS` and `$FUZZING_CXXFLAGS` variables, if set, or falls back to `$CFLAGS` and `$CXXFLAGS` otherwise.
+
+* `--@rules_fuzzing//fuzzing:cc_engine_sanitizer` specifies the sanitizer configuration used to detect bugs. Valid values are:
+   * `none`: No sanitizer instrumentation.
+   * `asan`: [Address Sanitizer (ASAN)][asan-doc].
+   * `msan`: [Memory Sanitizer (MSAN)][msan-doc].
+   * `msan-origin-tracking`: MSAN with [origin tracking][msan-origin-tracking] enabled (useful for debugging crash reproducers; available separately due to it being 1.5-2x slower).
+
+* `--@rules_fuzzing//fuzzing:cc_fuzzing_build_mode` is a bool flag that specifies whether the special [`FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION` macro][fuzzing-build-mode] is defined during the build. This is turned on by default and most users should not need to change this flag.
+
+## Integrating in your project
+
+### Configuring the .bazelrc file
+
+Each fuzz test is built with a fuzzing engine and instrumentation specified as [build setting flags](#configuration-flags). For example, running a fuzz test in the libFuzzer / ASAN configuration would look like:
+
+```sh
+$ bazel test \
+    --//fuzzing:cc_engine=//fuzzing/engines:libfuzzer \
+    --@rules_fuzzing//fuzzing:cc_engine_instrumentation=libfuzzer \
+    --@rules_fuzzing//fuzzing:cc_engine_sanitizer=asan \
+    //examples:re2_fuzz_test
+```
+
+This command is clearly too verbose to be used manually, so we recommend combining these options as a `--config` setting in your project's [`.bazelrc` file][bazelrc-docs]. For the example above, we can define an `asan-libfuzzer` config setting as follows:
+
+```
+build:asan-libfuzzer --//fuzzing:cc_engine=//fuzzing/engines:libfuzzer
+build:asan-libfuzzer --@rules_fuzzing//fuzzing:cc_engine_instrumentation=libfuzzer
+build:asan-libfuzzer --@rules_fuzzing//fuzzing:cc_engine_sanitizer=asan
+```
+
+To run your fuzz test, now you can simply invoke:
+
+```sh
+$ bazel test --config=asan-libfuzzer //examples:re2_fuzz_test
+```
+
+You can add to your `.bazelrc` file as many configurations as you need. Feel free to use the [`.bazelrc` file of this repository](/.bazelrc) as a starting point.
+
+## Advanced topics
+
+### Defining fuzzing engines
+
+> TODO: The documentation for this feature is coming soon.
+
+A fuzzing engine launcher script receives configuration through the following environment variables:
+
+| Variable                   | Description |
+|----------------------------|-------------|
+| `FUZZER_BINARY`            | The path to the fuzz target executable. |
+| `FUZZER_TIMEOUT_SECS`      | If set, a positive integer representing the timeout in seconds for the entire fuzzer run. |
+| `FUZZER_IS_REGRESSION`     | Set to `1` if the fuzzer should run in regression mode (just execute the input tests), or `0` if this is a continuous fuzzer run. |
+| `FUZZER_DICTIONARY_PATH`   | If set, provides a path to a fuzzing dictionary file. |
+| `FUZZER_SEED_CORPUS_DIR`   | If set, provides a directory path to a seed corpus. |
+| `FUZZER_OUTPUT_ROOT`       | A writable path that can be used by the fuzzer during its execution (e.g., as a workspace or for generated artifacts). See the variables below for specific categories of output. |
+| `FUZZER_OUTPUT_CORPUS_DIR` | A path under `FUZZER_OUTPUT_ROOT` where the new generated tests should be stored. |
+| `FUZZER_ARTIFACTS_DIR`     | A path under `FUZZER_OUTPUT_ROOT` where generated crashes and other relevant artifacts should be stored. |
+
+## Rule reference
+
+* [`cc_fuzz_test`](/docs/cc-fuzzing-rules.md#cc_fuzz_test)
+* [`cc_fuzzing_engine`](/docs/cc-fuzzing-rules.md#cc_fuzzing_engine)
+
+<!-- Links -->
+
+[asan-doc]: https://clang.llvm.org/docs/AddressSanitizer.html
+[bazel-oss-fuzz]: https://google.github.io/oss-fuzz/getting-started/new-project-guide/bazel/
+[bazelrc-docs]: https://docs.bazel.build/versions/master/guide.html#bazelrc-the-bazel-configuration-file
+[fuzzing-build-mode]: https://llvm.org/docs/LibFuzzer.html#fuzzer-friendly-build-mode
+[honggfuzz-doc]: https://github.com/google/honggfuzz
+[libfuzzer-doc]: https://llvm.org/docs/LibFuzzer.html
+[msan-doc]: https://clang.llvm.org/docs/MemorySanitizer.html
+[msan-origin-tracking]: https://clang.llvm.org/docs/MemorySanitizer.html#origin-tracking
+[seed-corpus]: https://github.com/google/fuzzing/blob/master/docs/good-fuzz-target.md#seed-corpus
diff --git a/examples/BUILD b/examples/BUILD
index afa7bf3..4b1e0a4 100644
--- a/examples/BUILD
+++ b/examples/BUILD
@@ -17,7 +17,7 @@
 # serve as regression tests. Targets that are expected to crash or hang are
 # disabled in the OSS-Fuzz integration using the "no-oss-fuzz" tag.
 
-load("//fuzzing:cc_deps.bzl", "cc_fuzz_test")
+load("//fuzzing:cc_defs.bzl", "cc_fuzz_test")
 
 cc_fuzz_test(
     name = "empty_fuzz_test",
diff --git a/fuzzing/BUILD b/fuzzing/BUILD
index 9053349..c8805eb 100644
--- a/fuzzing/BUILD
+++ b/fuzzing/BUILD
@@ -62,6 +62,6 @@
 )
 
 exports_files([
-    "cc_deps.bzl",
+    "cc_defs.bzl",
     "instrum_opts.bzl",
 ])
diff --git a/fuzzing/cc_deps.bzl b/fuzzing/cc_defs.bzl
similarity index 100%
rename from fuzzing/cc_deps.bzl
rename to fuzzing/cc_defs.bzl
diff --git a/fuzzing/engines/BUILD b/fuzzing/engines/BUILD
index eeee47e..0cfdecc 100644
--- a/fuzzing/engines/BUILD
+++ b/fuzzing/engines/BUILD
@@ -12,7 +12,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-load("//fuzzing:cc_deps.bzl", "cc_fuzzing_engine")
+load("//fuzzing:cc_defs.bzl", "cc_fuzzing_engine")
 load("@rules_cc//cc:defs.bzl", "cc_library")
 
 # libFuzzer specification.
diff --git a/fuzzing/engines/honggfuzz_launcher.sh b/fuzzing/engines/honggfuzz_launcher.sh
index 0edae5f..a872e55 100755
--- a/fuzzing/engines/honggfuzz_launcher.sh
+++ b/fuzzing/engines/honggfuzz_launcher.sh
@@ -12,7 +12,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-command_line="${HONGGFUZZ_PATH}"
+command_line="$(readlink -f ${HONGGFUZZ_PATH})"
 command_line+=("--workspace=${FUZZER_OUTPUT_ROOT}")
 
 if [[ -n "${FUZZER_SEED_CORPUS_DIR}" ]]; then
diff --git a/fuzzing/engines/libfuzzer_launcher.sh b/fuzzing/engines/libfuzzer_launcher.sh
index 17c1f0c..638f478 100755
--- a/fuzzing/engines/libfuzzer_launcher.sh
+++ b/fuzzing/engines/libfuzzer_launcher.sh
@@ -16,7 +16,7 @@
 # libFuzzer engine. The launch configuration is supplied by the launcher
 # script through environment variables.
 
-command_line=("${FUZZER_BINARY}")
+command_line=("$(readlink -f ${FUZZER_BINARY})")
 
 # libFuzzer flags.
 
diff --git a/fuzzing/engines/replay_launcher.sh b/fuzzing/engines/replay_launcher.sh
index f26c52f..735c5c4 100755
--- a/fuzzing/engines/replay_launcher.sh
+++ b/fuzzing/engines/replay_launcher.sh
@@ -16,7 +16,7 @@
     echo "NOTE: Non-regression mode is not supported by the replay engine."
 fi
 
-command_line=("${FUZZER_BINARY}")
+command_line=("$(readlink -f ${FUZZER_BINARY})")
 if [[ -n "${FUZZER_SEED_CORPUS_DIR}" ]]; then
     command_line+=("${FUZZER_SEED_CORPUS_DIR}")
 fi
diff --git a/fuzzing/init.bzl b/fuzzing/init.bzl
new file mode 100644
index 0000000..4c96927
--- /dev/null
+++ b/fuzzing/init.bzl
@@ -0,0 +1,28 @@
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+"""Dependency initialization utilities."""
+
+load("@rules_python//python:pip.bzl", "pip_install")
+load("@rules_python//python:repositories.bzl", "py_repositories")
+load("@bazel_skylib//:workspace.bzl", "bazel_skylib_workspace")
+
+def rules_fuzzing_init():
+    py_repositories()
+    pip_install(
+        name = "fuzzing_py_deps",
+        extra_pip_args = ["--require-hashes"],
+        requirements = "@rules_fuzzing//fuzzing:requirements.txt",
+    )
+    bazel_skylib_workspace()
diff --git a/fuzzing/private/fuzz_test.bzl b/fuzzing/private/fuzz_test.bzl
index d1715a5..fd8e77f 100644
--- a/fuzzing/private/fuzz_test.bzl
+++ b/fuzzing/private/fuzz_test.bzl
@@ -67,7 +67,7 @@
     # targets and their runfiles would be transferred from the remote cache to
     # the local machine, ballooning the size of the output.
 
-    instrum_binary_name = base_name + "_meta"
+    instrum_binary_name = base_name + "_bin"
     launcher_name = base_name + "_run"
     corpus_name = base_name + "_corpus"
     dict_name = base_name + "_dict"
@@ -143,7 +143,7 @@
 
     * `<name>`: A test that executes the fuzzer binary against the seed corpus
       (or on an empty input if no corpus is specified).
-    * `<name>_instrum`: The instrumented fuzz test executable. Use this target
+    * `<name>_bin`: The instrumented fuzz test executable. Use this target
       for debugging or for accessing the complete command line interface of the
       fuzzing engine. Most developers should only need to use this target
       rarely.
@@ -155,9 +155,6 @@
       directory of an OSS-Fuzz build. This target can be used inside the
       `build.sh` script of an OSS-Fuzz project.
 
-    > TODO: Document here the command line interface of the `<name>_run`
-    targets.
-
     Args:
         name: A unique name for this target. Required.
         corpus: A list containing corpus files.
diff --git a/fuzzing/private/oss_fuzz/BUILD.tpl b/fuzzing/private/oss_fuzz/BUILD.tpl
index 901afdd..8735e04 100644
--- a/fuzzing/private/oss_fuzz/BUILD.tpl
+++ b/fuzzing/private/oss_fuzz/BUILD.tpl
@@ -12,7 +12,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-load("@rules_fuzzing//fuzzing:cc_deps.bzl", "cc_fuzzing_engine")
+load("@rules_fuzzing//fuzzing:cc_defs.bzl", "cc_fuzzing_engine")
 load("@rules_cc//cc:defs.bzl", "cc_library")
 
 cc_fuzzing_engine(
diff --git a/fuzzing/repositories.bzl b/fuzzing/repositories.bzl
index bb6b502..e8f7344 100644
--- a/fuzzing/repositories.bzl
+++ b/fuzzing/repositories.bzl
@@ -18,8 +18,13 @@
 load("@bazel_tools//tools/build_defs/repo:utils.bzl", "maybe")
 load("//fuzzing/private/oss_fuzz:repository.bzl", "oss_fuzz_repository")
 
-def rules_fuzzing_dependencies():
-    """Instantiates the dependencies of the fuzzing rules."""
+def rules_fuzzing_dependencies(oss_fuzz = True, honggfuzz = True):
+    """Instantiates the dependencies of the fuzzing rules.
+
+    Args:
+      oss_fuzz: Include OSS-Fuzz dependencies.
+      honggfuzz: Include Honggfuzz dependencies.
+    """
 
     maybe(
         http_archive,
@@ -44,22 +49,18 @@
         sha256 = "f4f2d3d01c3cc99eebc9f370ea626c43a54b386913aef393bf8201b2c42a9e2f",
     )
 
-def honggfuzz_dependencies():
-    """The extra dependencies needed for Honggfuzz support."""
+    if oss_fuzz:
+        maybe(
+            oss_fuzz_repository,
+            name = "rules_fuzzing_oss_fuzz",
+        )
 
-    maybe(
-        http_archive,
-        name = "honggfuzz",
-        build_file = "@rules_fuzzing//:honggfuzz.BUILD",
-        sha256 = "a6f8040ea62e0f630737f66dce46fb1b86140f118957cb5e3754a764de7a770a",
-        url = "https://github.com/google/honggfuzz/archive/e0670137531242d66c9cf8a6dee677c055a8aacb.zip",
-        strip_prefix = "honggfuzz-e0670137531242d66c9cf8a6dee677c055a8aacb",
-    )
-
-def oss_fuzz_dependencies():
-    """The extra dependencies needed for OSS-Fuzz support."""
-
-    maybe(
-        oss_fuzz_repository,
-        name = "rules_fuzzing_oss_fuzz",
-    )
+    if honggfuzz:
+        maybe(
+            http_archive,
+            name = "honggfuzz",
+            build_file = "@rules_fuzzing//:honggfuzz.BUILD",
+            sha256 = "a6f8040ea62e0f630737f66dce46fb1b86140f118957cb5e3754a764de7a770a",
+            url = "https://github.com/google/honggfuzz/archive/e0670137531242d66c9cf8a6dee677c055a8aacb.zip",
+            strip_prefix = "honggfuzz-e0670137531242d66c9cf8a6dee677c055a8aacb",
+        )
diff --git a/fuzzing/tools/BUILD b/fuzzing/tools/BUILD
index 227f5b0..21691a6 100644
--- a/fuzzing/tools/BUILD
+++ b/fuzzing/tools/BUILD
@@ -23,6 +23,7 @@
 py_binary(
     name = "launcher",
     srcs = ["launcher.py"],
+    python_version = "PY3",
     visibility = ["//visibility:public"],
     deps = [requirement("absl-py")],
 )
@@ -30,6 +31,7 @@
 py_binary(
     name = "make_corpus_dir",
     srcs = ["make_corpus_dir.py"],
+    python_version = "PY3",
     visibility = ["//visibility:public"],
     deps = [requirement("absl-py")],
 )
@@ -37,6 +39,7 @@
 py_binary(
     name = "validate_dict",
     srcs = ["validate_dict.py"],
+    python_version = "PY3",
     visibility = ["//visibility:public"],
     deps = [
         ":dict_validation",