π§© Plugins and extractors that ArchiveBox + abx-dl use: chrome, ytdlp, wget, singlefile, readability, forum-dl, gallery-dl, papers-dl, and more...
14
stars
1,318
commits
Python
primary language
Sep 11, 2026
updated
ArchiveBox-compatible plugin suite (hooks and config schemas).
This package contains standalone plugin hook scripts and config schemas. A hook
can be run directly as a CLI; runners such as abx-dl
and archivebox add orchestration,
environment setup, and cache projection around the same scripts.
Tools like abx-dl and ArchiveBox can discover plugins from this package
without symlinks or environment-variable tricks.
Each plugin lives under plugins/<name>/ and may include:
config.json config schemaconfig.json: category, display_order, hidden, and x-auto-run (set false for hooks that require explicit host selection)config.json > required_binaries binary dependency declarations (optional)on_CrawlSetup__... crawl setup hook scripts (optional) - shared setup/process startup, emit no stdout JSONL recordson_Snapshot__... per-snapshot hooks - emit ArchiveResult and may also emit Snapshot / TagHooks run with:
.).)SNAP_DIR/<plugin>/...CRAWL_DIR/<plugin>/...../<other-plugin>/... from your own output dirSNAP_DIR - base snapshot directory (default: .)CRAWL_DIR - base crawl directory (default: .)ABXPKG_LIB_DIR - binaries/tools root (default: ~/.config/abx/lib)PERSONAS_DIR - persona profiles root (default: ~/.config/abx/personas)ACTIVE_PERSONA - persona name (default: Default)Lifecycle:
config.json > required_binaries declares plugin dependencies.*_BINARY values from env, known local paths, and abxpkg provider state so hooks can run as standalone CLIs.abx-dl and ArchiveBox use abxpkg services/cache backends to prepare env/DB state, but hooks must not depend on those services being active.config.json declaration:
[
{
"name": "{YTDLP_BINARY}",
"binproviders": "env,uv,brew,apt",
"min_version": null,
"overrides": {
"uv": {
"install_args": ["yt-dlp[default]"]
}
}
}
]
Runners may project resolved binary metadata internally as BinaryEvent records shaped like:
{"type":"Binary","name":"yt-dlp","abspath":"/abs/path","version":"2025.01.01","sha256":"<optional>","binprovider":"pip","machine_id":"<recommended>","binary_id":"<recommended>"}
Notes:
config.json > required_binaries.abxpkg.abxpkg owns the provider cache under ABXPKG_LIB_DIR; ArchiveBox may additionally project resolved binary events into DB machine_binary rows. Plugins and abx-dl stay unaware of both persistence layers.State/OS:
CRAWL_DIR/<plugin>/ABXPKG_LIB_DIR (e.g. npm prefix, pip venv, puppeteer cache)apt (Debian/Ubuntu), brew (macOS/Linux), and language/runtime-specific installers; many hooks currently assume POSIX pathsLifecycle:
on_CrawlSetup__* runs before snapshot extraction; background setup hooks use their first stdout line as readiness and emit no stdout JSONL recordson_Snapshot__* runs once per snapshot; background hooks use their first stdout line as readiness and then may emit ArchiveResult, Snapshot, and Tag records onlyState:
SNAP_DIR/<plugin>/../<plugin>/...Output records:
on_Snapshot__* should finish with an ArchiveResult record:{"type":"ArchiveResult","status":"succeeded|noresults|skipped|failed","output_str":"path-or-message"}
Snapshot and Tag records may appear before the final ArchiveResultSemantics:
stdout: for background hooks, the first line is the readiness boundary; hook JSONL records may followstderr: diagnostics/logging0: succeeded, noresults, or skippedRules:
on_CrawlSetup__* hooks should communicate only through side effects such as files, sockets, long-lived processes, or the background readiness stdout line, not stdout JSONL recordson_Snapshot__* hooks should not emit Machine, Process, or Binary recordsThe base/ plugin provides shared Python and JS helpers that all other plugins import:
Python (base/utils.py):
from abx_plugins.plugins.base.utils import (
load_config,
emit_archive_result_record,
emit_snapshot_record,
)
load_config() β load plugin config.json with env var + alias + fallback resolution, merged with shared base/common runtime vars like SNAP_DIR, CRAWL_DIR, ABXPKG_LIB_DIR, PERSONAS_DIR, EXTRA_CONTEXT, TIMEOUT, and USER_AGENTemit_archive_result_record(status, output_str) β print {"type":"ArchiveResult",...} JSONL to stdoutemit_snapshot_record(record) β emit {"type":"Snapshot",...} JSONL to stdoutwrite_text_atomic(path, content) β write file atomically (temp + rename)find_html_source(snap_dir, ...) β locate HTML from sibling pluginshas_staticfile_output(snap_dir, path) β check if a sibling plugin produced a fileenforce_lib_permissions() β lock down ABXPKG_LIB_DIR so snapshot hooks can read/execute but not writeJS (base/utils.js):
const { loadConfig, getEnv, getEnvBool, getEnvInt, getEnvArray, emitArchiveResultRecord, emitSnapshotRecord } = require('../base/utils.js');
loadConfig() β load plugin config.json merged with shared base/common runtime vars using env var + alias + fallback resolutionemitArchiveResultRecord(status, outputStr) β emit ArchiveResult JSONL to stdoutemitSnapshotRecord(record) β emit Snapshot JSONL to stdoutTest helpers (base/test_utils.py):
from abx_plugins.plugins.base.testing import (
get_hook_script,
parse_jsonl_output,
run_hook,
)
parse_jsonl_output(stdout) β extract first matching JSONL record from hook stdoutrun_hook(hook_script, url, snapshot_id=None) β run a hook subprocess with standard args, optionally relying on EXTRA_CONTEXT for snapshot metadataget_hook_script(plugin_dir, pattern) β find hook script by glob patternNote: Use
sys.path.append()(notinsert(0, ...)) because thessl/plugin directory would shadow Python's stdlibsslmodule.
succeeded if they ran and produced outputnoresults if they ran successfully but produced no meaningful output (e.g. git on a non-github url, ytdlp on a site with no media, paperdl on a site with no pdfs, etc.)skipped if only if config caused them not to run (e.g. YTDLP_ENABLED=False)failed if any hard dependencies are missing/invalid (e.g. chrome) or if the process exited non-0 / raised an exceptionoutput_str e.g. the page title, mimetype, return status code, or the relative path of the primary output file produced like output.pdf or 0 modals closed or The Page Title Verbatim or favicon.io or Not a git URLbg vs fg as the only programmatic hook distinction; words like daemon and finite in hook filenames are human hints onlyHooks emit plain JSONL records to stdout. The current hook families and records are:
on_CrawlSetup__* β background readiness line only, no stdout JSONL recordson_Snapshot__* β background readiness line when applicable, then ArchiveResult, Snapshot, Tagabx-dl and ArchiveBox map those records into their own internal event systems. Binary request events are produced from plugin config and handled by abxpkg, not by plugin hook scripts. Plugins do not need to know or emit any bus envelope format.
Python
71.6%
JavaScript
23.5%
HTML
3.5%
Shell
1.4%
π§© Plugins and extractors that ArchiveBox + abx-dl use: chrome, ytdlp, wget, singlefile, readability, forum-dl, gallery-dl, papers-dl, and more...
14
stars
1,318
commits
Python
primary language
Sep 11, 2026
updated
ArchiveBox-compatible plugin suite (hooks and config schemas).
This package contains standalone plugin hook scripts and config schemas. A hook
can be run directly as a CLI; runners such as abx-dl
and archivebox add orchestration,
environment setup, and cache projection around the same scripts.
Tools like abx-dl and ArchiveBox can discover plugins from this package
without symlinks or environment-variable tricks.
Each plugin lives under plugins/<name>/ and may include:
config.json config schemaconfig.json: category, display_order, hidden, and x-auto-run (set false for hooks that require explicit host selection)config.json > required_binaries binary dependency declarations (optional)on_CrawlSetup__... crawl setup hook scripts (optional) - shared setup/process startup, emit no stdout JSONL recordson_Snapshot__... per-snapshot hooks - emit ArchiveResult and may also emit Snapshot / TagHooks run with:
.).)SNAP_DIR/<plugin>/...CRAWL_DIR/<plugin>/...../<other-plugin>/... from your own output dirSNAP_DIR - base snapshot directory (default: .)CRAWL_DIR - base crawl directory (default: .)ABXPKG_LIB_DIR - binaries/tools root (default: ~/.config/abx/lib)PERSONAS_DIR - persona profiles root (default: ~/.config/abx/personas)ACTIVE_PERSONA - persona name (default: Default)Lifecycle:
config.json > required_binaries declares plugin dependencies.*_BINARY values from env, known local paths, and abxpkg provider state so hooks can run as standalone CLIs.abx-dl and ArchiveBox use abxpkg services/cache backends to prepare env/DB state, but hooks must not depend on those services being active.config.json declaration:
[
{
"name": "{YTDLP_BINARY}",
"binproviders": "env,uv,brew,apt",
"min_version": null,
"overrides": {
"uv": {
"install_args": ["yt-dlp[default]"]
}
}
}
]
Runners may project resolved binary metadata internally as BinaryEvent records shaped like:
{"type":"Binary","name":"yt-dlp","abspath":"/abs/path","version":"2025.01.01","sha256":"<optional>","binprovider":"pip","machine_id":"<recommended>","binary_id":"<recommended>"}
Notes:
config.json > required_binaries.abxpkg.abxpkg owns the provider cache under ABXPKG_LIB_DIR; ArchiveBox may additionally project resolved binary events into DB machine_binary rows. Plugins and abx-dl stay unaware of both persistence layers.State/OS:
CRAWL_DIR/<plugin>/ABXPKG_LIB_DIR (e.g. npm prefix, pip venv, puppeteer cache)apt (Debian/Ubuntu), brew (macOS/Linux), and language/runtime-specific installers; many hooks currently assume POSIX pathsLifecycle:
on_CrawlSetup__* runs before snapshot extraction; background setup hooks use their first stdout line as readiness and emit no stdout JSONL recordson_Snapshot__* runs once per snapshot; background hooks use their first stdout line as readiness and then may emit ArchiveResult, Snapshot, and Tag records onlyState:
SNAP_DIR/<plugin>/../<plugin>/...Output records:
on_Snapshot__* should finish with an ArchiveResult record:{"type":"ArchiveResult","status":"succeeded|noresults|skipped|failed","output_str":"path-or-message"}
Snapshot and Tag records may appear before the final ArchiveResultSemantics:
stdout: for background hooks, the first line is the readiness boundary; hook JSONL records may followstderr: diagnostics/logging0: succeeded, noresults, or skippedRules:
on_CrawlSetup__* hooks should communicate only through side effects such as files, sockets, long-lived processes, or the background readiness stdout line, not stdout JSONL recordson_Snapshot__* hooks should not emit Machine, Process, or Binary recordsThe base/ plugin provides shared Python and JS helpers that all other plugins import:
Python (base/utils.py):
from abx_plugins.plugins.base.utils import (
load_config,
emit_archive_result_record,
emit_snapshot_record,
)
load_config() β load plugin config.json with env var + alias + fallback resolution, merged with shared base/common runtime vars like SNAP_DIR, CRAWL_DIR, ABXPKG_LIB_DIR, PERSONAS_DIR, EXTRA_CONTEXT, TIMEOUT, and USER_AGENTemit_archive_result_record(status, output_str) β print {"type":"ArchiveResult",...} JSONL to stdoutemit_snapshot_record(record) β emit {"type":"Snapshot",...} JSONL to stdoutwrite_text_atomic(path, content) β write file atomically (temp + rename)find_html_source(snap_dir, ...) β locate HTML from sibling pluginshas_staticfile_output(snap_dir, path) β check if a sibling plugin produced a fileenforce_lib_permissions() β lock down ABXPKG_LIB_DIR so snapshot hooks can read/execute but not writeJS (base/utils.js):
const { loadConfig, getEnv, getEnvBool, getEnvInt, getEnvArray, emitArchiveResultRecord, emitSnapshotRecord } = require('../base/utils.js');
loadConfig() β load plugin config.json merged with shared base/common runtime vars using env var + alias + fallback resolutionemitArchiveResultRecord(status, outputStr) β emit ArchiveResult JSONL to stdoutemitSnapshotRecord(record) β emit Snapshot JSONL to stdoutTest helpers (base/test_utils.py):
from abx_plugins.plugins.base.testing import (
get_hook_script,
parse_jsonl_output,
run_hook,
)
parse_jsonl_output(stdout) β extract first matching JSONL record from hook stdoutrun_hook(hook_script, url, snapshot_id=None) β run a hook subprocess with standard args, optionally relying on EXTRA_CONTEXT for snapshot metadataget_hook_script(plugin_dir, pattern) β find hook script by glob patternNote: Use
sys.path.append()(notinsert(0, ...)) because thessl/plugin directory would shadow Python's stdlibsslmodule.
succeeded if they ran and produced outputnoresults if they ran successfully but produced no meaningful output (e.g. git on a non-github url, ytdlp on a site with no media, paperdl on a site with no pdfs, etc.)skipped if only if config caused them not to run (e.g. YTDLP_ENABLED=False)failed if any hard dependencies are missing/invalid (e.g. chrome) or if the process exited non-0 / raised an exceptionoutput_str e.g. the page title, mimetype, return status code, or the relative path of the primary output file produced like output.pdf or 0 modals closed or The Page Title Verbatim or favicon.io or Not a git URLbg vs fg as the only programmatic hook distinction; words like daemon and finite in hook filenames are human hints onlyHooks emit plain JSONL records to stdout. The current hook families and records are:
on_CrawlSetup__* β background readiness line only, no stdout JSONL recordson_Snapshot__* β background readiness line when applicable, then ArchiveResult, Snapshot, Tagabx-dl and ArchiveBox map those records into their own internal event systems. Binary request events are produced from plugin config and handled by abxpkg, not by plugin hook scripts. Plugins do not need to know or emit any bus envelope format.
Python
71.6%
JavaScript
23.5%
HTML
3.5%
Shell
1.4%