Trops¶
Trops is a command-line tool designed for tracking system operations on destributed Linux systems. It keeps a log of executed commands and modified files, being helpful for developing Ansible roles, Dockerfiles, and similar tasks. It is portable and easy to use, and it can be used in a variety of environments, such as local, remote, and containerized environments. You can store your log on a private, internal Git repository (not public) and link it to issues in tools such as GitLab and Redmine.
It aims for solving these challenges:
Keeping track of when and what has been done on which host (for which issue)
Note-taking for solo system administrators of destributed systems
“Potentially” bridging the gap between Dev and Ops
Prerequisites¶
OS: Linux, MacOS
Shell: Bash, Zsh
Python: 3.8 or higher
Git: 2.28 or higher
Installation¶
Ubuntu:
sudo apt install pipx git
pipx install trops
Rocky:
sudo dnf install epel-release git
sudo dnf install python3.12-pip
pip3.12 install --user pipx
pipx install trops
MacOS:
brew install pipx git
pipx install trops
Conda-forge:
wget https://github.com/conda-forge/miniforge/releases/latest/download/Miniforge3-Linux-x86_64.sh
bash Miniforge3-Linux-x86_64.sh -b -p $HOME/miniforge3
$HOME/miniforge3/bin/conda install git
$HOME/miniforge3/bin/pip install trops
mkdir $HOME/bin
cd $HOME/bin
ln -s ../miniforge3/bin/git git
ln -s ../miniforge3/bin/trops trops
export PATH=$HOME/bin:$PATH # Add this line in your .bashrc
Install as a Claude Code skill¶
If you use Claude Code, you can install a skill that walks Claude through installing, setting up, and using trops on your machine. Run:
mkdir -p ~/.claude/skills/trops && \
wget -O ~/.claude/skills/trops/SKILL.md \
https://raw.githubusercontent.com/kojiwell/trops/main/SKILL.md
After installing, ask Claude something like “install trops” or “set up a trops env for this project” and the skill will load automatically. Re-run the command above any time to pull the latest version of the skill.
Quickstart¶
Activate trops:
export TROPS_DIR="/path/to/your/trops"
test -d $TROPS_DIR || mkdir -p $TROPS_DIR
# for Bash
eval "$(trops init bash)"
# for Zsh
eval "$(trops init zsh)"
Create a trops environment(e.g. myenv):
trops env create myenv
Activate or deactivate background tracking:
# Activate
ontrops myenv
# Deactivate
offtrops
When activated, every command is logged in a log file located at $TROPS_DIR/log/trops.log, and any modified file is committed to its designated Git repository ($TROPS_DIR/repo/<env>.git). To see this in action, perform tasks such as installing or compiling an application, and then use the trops log command to review the log:
# Get your work done, and then check log
trops log
# You can also pass the output to Trops TLDR(tldr),
# which unclutters and shows log in a table
trops log | trops tldr
If you use tools such as GitLab and Redmine as an internal, remote, private repository for your Trops, you can set it by –git-remote option like this:
# At creation
trops env create --git-remote=git@gitlab.example.local:username/repository_name.git myenv
# or update
ontrops myenv
trops env update --git-remote=git@gitlab.example.local:username/repository_name.git
Trops now transforms your system operations into an issue-driven project. Create an issue on your private repository, for example, “Install foobar #1,” and then set the issue number as a tag in Trops like this:
# '#<issue number>'
ttags '#1'
# repo_name#<number>
ttags repo_name#1
Once your work is done, you can save and push the log:
# Save the log as a markdown table
trops log | trops tldr --save
# And then, push your trops' commits to the remote repository
trops repo push
On the issue page, you can find the log in a markdown table format, which is useful for reviewing and sharing your work with your team members.
Now, you can update the tasks and recipes in your Ansible roles, Dockerfiles, and so on, based on the log. You can also use the log as a reference for troubleshooting.
Trops helps you easily try new things, and you don’t have to worry about forgetting what you’ve done. And then, once you’ve got used to it, it will actually help you organize your day-to-day multitasking, which is probably something that a lot of system admins cannot avoid.
Reviewing and sharing logs¶
Once you have been using ontrops for a while, three subcommands turn the raw trops.log into shareable artifacts and a browsable history: trops tldr renders the log as a table, trops tablog collects and merges the saved tables, and trops view opens a tracked file or a folder of tables in a local web viewer.
trops tldr¶
trops tldr (Table Log Direct, “Too Long Don’t Read”) consumes the output of trops log on stdin and renders it as a table. By default the output is plaintext for terminal viewing; with -m or --html you get Markdown or HTML, and with -s the table is saved as Markdown into the env’s tablog_dir so that it can be committed and shared (for example, pasted into a GitLab or Redmine issue).
Pipe trops log into tldr, and optionally save:
trops log | trops tldr
trops log | trops tldr -s
Notable options:
-o, --only <fmt>–%-placeholder string controlling which columns appear. Supported codes:%DDate,%TTime,%uUser@host,%llLog level,%ltLog type,%cCommand,%dDirectory/Owner,Group,Mode,%xExit code,%iID,%eEnv,%tTags. Default:%D,%T,%u,%c,%d,%x.-s, --save– save the rendered table as Markdown under the env’stablog_dir(default$TROPS_DIR/tablogper env config). The filename is auto-generated from repo + env + tag.--name <name>– override the auto-generated filename when used with--save.-m, --markdown/--html– output format selectors (mutually exclusive); default is plaintext.-n, --no-declutter– disable noise filtering.-a, --all– include all log entries.
trops tablog¶
trops tablog works on the Markdown tables that trops tldr -s saves. The saved tables live as commits inside each env’s git repo (under tablog_dir); tablog get extracts them onto the filesystem so they can be browsed, merged, or served by trops view --web, and tablog join merges multiple of them into a single time-sorted table.
tablog get¶
Extract the saved tables from one or all envs into a target directory:
trops tablog get -a -u -f /path/to/extract
Notable options:
positional
path– destination directory; created if missing. Used as--prefixfor the underlyinggit checkout-index.-a, --all– process every env introps.cfg. Mutually exclusive with-e.-e, --env <name>– process a single env.-u, --update– runtrops fetchbefore extracting (refreshes from the configured remote).-f, --force– overwrite existing files in the target directory.
tablog join¶
Merge multiple Markdown tables into one time-sorted table:
trops tablog join -o merged.md file1.md file2.md
Notable options:
-o, --output <path>– required output file path.-a, --append– append to the output file instead of overwriting it.
trops view¶
trops view has two modes. In file mode it shows a tracked file’s content at a given commit (default HEAD); useful for inspecting historical state without leaving the shell. In web mode (--web) it serves a folder of .md tablog files in a browser, with each trops show <hex>:<path> entry hyperlinked: clicking <hex> opens a diff view, and clicking <path> opens the file’s content at that commit.
File mode:
trops view /etc/hosts
trops view --commit 1a2b3c /etc/hosts
Web mode (after extracting tablog files with trops tablog get):
trops view --web /path/to/extract
Notable options:
positional
file– absolute path to a tracked file (file mode), or a folder of.mdtablog files (with--web).-e, --env <name>– select the env.--commit <hash>– commit-ish to view; defaultHEAD.--web– start a local web viewer. The server binds tohttp://localhost:8001and the default browser opens automatically.-u, --update-tablog– before starting the web viewer, runtrops tablog get -a -u -f <folder>to refresh the tablog files into the served folder.--no-browser– do not auto-open a browser tab (useful for headless or remote sessions; you can still navigate tohttp://localhost:8001manually, e.g., via an SSH port-forward).
Contributing¶
If you have a problem, please create an issue or a pull request.
Fork it ( https://github.com/kojiwell/trops/fork )
Create your feature branch (
git checkout -b my-new-feature)Commit your changes (
git commit -am 'Add some feature')Push to the branch (
git push origin my-new-feature)Create a new Pull Request
Changelog¶
Unreleased¶
v0.3.0 - 2026-05-16¶
Breaking: rename
kmtotablogacross the codebase. The hardcoded/kmdefault directory under$TROPS_DIRbecomes/tablog; the per-envkm_dirconfig key introps.cfgbecomestablog_dir; thetrops view --update-kmCLI flag becomes--update-tablog; internal variables and help text follow suit. Encountering the legacykm_dirkey now raisesTropsErrorwith a pointer to this changelog entry – no silent fallback. (#161)Migration: for each env in
~/.trops/trops.cfgthat still haskm_dir = ..., rename the key totablog_dir. If your env’s git history contains files committed underkm/(fromtrops tldr -sruns prior to this release) and you wanttrops tablog getto keep finding them, settablog_dir = /kmfor that env. New envs gettablog_dir = /tabloggoing forward. The orphaned~/.trops/km/directory can be moved or deleted manually (e.g.,mv ~/.trops/km ~/.trops/tablog).
v0.2.36 - 2026-05-09¶
capcmd: differentiate
teeandtteein pipeline detection. Plaincmd | tee outnow commitsoutas a transparent passthrough – the file is no longer mutated.cmd | ttee out(using the trops-aliasedtteedefined introps init) commits the file and prepends# <left-command>as the first line, so that the originating command is recorded inside the artifact.-a/--appendskips the prepend so that growing log files are not silently rewritten. Backward-compat note: anyone whose current workflow relied onteeimplicitly prepending# <cmd>should switch tottee; existing files in the env git repo are unaffected. (#162)perf: cut
capture-cmdbaseline overhead by lazy-loading subcommand modules inexec.py(only the invoked subcommand is imported) and deferringsubprocess/reimports incapcmd.pyto the editor / tee / package paths that actually need them. Trivial-command import chain drops ~146ms → ~64ms cumulative; user CPU per prompt drops ~50ms → ~30ms (#166).capcmd: skip
tmp/mkdirwhen the directory already exists; fast-skip the tee-pipeline tokenizer when no|is in the command; remove the dead duplicated_sanitize_for_sudoblock.docs: add “Reviewing and sharing logs” section to README covering
trops tldr,trops tablog(get/join), andtrops view– including the%-placeholder map for--onlyand theview --webURL/clickable behavior (#165).chore(release): make
release.shportable across BSD and GNU sed, exit on missing/invalid argument, pre-flight check the working tree, and print the git tag/push steps so future releases get a matching annotated tag.
v0.2.35 - 2025-09-23¶
Packaging/docs: bump version to 0.2.35.
v0.2.34 - 2025-09-23¶
tldr: Fix save when git_remote is not configured.
v0.2.33 - 2025-08-18¶
Rename: km`→`tldr subcommand; getkm`→`tablog get; joinkm`→`tablog join.
CLI: Remove glab (GitLab) subcommand.
view –web: Use trops tablog get -a -u -f <path> for –update-km refresh.
v0.2.32 - 2025-08-17¶
tablog get: Add -f/–force to overwrite existing files and -u/–update to run trops fetch beforehand.
view –web: Add -u/–update-km to run trops tablog get -a -u -f <path> before starting the viewer.
tablog join: New subcommand to merge multiple KM markdown logs into a single time-sorted table; support append mode and header handling.
Errors: Replace many print + exit paths with structured TropsError exceptions; top-level CLI prints the error and exits with non-zero code.
Core: Rename classes Trops`→`TropsBase, TropsMain`→`TropsCLI (backward-compatible aliases maintained).
v0.2.31 - 2025-08-13¶
view –web: Use trops show <hash>[:<path>] for the web endpoint instead of raw git show, so it respects trops configuration.
tablog get: Create the destination directory automatically if it does not exist. Use –work-tree=<path> on checkout-index and strip a leading / from km_dir when building refs.
v0.2.30 - 2025-08-13¶
capcmd: defer “trops show <hash>:<path>” file logs until after the actual command log, preserving real-world order (e.g., “vi <path>” then “trops show <hash>:<path>”).
tests: add a test to assert the command log precedes the file log for editor commands.
note: logging deferral is in-memory only; existing log files are not read or rewritten.
v0.2.29 - 2025-08-11¶
capcmd performance: early fast-path ignore for commands like ttags (skip side-effects), avoid os.chdir by using git -C, and use a set for ignore_cmds membership checks.
log: default to printing all lines when no filters are specified; apply same logic in follow mode.
capcmd: clearer error when TROPS_ENV is set but missing in config; safer defaults for attributes.
utils: rename unclear that to sid_seed_text and add tests for SID format.
capcmd: rename _update_files to _track_editor_files for clarity and add test.
v0.2.28 - 2025-08-10¶
capture-cmd: Automatically add the original command (# <command>) to the first line of files added with | tee <file>.
view –web: Skip the front matter (YAML, — to —) and display only the main content.
view –web: Adjust to display hyperlinks with underlines only, without changing their color.
trops git: Normalize relative paths or CWD-based paths to work-tree relative paths and appropriately insert –.
trops ll: Normalize directory arguments to work-tree relative paths for display.
Common: Utility-ize path normalization logic to reduce duplication.
v0.2.27 - 2025-08-10¶
Add trops view command with: - Single file viewing from repo: trops view <file> [–commit <rev>] - Web viewer: trops view –web <folder> serving at http://localhost:8001 - Clickable “trops show <hash>[:<path>]” links in Markdown to open modal with git show outputs - Optional –no-browser to suppress auto opening browser - Markdown tables render with borders in web viewer - Improved modern styling and search filter - Diff syntax highlighting for git show output
Editor/tee capture-cmd improvements: - Detect files edited even when command is repeated - Auto-push only when files were added/updated - Handle chained pipelines and |tee variations
Git wrapper improvements: - Normalize absolute paths to work-tree relative pathspecs - Use -C <work_tree> and – separator for safety - -v/–verbose to print wrapped git/touch commands
Tags and log improvements: - Filter log by any tag element; –tags override at runtime - Primary tag extraction and normalization