尚未检测到更新。GitHub 发布版本后会显示在这里。
个人 GitHub 账号下公开仓库的所有者可以登录并验证所有权,自行管理介绍,无需管理员批准。
登录并生成验证文件,在 30 分钟内将其提交到此仓库的默认分支。其他分支或分叉仓库中的文件无效。然后在下方检查文件,即可无需管理员批准直接管理项目。请保留文件以维持管理权限。
如需登录,将前往登录页面。登录后请回到此处,再次点击所选的验证按钮。
在项目文件夹中运行 /nomorevibe verify,即可验证所有权并自行管理介绍。
一分钟完成验证制作者的介绍仅有上面的一句话。 更多详情请阅读仓库 README。 仓库 README ↗
正在加载完整 README。
查看完整 README ↗The Script Catalog is a tool for discovering, searching, and understanding scripts.
It provides:
The catalog is indexed nightly on a central CRON server and consumed read‑only by engineers on RHEL systems.
The project website publishes these guides with
shared navigation; the documentation index
lists them all. The Markdown in docs/ is the source of truth.
Website development instructions cover the Astro build.
Over time, the number of Python and shell scripts grows significantly:
This tool provides a single searchable index without:
┌────────────────────┐
│ RHEL CRON server │
│ │
│ Nightly index job │
│ - scan scripts │
│ - parse scripts │
│ - run tree-sitter │
│ - build SQLite │
└─────────┬──────────┘
│
scripts.sqlite (read-only,
on the shared drive)
│
┌─────────────────┴────────────────┐
│ one copy per host, per rebuild │
┌───────────────┐ ┌───────────────┐
│ RHEL host A │ │ RHEL host B │
│ │ │ │
│ /dev/shm copy │ │ /dev/shm copy │
│ ↑ scat CLI │ │ ↑ scat CLI │
│ ↑ scat TUI │ │ ↑ scat TUI │
└───────────────┘ └───────────────┘
scat deps <path> --tree [--depth N].csv, .txt, .lst) are catalogued but only their first 20
lines are stored — enough to show the data format, without full-text indexing
feeds and exports that are large and refresh constantly@inputfile, @outputfile, …) are searchable
and navigable even when they aren't cataloged:
scat search --declares report.csv [--role outputfile], and
scat deps <declared-path> lists the scripts that declare itscat completions bash|zsh|fish|powershell|elvishscat man --dir /usr/share/man/man1 (one page per command; the RPM installs them)scat similar <path> [--limit N]
— requires an embeddings.sqlite sidecar built separately by scat-embed
(see the scat-embed source) and published next to the
catalog (or wherever embeddings_path/--embeddings/SCAT_EMBEDDINGS
points); ranks scripts already in the catalog against each other and never
embeds a typed query — see
tjorim/scat#73 for why.Use F7 for similar scripts, F8 for catalog-wide checkout/warning status,
F9 for transitive uses/used-by trees, and F10 for incoming/outgoing symlinks.
These actions are also in F1 help and the F4 palette. Move with Up/Down, press
Enter for script details, then Esc to return to the inspection results. Esc
closes the results. Use +/- to adjust the similarity limit or tree depth
(minimum 1), and r to reload. Trees show edge kinds, unresolved paths, cycles,
repeated subtrees and depth cutoffs. Similarity uses the same configured
--embeddings sidecar and local cache as the CLI; clients never load a model.
Press F11 for script/file/revision or whole-catalog comparisons, and F12
for JSON or search CSV export. The dialog accepts the same read-only command
arguments as the CLI (without scat), including --against, --old/--new,
revision selectors, --fields, and output formats. Tab selects a field; Ctrl+U
clears it; Enter generates output. F1 shows examples for every comparison mode.
PageUp/PageDown scroll the output.
Search export defaults to displayed: the captured search rows, with their
count and TUI limit shown. Only format and selected fields apply in this scope.
Select requested to run a fresh query; an explicit search --limit makes
larger exports deliberate. Inspection exports run fresh requests using the
shown limit/depth. F3 sends a terminal clipboard request; Ctrl+S saves generated
output to the absolute local path you enter, refusing existing files (including
symlinks). Comparison, export and save work runs in the background; errors stay
in the dialog. Esc closes it and preserves the underlying view and selection.
Press F6 (also listed in F1 help and the F4 palette) to edit search mode,
role, language, owner, tag and the positive result limit. Tab selects a field,
Ctrl+U clears it, Enter applies settings and Esc cancels. The search box supplies
the pattern for text, regex, function-name substring or declared-file search.
Role applies only to declared-file search; leave it blank to match all roles.
Settings remain active across searches. Explicit editor filters override matching
text filter tokens. Advanced patterns are literal patterns, so lang:/owner:/
tag: tokens are interpreted only in text mode.
Text mode expands an exact @bookmark from configuration, showing the expansion
in the search title; unknown bookmarks use the alias without @, like the CLI.
Unlike CLI text search, live TUI text search prefixes the final term as you type.
Other modes use the CLI SearchApi directly. The results title shows the configured
window and warns when the cap is reached (more matches may exist); ranking applies
to that result window. F6 settings keep expensive searches on the worker thread.
lang:, owner:, and tag: tokens in the search box filter results the
same way the CLI's --lang/--owner/--tag flags do
(e.g. backup lang:python owner:alice)v — view the indexed catalog content (scripts.content, exactly what
the preview/search show), written to a temp file with the original filenameV — view the live filesystem source resolved through the configured
path mapping (or the logical path directly when it is already a real file),
failing clearly when the source file cannot be found$SCAT_EDITOR, then $VISUAL, then
$EDITOR, falling back to view/vim -R/vi -R/less. Vim-compatible
editors are opened read-only so you can search with / without
accidentally editing.Example commands:
scat search "patch freeze"
scat show /catalog/scripts/foo/bar.py
scat deps /catalog/scripts/foo/bar.py
scat deps /catalog/scripts/foo/bar.py --tree --depth 3
scat catalog stats
scat tui
scat completions bash
Press F1 in any TUI view for contextual help, or F4 to search the
command palette. The palette shows shortcuts and marks unavailable actions;
Enter runs the selected action and Esc closes either popup. Search input keeps
ordinary characters, including ?, as text. F2 toggles native terminal text
selection and F3 copies the focused content. Use scat tui --terminal-info to
inspect terminal/session hints, --glyphs ascii for constrained fonts/locales,
and --colors reduced|mono or global --no-color to limit colors. See
terminal modes and SSH guidance.
Wide terminals show all panes. Below 110 columns or 30 body rows, the active
pane is shown with tabs; use Tab/Shift+Tab or click a tab to switch panes.
Focus and selection survive resizing and fullscreen changes. Scrollbars are
position indicators; use the existing keyboard shortcuts or mouse wheel to
navigate. Revision tables keep type and checkout path visible, hide owner
below 72 columns, and hide timestamp below 48 columns. * marks the active
revision; Enter opens the selected revision diff and Esc returns to its row.
Scripts under change control keep several files per tool on disk: an active
symlink (prepare_release), the version copies vc retains beside it for
rollback (prepare_release_20260729_140513), and the DEVELOP/ARCHIVE
containers holding checkouts and older versions.
Only the active script is indexed into the catalog — one entry per tool, not
one per retained version. The rest are recorded as revisions of that
script and surface through scat show, the TUI's revisions pane, and
scat catalog stats, so a search for prepare_release returns the tool
rather than every version of it. This holds whether or not the script name
carries an extension. Editor backup files (prepare_release~) are skipped.
Container directory names are matched exactly as configured under vc.develop_dirs
and vc.archive_dirs, so a tree whose containers are spelled differently from the
DEVELOP/ARCHIVE defaults must list its own spelling there.
Where the catalog shows a symlinked script, it also shows what the link
resolved to at index time — a ↳ <target> sub-row in the CLI's search table,
a → <target> suffix in the TUI's results list and metadata pane. Since the
catalog is built nightly, a script checked in during the day still shows the
version that was live when the index was last built.
Dependency extraction uses Tree‑sitter for accurate parsing.
Two kinds of dependency edges are recorded:
import — language-level edges: Python import/from statements and
bare-name shell source/. directives (source common.sh), resolved
through module/basename mapping. A source/. of a path
(source ../lib/common.sh) is treated as a referenced edge instead, so it
resolves by path.referenced — a script invoked by path rather than imported: a shell
script that scp/ssh-runs another script, a Python file executing one via
subprocess/paramiko, or a JSON/YAML manifest listing scripts to run.
These are found by scanning the file body for path literals and are kept
only when the path resolves to an indexed script — either an absolute
logical path matched exactly, or a relative path (./x.py,
../lib/x.py) resolved against the referencing script's own directory.
Unrelated strings (logs, temp files, copy destinations) are discarded.
Resolution is language-agnostic, so cross-language edges (a shell script
invoking a Python one, or vice versa) are captured. In scat deps they show
as ref (flat table) or (ref) (tree).@parentfile, @childfile, @inputfile,
@outputfile and @paramfile keywords. Each keyword is its own edge kind,
shown as parent/child/input/output/param. Unlike path literals,
these are kept even when the target isn't an indexed script (a config, data
or report file), since the author declared the relationship explicitly.
Relative paths are resolved against the declaring script's directory. Find
them with scat search --declares <substring> [--role <keyword>], and run
scat deps <path> on a declared file to see which scripts declare it.Scripts can optionally include a sidecar metadata file:
myscript.py
myscript.py.meta.yml
Example myscript.py.meta.yml:
owner: [email protected]
purpose: Verify patch freeze consistency
tags:
- patching
- validation
entry_points:
- main
related:
- /catalog/scripts/common/logging.py
Metadata is indexed together with the script content. When multiple sources provide the same field, precedence is deterministic:
.meta.yml sidecar@brief, @author, @techowner,
@funcowner, and @historyscat can read an optional config file (JSON or YAML, detected from the
extension) for the database path, scan roots, ignore patterns, vc
executable/checkout dirs, and search bookmarks. Point scat at it with
--config <path> or SCAT_CONFIG; CLI flags and env vars always take
precedence over config-file values.
See docs/scat.example.yaml for an annotated example covering every field.
Separately, scat tui accepts an optional path-mapping file (--mapping <path> / SCAT_MAPPING) that resolves a script's logical catalog path to
its real filesystem path, used by the V (view live filesystem source)
key. scat doctor PATH --mapping <path> accepts the same file for host-local
diagnostics. See
docs/scat-mapping.example.yaml.
The database contains logical paths, which by default are simply the
absolute filesystem path the indexer scanned each script from (e.g.
/shared/tools/security/foo.sh). Clients whose local mount doesn't match the
indexing host's layout can resolve them through an optional path-mapping
file instead — see docs/scat-mapping.example.yaml.
The published scripts.sqlite lives on a shared network drive, and normal browsing uses a local copy. On first use after a rebuild, one process copies the
catalog into tmpfs (/dev/shm by default) with SQLite's Online Backup API and
every scat process on that host — TUI session or one-off CLI query — reads
the local copy instead. Staleness is detected from the published file's
identity and its index_metadata.build_timestamp, so the copy costs one read
per host per nightly rebuild rather than one per invocation.
This keeps SQLite's locking off the network filesystem entirely, which matters
because NFS byte-range locks are a documented source of client/server bugs and
WAL mode needs an mmap-able -shm file that network filesystems generally
don't provide. For the same reason the published catalog is written in
rollback-journal mode: a WAL database needs that -shm file even for
read-only connections.
The cache is never load-bearing. If /dev/shm is missing, full, or owned by
another user, scat logs a warning and reads the shared drive directly.
| Flag | Env | Effect |
|---|---|---|
--cache-dir <path> | SCAT_CACHE_DIR | Cache root (default /dev/shm) |
--no-cache | SCAT_NO_CACHE | Query the shared drive directly |
scat catalog info prints the cache path in use when one is active.
The embeddings.sqlite sidecar scat similar reads goes through the same
host-local cache, under its own entry — it's a separate file, published
separately (a scat-embed run, not the nightly indexer), but it lands on the
same kind of shared drive and gets the same treatment. It has no
index_metadata.build_timestamp the way the catalog does, so a changed
sidecar is always recopied rather than sometimes re-stamped in place; that's
a fine tradeoff for a file this much smaller than the catalog. The sidecar
records its format and the catalog build it embedded; see
COMPATIBILITY.md for how mismatches are reported.
✅ RHEL / Linux
✅ No internet access required
✅ Single compiled binary
✅ No background services
✅ No open ports
❌ Windows — support was dropped; clients and the indexer are Linux-only. The build fails fast on non-Unix targets rather than producing a binary whose atomic swap and tmpfs cache have no working equivalent.
The release artifact is a compiled Rust binary:
| Platform | Artifact | Rust Target |
|---|---|---|
| RHEL / Linux x86-64 | scat | x86_64-unknown-linux-musl |
Copy the artifact to a directory on PATH, set SCAT_DB to the shared
scripts.sqlite catalog, and run scat.
For deployment details, see the deployment guide.
Tree‑sitter parsing is compiled into the Rust binary. No separate grammar shared library is deployed to user machines.
Typical flow:
scat/
├── src/ # Rust CLI, core search API, and indexer
├── tests/ # Rust integration tests
├── docs/ # design documents and deployment guides (Markdown)
├── site/ # Astro website that publishes the landing page and docs
└── README.md
scat's CLI and indexer are implemented in Rust, producing a compiled native
binary for RHEL (x86-64). This removes Python version constraints, vendored
wheels, and the scat.sh bootstrap script.
| Concern | Choice |
|---|---|
| CLI | clap (derive) |
| SQLite | rusqlite with features = ["bundled-full"] (bundled SQLite + FTS5) |
| JSON | serde + serde_json |
| YAML | yaml_serde (official YAML org) |
| Tree-sitter | tree-sitter + tree-sitter-python + tree-sitter-bash |
| TUI | ratatui with crossterm (multi-pane, vim keybindings) |
catalog build/stats/info/audit/diff)x86_64-unknown-linux-musl binaryPlease:
This project was developed with significant assistance from AI coding assistants, used for code generation, architecture discussions, and code review. All code has been reviewed and tested by human contributors.
Run scat doctor (or scat doctor --json for support tooling) without a working
catalog or privileged access. In the TUI, choose Host diagnostics from F4 or
press Alt+d, then Enter. Escape cancels a running diagnostics request. With
a selected script, this view queries its mapped host-local path and optional RPM
provenance. CLI examples:
scat --db /shared/catalog.sqlite doctor --json
scat doctor /logical/script --mapping mapping.yaml --rpm --json
Doctor reports terminal capabilities using the same detection as the TUI,
source/catalog availability, catalog build age, existing cache freshness and the
predicted read path, mount restrictions, viewer candidates and policy state.
It never refreshes the cache or changes configuration or system policy. A normal
catalog read may refresh a stale cache, so its eventual read path can differ
from doctor's prediction. TUI diagnostics run in a captured worker; terminal
interactivity in that worker describes its pipes. scat tui --terminal-info
reports the foreground terminal directly.
JSON uses schema_version: 1; unavailable tools and timed-out probes return
explicit unknown/unavailable results. Filesystem probes have six-second budgets;
individual tool invocations have two-second budgets. Raw command stderr, viewer
arguments, arbitrary configuration values and credential-bearing mount options
are omitted. Review paths and host identifiers before sharing support output.
RPM provenance belongs to the queried host and resolved path, independently of
catalog metadata or indexing-host paths. Only the selected file is hashed:
size, mode, mtime, link target and SHA-256/SHA-512 digests are compared with RPM
metadata. unchanged applies to these checks; ownership names, capabilities and
security labels are outside this verification scope. Unsupported digest
algorithms, RPM failures and unavailable files are unverifiable.
A readable catalog on a noexec mount is usable; executing a viewer from that
mount is a separate operation. PermissionDenied alone does not establish a
policy denial. For a selected path, doctor makes bounded, read-only recent audit queries and
reports counts of matching records and denial markers. Raw logs are omitted;
no matches and inaccessible logs remain unknown. It also suggests audit commands
for further investigation. An active fapolicyd service does not prove enforcement.
See Red Hat's SELinux troubleshooting
and fapolicyd guidance
for administrator-owned investigations.
Original project material, including scat, scat-embed, documentation, website and artwork, is licensed under the Apache License 2.0. Copyright 2026 scat contributors. Third-party dependencies and downloaded models retain their own terms. See the licensing and distribution guide for provenance, exclusions and the notices that accompany releases.