Small tools. Real problems. A slightly questionable mahjong team.
A growing collection of practical utilities by Hugo Syarof. Developer helpers, text and data converters, and file utilities — each focused on doing one useful thing well.
| Tool | What it does | Runtime |
|---|---|---|
| JSON Diff | Compare API responses or JSON files with precise field-level changes | Python 3.9+, no dependencies |
| JSON Merge Patch | Apply object updates, removals, and replacements from a merge-patch document | Python 3.9+, no dependencies |
| JSON Redact | Replace explicitly selected JSON Pointer values with a fixed string | Python 3.9+, no dependencies |
| JSON Flatten | Convert nested JSON leaves into JSON Pointer and value records | Python 3.9+, no dependencies |
| JSON Stats | Count JSON structure, depth, members, items, and value types without printing values | Python 3.9+, no dependencies |
| Env Audit | Check dotenv files for missing, undocumented, duplicate, empty, or malformed keys without exposing values | Python 3.9+, no dependencies |
| Duplicate Finder | Find byte-identical files safely and estimate reclaimable space without deleting anything | Python 3.9+, no dependencies |
| JSONL Check | Validate JSON Lines with line-level errors, duplicate-key checks, and bounded error details | Python 3.9+, no dependencies |
| CSV Audit | Check CSV headers, quoting, encoding, and row widths without exposing field contents | Python 3.9+, no dependencies |
| CSV Select | Select and reorder CSV columns with header and row-width validation | Python 3.9+, no dependencies |
| CSV Join | Join two CSV files by named key columns with inner, left, or full semantics | Python 3.9+, no dependencies |
| CSV to JSONL | Convert header-based CSV rows into JSON objects while retaining string values | Python 3.9+, no dependencies |
| Cron Next | Validate five-field cron expressions and preview timezone-aware run times | Python 3.9+, no dependencies |
| Hash Manifest | Create and verify deterministic SHA-256 inventories without following symlinks | Python 3.9+, no dependencies |
| Markdown Link Check | Check whether relative file targets in common Markdown link forms exist | Python 3.9+, no dependencies |
| Port Wait | Wait for a TCP endpoint with retries, timeout, stability checks, and JSON output | Python 3.9+, no dependencies |
| Line Unique | Remove duplicate text lines while retaining first-seen order | Python 3.9+, no dependencies |
| Line Sample | Select deterministic reservoir samples while preserving line bytes and source order | Python 3.9+, no dependencies |
| Subnet Inspect | Inspect IPv4/IPv6 CIDRs and check address membership | Python 3.9+, no dependencies |
| Query Decode | Decode form query strings into ordered name/value pairs | Python 3.10+, no dependencies |
| EOL Inspect | Count LF, CRLF and CR endings and check final newlines | Python 3.9+, no dependencies |
| Epoch Convert | Convert Unix timestamps and offset-aware ISO datetimes | Python 3.9+, no dependencies |
| Path Collisions | Find Unicode-normalized and case-insensitive path collisions | Python 3.9+, no dependencies |
| JSON Select | Extract JSON values using explicit keys and array indexes | Python 3.9+, no dependencies |
| Tree Usage | Summarize file counts and logical bytes by final extension | Python 3.9+, no dependencies |
| File Compare | Compare files and report the first differing byte offset | Python 3.9+, no dependencies |
| Hex View | Display binary input as byte offsets, hexadecimal values, and printable ASCII | Python 3.9+, no dependencies |
| Duration Sum | Add signed durations with integer microsecond precision | Python 3.9+, no dependencies |
| Base64 Codec | Encode bytes or validate and decode padded Base64 | Python 3.9+, no dependencies |
| ZIP Inventory | Summarize ZIP entry sizes, duplicate names and largest files without extraction | Python 3.9+, no dependencies |
| TAR Inventory | Summarize TAR entry types, sizes, duplicate names, and suspicious paths without extraction | Python 3.9+, no dependencies |
| Gzip Check | Validate gzip data and report sizes plus the uncompressed SHA-256 digest | Python 3.9+, no dependencies |
| Retry Command | Retry local commands after nonzero exits or per-attempt timeouts | Python 3.9+, no dependencies |
| Text Transcode | Convert explicit text encodings with strict errors and binary stdout | Python 3.9+, no dependencies |
| Byte Size | Parse exact byte quantities and display decimal and binary sizes | Python 3.9+, no dependencies |
| List Compare | Compare UTF-8 line-list membership in first-seen order | Python 3.9+, no dependencies |
| Unicode Inspect | Locate selected Unicode control, format and separator characters | Python 3.9+, no dependencies |
| Unicode Normalize | Normalize UTF-8 text as NFC, NFD, NFKC, or NFKD, or check whether changes are needed | Python 3.9+, no dependencies |
| JWT Inspect | Decode compact token JSON without verifying its signature | Python 3.9+, no dependencies |
| UUID Inspect | Normalize UUID text and report its encoded version, variant, and forms | Python 3.9+, no dependencies |
| SemVer Compare | Compare Semantic Versions with prerelease precedence and ignored build metadata | Python 3.9+, no dependencies |
| PEM Inspect | Inventory strict base64 PEM blocks by label, size, digest, and duplicate payload | Python 3.9+, no dependencies |
| Unix Mode | Convert Unix permission bits between octal and symbolic forms | Python 3.9+, no dependencies |
Clone the repository:
git clone https://github.com/HugoIrfenz/DailyTools.git
cd DailyToolsPick a tool from the catalog and follow its README. There is no global installation step: each utility documents its own runtime, dependencies, commands, examples, and limitations.
DailyTools/
├── README.md
├── assets/
│ └── dailytools-thumbnail.jpg
└── tools/
├── json-redact/
│ ├── README.md
│ ├── json_redact.py
│ └── test_json_redact.py
├── csv-join/
│ ├── README.md
│ ├── csv_join.py
│ └── test_csv_join.py
├── markdown-link-check/
│ ├── README.md
│ ├── markdown_link_check.py
│ └── test_markdown_link_check.py
├── tar-inventory/
│ ├── README.md
│ ├── tar_inventory.py
│ └── test_tar_inventory.py
├── hex-view/
│ ├── README.md
│ ├── hex_view.py
│ └── test_hex_view.py
├── unicode-normalize/
│ ├── README.md
│ ├── unicode_normalize.py
│ └── test_unicode_normalize.py
├── line-sample/
│ ├── README.md
│ ├── line_sample.py
│ └── test_line_sample.py
├── gzip-check/
│ ├── README.md
│ ├── gzip_check.py
│ └── test_gzip_check.py
├── json-stats/
│ ├── README.md
│ ├── json_stats.py
│ └── test_json_stats.py
├── unix-mode/
│ ├── README.md
│ ├── unix_mode.py
│ └── test_unix_mode.py
├── csv-to-jsonl/
│ ├── README.md
│ ├── csv_to_jsonl.py
│ └── test_csv_to_jsonl.py
├── json-flatten/
│ ├── README.md
│ ├── json_flatten.py
│ └── test_json_flatten.py
├── pem-inspect/
│ ├── README.md
│ ├── pem_inspect.py
│ └── test_pem_inspect.py
├── semver-compare/
│ ├── README.md
│ ├── semver_compare.py
│ └── test_semver_compare.py
├── json-merge-patch/
│ ├── README.md
│ ├── json_merge_patch.py
│ └── test_json_merge_patch.py
├── uuid-inspect/
│ ├── README.md
│ ├── uuid_inspect.py
│ └── test_uuid_inspect.py
├── csv-select/
│ ├── README.md
│ ├── csv_select.py
│ └── test_csv_select.py
├── jwt-inspect/
│ ├── README.md
│ ├── jwt_inspect.py
│ └── test_jwt_inspect.py
├── unicode-inspect/
│ ├── README.md
│ ├── unicode_inspect.py
│ └── test_unicode_inspect.py
├── list-compare/
│ ├── README.md
│ ├── list_compare.py
│ └── test_list_compare.py
├── byte-size/
│ ├── README.md
│ ├── byte_size.py
│ └── test_byte_size.py
├── text-transcode/
│ ├── README.md
│ ├── text_transcode.py
│ └── test_text_transcode.py
├── retry-command/
│ ├── README.md
│ ├── retry_command.py
│ └── test_retry_command.py
├── zip-inventory/
│ ├── README.md
│ ├── zip_inventory.py
│ └── test_zip_inventory.py
├── base64-codec/
│ ├── README.md
│ ├── base64_codec.py
│ └── test_base64_codec.py
├── duration-sum/
│ ├── README.md
│ ├── duration_sum.py
│ └── test_duration_sum.py
├── file-compare/
│ ├── README.md
│ ├── file_compare.py
│ └── test_file_compare.py
├── tree-usage/
│ ├── README.md
│ └── ...source files
├── json-select/
│ ├── README.md
│ └── ...source files
├── path-collisions/
│ ├── README.md
│ └── ...source files
├── epoch-convert/
│ ├── README.md
│ └── ...source files
├── eol-inspect/
│ ├── README.md
│ └── ...source files
├── query-decode/
│ ├── README.md
│ └── ...source files
├── cron-next/
│ ├── README.md
│ └── ...source files
├── csv-audit/
│ ├── README.md
│ └── ...source files
├── duplicate-finder/
│ ├── README.md
│ └── ...source files
├── env-audit/
│ ├── README.md
│ └── ...source files
├── hash-manifest/
│ ├── README.md
│ └── ...source files
├── json-diff/
│ ├── README.md
│ └── ...source files
├── jsonl-check/
│ ├── README.md
│ └── ...source files
├── line-unique/
│ ├── README.md
│ └── ...source files
├── port-wait/
│ ├── README.md
│ └── ...source files
└── subnet-inspect/
├── README.md
└── ...source files
New utilities are selected and built through a daily automation scheduled for 12:00 WIB (Asia/Jakarta). Each run is tasked with inspecting the existing collection, choosing a useful idea, checking its behavior, and publishing the code together with documentation. Failed runs are reported rather than treated as successful releases.
- Useful: solve a concrete problem; no empty activity commits.
- Simple: keep setup understandable and dependencies minimal.
- Verified: check normal usage and relevant edge cases before release.
- Documented: include copyable commands, examples, and honest limitations.
- Local when practical: explain any network access or external service requirements.
- Careful with files: document side effects and preserve unrelated work.
Open an issue with the problem you want to solve, an example input, and the desired output. Improvements to existing tools are welcome through pull requests.
The AI-generated cover features a realistic cat and fish playing mahjong. Created for this repository; the artwork is stored in assets/dailytools-thumbnail.jpg.
Built by Hugo Syarof, with Angela helping turn little ideas into working tools.