socket manifest <subcommand> generates declarative dependency manifests
(pom.xml, requirements.txt, etc.) for ecosystems whose canonical build
system does not ship one out of the box. The resulting files are consumed by
socket scan create's server-side per-ecosystem parsers.
Sections are sorted alphabetically by subcommand name.
Auto-detect the build system in the target directory and run the matching manifest generator. Useful when you do not want to spell out the language.
Generates Bazel SBOM manifests (Maven maven_install.json and/or PyPI
requirements.txt) by running bazel query against discovered ecosystem
hubs in a Bazel workspace. Output is consumed by socket scan create and
closes the inline-declaration gap that lockfile-only parsing misses for
Bazel monorepos.
Note: This command generates dependency manifests for Bazel workspaces (Maven and PyPI). It does not run reachability analysis.
socket manifest bazel [options] [DIR=.]--bazel <path>— path to bazel/bazelisk binary; default$(which bazelisk) || $(which bazel).--bazel-rc <path>— path to additional.bazelrcfragments forwarded to bazel.--bazel-flags <str>— flags forwarded to every bazel invocation (single quoted string).--bazel-output-base <dir>— Bazel--output_basefor read-only-cache CI environments.--ecosystem <name>— ecosystem(s) to extract; repeatable. Supported values:maven,pypi. When omitted, Maven is generated by default; PyPI is explicit opt-in.--out <dir>— output directory; default./.socket/bazel-manifests/.--dry-run,--verbose— standard diagnostic flags.
Upload: This subcommand only generates manifests. To generate and upload in one step, use
socket scan create --auto-manifest .— it detects the workspace, generates Bazel Maven manifests, and uploads the result. Generate Bazel PyPI manifests explicitly withsocket manifest bazel --ecosystem pypi, then scan the generated output withsocket scan create.
# Generate the default Bazel Maven manifest from the current workspace.
socket manifest bazel .
# Generate only the PyPI manifest.
socket manifest bazel . --ecosystem pypi
# Generate both Maven and PyPI manifests explicitly.
socket manifest bazel . --ecosystem maven --ecosystem pypi
# Use bazelisk explicitly.
socket manifest bazel --bazel=/usr/local/bin/bazelisk .When --ecosystem pypi is selected, the command:
- Discovers
rules_pythonpip hubs from Bazel'smod show_extensionoutput when available, with bounded static parsing ofMODULE.bazel(pip.parse(hub_name = "...")) and legacyWORKSPACE(pip_parse(name = "...")/pip_install(name = "...")) retained as fallback. Hub names are never hardcoded; custom names likemy_pypiare detected automatically. - Validates each candidate hub by probing it with
bazel queryfor:pkgtargets /alias(rules. Invalid candidates are dropped. - Runs
bazel query 'deps(kind("py_library|py_binary|py_test", //...))'to determine which PyPI packages are actually reached by Python rules in the repo (test dependencies included for whole-repo scope). - Reads
requirements_lock.txt(the path discovered frompip.parse(requirements_lock = "...")) for canonical pinned versions. When the lockfile is unavailable, falls back to parsingpypi_name=andpypi_version=tags from the spokepy_libraryrules in the hub-and-spoke architecture. - Emits a sorted canonical
requirements.txtcontainingname==versionlines for every reached package.
- PEP 503 normalization. Package matching uses PEP 503 normalization
(lowercase, then any run of
-,_, or.is collapsed to a single-). Bazel target names use underscores (charset_normalizer); PyPI canonical names use hyphens (charset-normalizer). The emittedrequirements.txtalways uses the canonical hyphenated form. - Lockfile pins win. When the lockfile and spoke-repo tags disagree on
a version, the lockfile wins because that is the version Bazel actually
resolves at analysis time. A
--verbosewarning is logged for the divergence. - Conflict detection. When two reached packages normalize to the same
PyPI name with different versions, the command fails clearly: a single
requirements.txtcannot represent both versions, and silently picking one would produce a misleading SBOM.
The PyPI extractor is intentionally narrow in this phase:
- Direct URL, editable (
-e), and unpinned requirements are not emitted. Only canonicalname==versionlines from the resolved lockfile are produced. Repositories that rely on unpinned or URL-pinned requirements will see those packages omitted fromrequirements.txt. - Private corpus validation requires authenticated GitHub access. When credentials are unavailable, the bazel-bench harness's private PyPI case skips cleanly with a distinct reason rather than failing.
- Whole-repo extraction. The initial PyPI implementation emits one whole-workspace manifest. Per-target PyPI slicing is not currently supported.
Bazel repos with cross-language dependencies (e.g. rust_library →
py_library via PyO3 / cffi / etc.) are not traversed by the PyPI
extractor in this phase. The PyPI extractor only covers Python rule
dependencies reachable from py_library, py_binary, and py_test
targets. Cross-language edges are assigned to Phase 4. The bazel-bench
fixture constructed/python-pypi includes Go/Rust sidecars as
validation context only; they are intentionally not asserted by the
PyPI correctness cases.
bazelorbazeliskonPATH(or pass--bazel <path>).- Network access on cold cache. Bazel and
rules_jvm_external/rules_pythonown their own retry policy for transient resolution failures —socket manifest bazeldoes not retry on top of them. - Writable Bazel output base; pass
--bazel-output-basefor read-only-cache CI. - For PyPI extraction: a Python 3 interpreter on
PATHso the rules_python toolchain can analyze the workspace.
This is the user-visible entry point for Bazel SBOM support (Maven and PyPI); the [beta] label and "Bazel SBOM support" wording must stay consistent across release notes and docs.
Wraps the upstream cdxgen CycloneDX BOM generator for repos that already
have a working cdxgen configuration.
Converts a Conda environment.yml file to a Python requirements.txt so the
Socket scan pipeline can consume the resulting manifest.
Uses Gradle (via the project's gradlew) to emit a pom.xml per subproject,
then feeds those files into the Socket scan pipeline. Mirrors the kotlin and
scala flows.
Uses Gradle to generate a manifest file (pom.xml) for a Kotlin project; the
underlying flow is identical to the gradle subcommand.
Generates a Socket facts file (.socket.facts.json) from a Maven pom.xml
project, using mvn (override with --bin, e.g. a project ./mvnw wrapper).
Pass extra options through to maven with --maven-opts (e.g.
--maven-opts="-P release -s settings.xml").
Generates a manifest file (pom.xml) from Scala's build.sbt file.
Starts an interactive configurator that writes default flag values for
socket manifest into a socket.json in the current directory.
Run it like these examples:
# Scala:
npm run bs manifest scala -- --bin ~/apps/sbt/bin/sbt ~/socket/repos/scala/akka
# Gradle/Kotlin
npm run bs manifest yolo -- --cwd ~/socket/repos/kotlin/kotlinx.coroutines
And upload with this:
npm exec socket scan create -- --repo=example-repo --branch=example-branch --tmp --cwd ~/repos/scala/akka example-org .
npm exec socket scan create -- --repo=example-repo --branch=example-branch --tmp --cwd ~/repos/kotlin/kotlinx.coroutines .
(The cwd option for create is necessary because we can't go to the dir and run npm exec).
User flow look something like this:
socket manifest scala .
socket manifest kotlin .
socket manifest yolo
socket scan create --repo=example-repo --branch=example-branch --tmp example-org .