pub enum HelpTopic {
Root,
Daemon,
Init,
Cd,
Add,
Remove,
Monitored,
Query,
Clean,
Changes,
}
pub const fn about(topic: HelpTopic) -> &'static str {
match topic {
HelpTopic::Root => "Lightweight high-performance file change tracking tool",
HelpTopic::Daemon => "Run the fsmon daemon (requires sudo for fanotify)",
HelpTopic::Init => "Initialize log and monitored data directories",
HelpTopic::Cd => "Open a subshell in the log directory",
HelpTopic::Add => "Add a path to the monitoring list",
HelpTopic::Remove => "Remove one or more paths from the monitoring list",
HelpTopic::Monitored => "List all monitored paths with their configuration",
HelpTopic::Query => "Query historical file change events from log files",
HelpTopic::Clean => "Clean historical log files, retain by time or size",
HelpTopic::Changes => "Show the most recent event per path (deduplicated changes)",
}
}
pub const fn long_about(topic: HelpTopic) -> &'static str {
match topic {
HelpTopic::Root => "",
HelpTopic::Daemon => {
r#"Run the fsmon daemon as a foreground process (requires sudo for fanotify).
The daemon monitors all configured paths via fanotify and logs events.
Use 'fsmon add'/'fsmon remove' to manage paths dynamically without
restarting the daemon.
Usage:
sudo fsmon daemon & Start daemon in background
sudo fsmon daemon --debug Enable debug output
sudo fsmon daemon --channel-capacity 1024 Event channel cap (default: unbounded)
sudo fsmon daemon --disk-min-free 10% Warn when disk < 10% free
sudo fsmon daemon --cache-dir-cap 200000 Override dir_cache capacity
fsmon add /path Monitor all events on /path
fsmon add openclaw --path /home -r Track openclaw on /home (recursive)
fsmon monitored List monitored paths
fsmon query -t '>1h' Query events from last hour
For systemd integration:
sudo fsmon init --service Install systemd service (auto-start on crash)
sudo systemctl start fsmon Start via systemd
journalctl -u fsmon -f View daemon logs
Config: ~/.config/fsmon/fsmon.toml
Monitored: ~/.local/share/fsmon/monitored.jsonl (configurable via [monitored].path)
Log dir: ~/.local/state/fsmon/ (configurable via [logging].path)
Socket: /tmp/fsmon-<UID>.sock (configurable via [socket].path)"#
}
HelpTopic::Init => {
r#"Initialize fsmon data directories (chezmoi-style).
Creates:
~/.local/state/fsmon/ Event log storage
~/.local/share/fsmon/ Monitored paths database
~/.config/fsmon/fsmon.toml Reference config (all commented, defaults apply)
With --service, also installs a systemd service for automatic crash recovery:
sudo fsmon init --service
Examples:
fsmon init"#
}
HelpTopic::Cd => {
r#"Open a subshell in the log directory.
Spawns a new shell (using $SHELL, fallback /bin/sh) inside the
log directory. Type 'exit' to return to the original directory.
Examples:
fsmon cd Enter log directory in subshell
fsmon cd && ls List log files, then exit"#
}
HelpTopic::Add => {
r#"Add a path or process to the monitoring list.
The entry is added immediately if the daemon is running, and persisted
in the monitored paths database for automatic monitoring on daemon restart.
No sudo needed — store is updated immediately.
USAGE:
fsmon add [CMD] [OPTIONS]
ARGS:
<CMD> Process name to track (process tree + ancestry chain).
Enables process tree tracking: fork/exec children are auto-included.
When specified, matching events include a `chain` field.
Omit to monitor all events on a path (path-only mode).
Options:
--path <PATH> Filesystem path to monitor
-r, --recursive Watch subdirectories recursively
-t, --types Event types to monitor (repeatable; use "all" for all 14 types)
-s, --size Size filter with operator (required: >=, >, <=, <, =)
e.g. >1MB, >=500KB, <100MB, =0
Examples:
fsmon add openclaw --path /home -r Track openclaw on /home (recursive)
fsmon add nginx Track nginx globally (process-only)
fsmon add --path /home -r Monitor /home recursively (path-only)
fsmon add --path /home --types MODIFY --types CREATE Filter by event types
fsmon add --path /home --types all All 14 event types
fsmon add --path /home -s '>=1MB' Minimum file size change"#
}
HelpTopic::Remove => {
r#"Remove one or more paths from the monitoring list.
Without --path, removes the entire cmd group (including the null group).
With --path, removes only the specified paths. Multiple paths are atomic:
all must exist, or nothing is removed.
USAGE:
fsmon remove [CMD] [--path <PATH>...]
ARGS:
<CMD> Cmd group to remove (positional). Omit for null cmd group.
Options:
--path <PATH> Path(s) to remove from the cmd group (repeatable)
Examples:
fsmon remove Remove all paths from null cmd group
fsmon remove openclaw Remove the entire openclaw cmd group
fsmon remove openclaw --path /a Remove /a from openclaw group
fsmon remove --path /a --path /b Remove /a, /b from null cmd group (atomic)"#
}
HelpTopic::Monitored => {
r#"List all monitored paths with their configuration.
Displays each path with its recursive flag, event type filters,
size threshold, path/cmd exclusion patterns.
Examples:
fsmon monitored"#
}
HelpTopic::Query => {
r#"Query historical file change events from log files.
Output is JSONL (one JSON object per line), pipe to jq for custom filtering.
USAGE:
fsmon query [CMD] [OPTIONS]
ARGS:
<CMD> Cmd group to query (positional). Omit to query all cmd groups.
Log files are named by cmd: `{cmd}_log.jsonl` or `_global_log.jsonl`.
Options:
-p, --path Path prefix filter(s) applied to event.path. Repeatable.
-t, --time Time filter with operator (repeatable).
>1h — events newer than 1 hour ago (since)
<2026-05-01 — events before a date (until)
Combine both for a range: -t '>1h' -t '<now'
Alternatively, query the log files directly with standard Unix tools:
cat ~/.local/state/fsmon/*_log.jsonl | jq 'select(.cmd == "nginx")'
grep '"event_type":"MODIFY"' ~/.local/state/fsmon/*_log.jsonl
tail -f ~/.local/state/fsmon/*_log.jsonl | jq 'select(.user == "deploy")'
(Note: native fsmon query uses binary search and is significantly faster on large logs)
Examples:
fsmon query All events from all cmd groups
fsmon query openclaw Events from openclaw cmd group
fsmon query --path /home Events under /home (all cmd groups)
fsmon query nginx --path /var/www Nginx events under /var/www
fsmon query -t '>1h' Events from last hour"#
}
HelpTopic::Clean => {
r#"Clean a log file for a specific cmd group, retain by time or size.
Defaults: keep_days=30, size=>=1GB (from fsmon.toml [logging] section or code fallback).
CLI args override config. Daemon does not auto-clean; use cron/systemd timer.
USAGE:
fsmon clean <CMD> [OPTIONS]
ARGS:
<CMD> Cmd group to clean (positional). Use '_global' for the global log.
Options:
-t, --time Time filter with operator (e.g. >30d — keep newer than 30 days)
-s, --size Size limit for log file truncation with operator (e.g. >500MB, >=1GB).
Operator required: >=, >, <=, <, =
--dry-run Preview mode, don't actually delete
Alternatively, clean the log files directly with standard Unix tools:
truncate --size 100M ~/.local/state/fsmon/*_log.jsonl
for f in ~/.local/state/fsmon/*_log.jsonl; do tail -500 "$f" > "${f}.tmp" && mv "${f}.tmp" "$f"; done
find ~/.local/state/fsmon/ -name '*.jsonl' -mtime +30 -delete
(Note: native fsmon clean uses accurate JSONL parsing and is safer for large files)
Examples:
fsmon clean _global Clean global log with defaults (>=30d)
fsmon clean openclaw -t '>7d' Keep last 7 days of openclaw events
fsmon clean nginx --dry-run Preview nginx log cleaning"#
}
HelpTopic::Changes => {
include_str!("help/changes.md")
}
}
}
pub const fn after_help() -> &'static str {
r#"Use 'fsmon <COMMAND> --help' for detailed help
Setup (no sudo needed):
fsmon init Create log, monitored directories and config
sudo fsmon init --service Also install systemd service (auto-start on crash)
fsmon cd Open subshell in log directory
Daemon (requires sudo):
sudo fsmon daemon & Start daemon in background
sudo systemctl start fsmon Start via systemd (if installed)
sudo systemctl stop fsmon Stop via systemd
journalctl -u fsmon -f View daemon logs via systemd
kill %1 Stop daemon (or Ctrl+C)
Management (no sudo needed):
fsmon add openclaw --path /home -r Track openclaw on /home (recursive)
fsmon add /path -r Monitor path (recursive, default 8 types)
fsmon remove Remove entire null cmd group
fsmon remove openclaw Remove entire openclaw cmd group
fsmon monitored List monitored paths
Query (stdout JSONL, pipe to jq):
fsmon query -t '>1h' Events from last hour
fsmon query | jq 'select(.cmd == "nginx")' Custom filter
cat ~/.local/state/fsmon/*_log.jsonl | jq ... Or direct pipe (slower)
Clean (config defaults: keep_days=30, size=>=1GB):
fsmon clean _global Clean global log (keep >30d)
fsmon clean openclaw -t '>7d' Keep last 7 days of openclaw
fsmon clean nginx --dry-run Preview nginx log cleaning
tail -500 ... Or direct Unix tools (slower)
Config: ~/.config/fsmon/fsmon.toml (created by fsmon init, all-commented — defaults apply)
Monitor: ~/.local/share/fsmon/monitored.jsonl (configurable via [monitored].path)
Logs: ~/.local/state/fsmon/*_log.jsonl (configurable via [logging].path)"#
}