<meta>_conflicts() and <meta>_deps() do not
evaluate them either. R's own load test at the end of R CMD INSTALL can
still evaluate them.<meta>_conflicts() to
inspect those intentional conflicts.install_local_pkg() has an example that installs the bundled example
archive into a temporary library.update = TRUE refuses a planned generated path that already exists outside
the manifest, including generated documentation files that were previously
regenerated over it. Remove or rename that file to let the update write it.bigbang_error_missing_project now inherits from
bigbang_error_missing_manifest while identifying a missing project more
precisely.dry_run now reports a read-only reconciliation plan for sibling journals
and the project lock; uncertain owners require recover = TRUE.create_metapackage() now accepts reexport_prefer and reexport_exclude.
Every collision requires one of them because static analysis cannot prove
object identity, and diagnostics classify the selected resolution..component_reexport_specs,
.reexport_state, .reexport_library_paths, .set_reexport_library,
.reexport_component_value, .reexport_installed_version,
.reexport_loaded_version, .reexport_version_text,
.make_reexport_binding, .install_reexport_bindings, .reexport_verify,
.reexport_verify_subprocess, .meta_package_version,
<meta>_reexport_verification, and the generated installer, lifecycle,
dependency, diagnostic, and translation helpers. Migrate colliding component
exports with reexport_exclude = "...". Version 0.4.0 already rejected
these collisions; 0.5.0 adds explicit choose-or-exclude handling and
diagnostics.if, [, or arithmetic and comparison
operators now requires reexport_exclude. Version 0.4.0 did not reserve
those names, so a component export could shadow syntax in generated code and
in the attached session. Migrate by excluding the syntax names; the generated
metapackage retains R's syntax and its installer remains usable.recover argument and reports recovered,
recovery, reexports, and reexport_excluded in its result. The generated
<meta>_reexport_verification() accessor returns installed-owner checks..S, .s, and .q sources; detected
dependencies can therefore differ from earlier releases.<meta>_detach() detaches components from the top of
the search path down, so families linked through Depends detach completely;
library(<meta>) reports components that cannot be attached, such as one
whose Depends are missing or whose namespace was loaded from another
library, instead of failing; installer messages respect verbose = FALSE;
<meta>_conflicts() compares namespace exports, so internal objects such as
.Depends are no longer reported as conflicts.DESCRIPTION version differ is
now given once per archive and installation call.R CMD INSTALL fail while loading the
metapackage. Re-export bindings now always evaluate safely and provide an
actionable <meta>_install() placeholder error when called./proc now record a locale-independent ps lstart
token, and the retry guard counts only consecutive no-progress attempts.state.rds and marker.rds
owners instead of rolling back a live update. Clean re-export verification
now follows the runtime library order and distinguishes installation,
export, and foreign-library failures.The project lifecycle is now documented as stable: its public API has remained stable since 0.1.0 and is protected by an extensive regression suite and repeated independent adversarial reviews.
create_metapackage(reexport = TRUE) now exposes explicit component exports
through lazy, read-only active bindings without making components installation
dependencies. Generated metapackages can load offline before their components
are installed, and the bindings resolve after a later installation.
Runtime re-exports now exclude S4 class and method directives, reserve every
generated helper symbol, preserve untracked reexports.R and reexports.Rd
files during updates, avoid loading components for startup reporting, and
support installation into a new library directory.
Component inputs now accept a bare package name when exactly one archive in
the supplied directories declares that Package identity. Ambiguous versions
or sources are rejected with the full candidate list.
pegeler/metapackage as a related online declarative metapackage.Bare package-name discovery now warns when an unreadable archive is excluded and suppresses uncontrolled tar diagnostics while retaining readable matches.
Runtime re-exports quote non-syntactic names in generated NAMESPACE files, so legal exports containing spaces or Unicode characters produce installable metapackages and working active bindings.
removed_files now includes partial documentation outputs that a generation
call created and cleaned up after roxygen failed. Dry-run plans continue to
report only removals that are knowable before generation starts.
This release makes the package accept component packages as an organisation
actually keeps them, instead of requiring one directory, one archive extension,
and a version in every filename. Package identity now comes from each archive's
DESCRIPTION rather than its filename, generation can report a plan without
writing anything, and the checks that concern project tidiness can be relaxed
individually. The checks that protect whoever installs the generated
meta-package cannot: they remain hard errors during generation.
It also supersedes 0.2.0, which was prepared and verified but never submitted. Everything listed under 0.2.0 below reaches CRAN for the first time here, so a user updating from 0.1.0 should read both sections.
reexport is deprecated and ignored. Generated metapackages attach installed
components, so their exports remain available directly or through each
component namespace, but they are not copied into the metapackage namespace.
Re-exporting would require declaring components as installation-time
dependencies, which conflicts with explicit offline component installation;
the option did not produce a valid package in the published 0.1.0 release.packages that is an existing file is used as a path, so
components can come from several directories in one call and mix
.tar.gz, .tar and .zip. Stems still work, resolved against pkg_dir,
which now accepts more than one directory.DESCRIPTION, not
from its filename, so a filename without a version is valid. A filename that
disagrees with the DESCRIPTION produces a warning and the DESCRIPTION
wins.DESCRIPTION at its root,
built for you with the optional pkgbuild package. It requires
include_archives = TRUE, because the archive built for it lives in a
temporary directory that does not outlive the call.packages may be the path to a manifest: one component per line, # for
comments. Relative paths resolve against the manifest's own directory,
absolute and ~ paths are used as given, and bare filenames are also looked
up in pkg_dir, so the list can live under version control while the archives
do not. A missing entry reports every directory that was searched.create_metapackage(dry_run = TRUE) resolves and validates everything and
returns the plan — components, installation order, files that would be
written, and every validation finding — without creating dest_dir or
writing anything.create_metapackage() gains a final tolerate argument taking a closed list
of named relaxations: "filename_mismatch" silences the filename-versus-
DESCRIPTION warning, and "unincluded_local_dep" turns the error for a
local dependency available in the supplied sources but omitted from packages
into a warning. That second relaxation means the dependency does not travel,
so the recipient has to supply it. Unknown names are errors, not silent
no-ops.tolerated table naming every applied
relaxation, the component it affected, and why.on_component_error = "skip" generates from the components that are valid
instead of aborting, and reports the ones it left out. The exclusion is
transitive: a component that depends on an excluded one is excluded too, and
the chain is reported. When the omitted archive can be read, its declared
Package drives the exclusion; when it cannot, the filename fallback is
reported explicitly. Excluding every component is an error.tolerate, and there is no switch that turns validation off as a
whole. It also states explicitly that bigbang does not run R CMD check
on component packages, so a component with check warnings or notes can be
included.create_metapackage(update = TRUE) regenerates an existing project, which
relaxes the rule that a destination must be new or empty. Generation records a
manifest of the files it wrote together with their content hashes; update
rewrites only those, and refuses to run if the manifest is missing or if a
generated file was modified or removed by hand.update refuses when a
generated file, or any parent directory on the way to it, is a symbolic link,
and it replaces generated files and shipped archives atomically, so a
regeneration cannot write outside the project tree.update reconciles: generated files
and shipped component archives that the new plan no longer includes are
removed transactionally, so the regenerated meta-package cannot end up
importing from a component it no longer declares. Before changing an existing
project, bigbang backs up all generated files and its manifest. If generation
or reconciliation fails, that state is restored and the update remains
retryable. Dry runs and completed updates report the affected paths in
removed_files; removing a component may remove the last available copy of
its shipped archive.<meta>_install(only = ...) installs a subset; local dependencies of the
selection are added automatically, and an unknown component name is an error.<meta>_install(lib = ...) chooses the library in which components must be
installed and verified. Non-local dependencies may already be available in
that library or anywhere on .libPaths(); they no longer need to be
duplicated into the component destination.create_metapackage(install_upgrade = ...) fixes the default upgrade policy
of the installer that gets emitted, so the person generating decides whether
recipients stay pinned to the versions being shipped or keep anything newer
they already have. The default is unchanged.order field as
dry-run plans. The planned files field remains specific to dry runs.install_local_pkg() and generated
installers now report the error lines of the installation subprocess itself
-- for example, which dependency it could not find -- instead of only a
generic verification failure.update = TRUE no longer deletes or leaves
partially overwritten an untracked Rd file whose name is reserved for
generated documentation. Such files are backed up before roxygen runs and
restored without being adopted into the generation manifest.inst/archives/ remains untracked and is
never removed by a later update..git/.on_component_error = "skip", a failed update input no longer authorizes
deletion of a previously shipped component archive. If the old component
cannot be identified safely, archive reconciliation is deferred until a clean
update.verbose = FALSE in both
install_local_pkg() and generated installers; failure details still retain
the child process's ERROR lines.install_local_pkg(lib = ...) and generated installers now distinguish the
component destination from the dependency search path: a component present
only elsewhere is installed into lib, while a non-local dependency already
available elsewhere on .libPaths() is reused. This also works under the
dependency isolation used by R CMD check on Windows.PKG_1.0.TAR.GZ, as they
often arrive from Windows — was shipped under its original name while the
generated installer looked for the normalised one. The component was never
installed on a case-sensitive filesystem, with no error anywhere. Archives are
now copied under canonical names, and names that collide only by case are
rejected.upgrade = "never"; under the default policy only the archive's
DESCRIPTION is read before deciding whether the archive is needed at all. An
unreadable archive is reported as unchanged when the installed package can be
kept, instead of failing the call.DESCRIPTION and
the archive it came from when the two differ, instead of reporting the
filename as though it were the package.upgrade = "never" the component is
identified from its filename, because the archive is deliberately not read;
use the default policy when the declared Package has to be checked against
what is installed.Prepared and verified but never submitted: CRAN submissions were closed between 2026-08-05 and 2026-08-19. These changes are released as part of 0.3.0.
crear_meta_paquete_local(),
diagnosticar_dependencias() and install_loc_pkg_w_dep() were removed. They
existed to ease a rename inside the organisation the package grew in, while it
was still unpublished. Use create_metapackage(), diagnose_dependencies()
and install_local_pkg().include_archives = FALSE,
<meta>_install() requires pkg_dir. In 0.1.0 that argument defaulted to the
absolute archive path of the machine where the meta-package had been
generated, which exists nowhere else. With the new default,
include_archives = TRUE, the argument is optional again because the archives
travel inside the package.unchanged element of the installation result instead of appearing in
installed labelled "Already installed". Reporting a package as installed
when nothing was installed was misleading.dependencies = NA instead of
TRUE, so their Suggests are no longer installed. Everything a component
needs in order to run is still installed; what is no longer pulled in is the
tooling those dependencies use for their own examples, tests and vignettes.detect_implicit_dependencies() are now diagnostic
only. Dependencies declared by a component, or supplied explicitly through
additional_deps/force_deps, remain binding; guessed packages must be opted
in explicitly. This prevents comments and common function names from making
a distributed meta-package depend on unrelated packages.pkg_dir but was
not included in packages. Component R version requirements are propagated to
the generated DESCRIPTION for enforcement on the recipient's R version.create_metapackage() gained include_archives, TRUE by default, which
copies the component archives into inst/archives/ of the generated
meta-package. Its installer then defaults pkg_dir to
system.file("archives", package = "<meta>"), resolved when the installer is
called, so the meta-package is the only artifact that has to be distributed
and its components install with no arguments, with no path agreed on
beforehand. Network access remains necessary only for components that depend
on a package coming from a repository. Pass include_archives = FALSE to keep
the archives in a shared location the recipient can reach.inst/archives/, so
shipped components reach the tarball while every other archive anywhere in the
tree is still excluded.cli two-column startup message
that falls back to the ASCII banner when cli is absent, a
<meta>.quiet option, <meta>_conflicts() for masking conflicts, explicit
reinstall and upgrade policies (force, and
upgrade = "newer" | "always" | "never"), and an optional ordered workflow
vignette through the workflow argument.Config/bigbang/packages,
and the generated package tests that the list agrees with what it exports.tempdir()
sits under /var, itself a link to /private/var. Both sides are now
normalised at the same moment.._<dir>
member is accepted. Archiving a package directory on macOS with extended
attributes emits one, and R installs such an archive, so rejecting it rejected
a working package.diagnose_dependencies() extracts through the same guarded path as generation.
A component carrying a symbolic link made the scanner read a file outside the
archive and return its contents in the result.dest_dir and pkg_dir paths, and roll back
incomplete project trees created by a failed invocation.create_metapackage() validates name before writing anything: against the R
package name grammar, and against the names R itself ships. A name carrying a
path separator or a parent reference previously placed the generated tree
outside dest_dir and still reported success.dependencies = NA, which covers
Depends, Imports and LinkingTo, instead of TRUE, which also covered
Suggests. Asking for one small dependency used to pull development tooling and
its whole tree into the library.result$path came back in the platform convention
and therefore did not compare equal to a path the caller had built with
file.path(). The containment checks normalise both sides the same way, so a
destination that does not exist yet cannot be compared against one that does
in a different convention.Package and Version fields are validated against their
filenames, duplicate component versions and archive basenames are rejected
while generating, and generated installers verify the declared version..Rbuildignore rules that could exclude the generated package's own files or
shipped archives.unchanged element of
an installation result now carries the same two versions instead of the label
"Already installed", which is untrue when the installed package only shares a
component's name; the result is the only thing a calling script can inspect.tests/DESCRIPTION files are allowed, while a missing root DESCRIPTION is
reported clearly.safe_unlink() uses temporary-directory containment rather than a broad
basename heuristic.Matrix, and an identifier beginning with st_ no longer suggests sf.The maintainer's given name is spelled Sebastián, and the author entry now carries an ORCID identifier.
Documented that distributing the component archives inside a meta-package is a redistribution, so their licenses have to allow it, and that a component still installs only where its format can.
Documented related meta-package projects and design precedents.
Added the r-universe version badge and the one-line install from the universe binaries.
First release on CRAN, accepted on 2026-08-08.
bigbang — create custom R metapackages from local packages
.onLoad() hooks are side-effect free; component installation is explicit via
<meta>_install().tmp, and content hashes for decoy directories.scan_bigbang_artifact() to identify the historical V1/V2/V3/V7
signatures in source trees, archives, and installed packages without loading
them.bigbang_error_cycle condition.skip, error, install) and
content-based distinction between source ZIPs and Windows binary ZIPs.create_metapackage(),
install_local_pkg(), and diagnose_dependencies(). Spanish aliases remain
available as deprecated transition wrappers.bigbang and generated metapackages.