{"id":17748099,"url":"https://github.com/purarue/ttt","last_synced_at":"2025-03-18T16:30:24.599Z","repository":{"id":94610644,"uuid":"293643289","full_name":"purarue/ttt","owner":"purarue","description":"Logs metadata for shell scripts/invocations; an extension to my shell history","archived":false,"fork":false,"pushed_at":"2024-10-25T18:03:52.000Z","size":44,"stargazers_count":8,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-02-28T10:44:37.346Z","etag":null,"topics":["history","metadata","shell","shell-history"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/purarue.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2020-09-07T22:16:43.000Z","updated_at":"2024-10-25T18:03:56.000Z","dependencies_parsed_at":"2024-06-21T14:24:13.830Z","dependency_job_id":"b52e630b-d96f-4968-acb6-3855ea682235","html_url":"https://github.com/purarue/ttt","commit_stats":null,"previous_names":["seanbreckenridge/ttt"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/purarue%2Fttt","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/purarue%2Fttt/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/purarue%2Fttt/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/purarue%2Fttt/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/purarue","download_url":"https://codeload.github.com/purarue/ttt/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":243940058,"owners_count":20372044,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["history","metadata","shell","shell-history"],"created_at":"2024-10-26T10:01:16.061Z","updated_at":"2025-03-18T16:30:24.594Z","avatar_url":"https://github.com/purarue.png","language":"Go","funding_links":[],"categories":["Go"],"sub_categories":[],"readme":"# ttt\n\nLogs metadata for shell scripts/invocations; an extension to my shell history.\n\nThis is essentially a wrapper script to store metadata. The wrapper script `ttt` takes any other command as input, stores some metadata about it in a history file, and then runs the command as normal. Its quite literally:\n\n```bash\n#!/bin/sh\ntttlog \"$@\"\nexec \"$@\"\n```\n\n## But Why?\n\nShell history is nice, but not all commands are run directly through the shell - so its not possible to track them. If you have some keybinding to launch a script/application, or force-quit the terminal without exiting, your commands don't get saved in your shell history.\n\nThis also provides me with context; like what directory was this command run in?\n\nWhen I started using [`z`](https://github.com/rupa/z), also made it incredibly easy to [create an initial database with years of history](https://github.com/purarue/HPI-personal/blob/master/scripts/z-init-database)\n\nThis gives me finer control on what gets logged, so I can do analysis on it later from [`HPI`](https://github.com/purarue/HPI#readme).\n\n## How?\n\nThis consists of:\n\n- `ttt` (the wrapper shell script)\n- `tttlog` (log metadata to the history file)\n\nAt the top of any shell script which I want to log, I add something like:\n\n```\ncommand -v tttlog \u003e/dev/null 2\u003e\u00261 \u0026\u0026 tttlog \"$(basename \"$0\")\" \"$@\"\n```\n\n(... that way it doesn't error if `tttlog` isn't installed)\n\nIf I'm launching the command with a keybinding or from another program that accepts a command as input (e.g. [`rifle`](https://github.com/ranger/ranger) (my file manager) or from my [`window manager`](https://i3wm.org/), I'd modify the line from:\n\n```\n# launch firefox\nbindsym $mod+f exec firefox-developer-edition\n```\n\n... to ...\n\n```\nbindsym $mod+f exec ttt firefox-developer-edition\n```\n\nThat _does_ mean that the command would fail if `ttt` isn't installed, but I'm willing to live with that.\n\nIf this can't find the current working directory (i.e. if you deleted the current directory and called it from there), it sets `-`, which signifies an error.\n\nI recommend you symlink `#!/bin/sh` to something faster than `bash`, like `dash`, to improve startup times. See [`here`](https://wiki.archlinux.org/index.php/Dash) for more info.\n\nAn example of what this logs to the CSV file:\n\n```csv\n1599523021,/home/username/Repos/ttt,nvim ./tttlog.go\n1599523446,/home/username,alacritty\n1599523626,/home/username,keepassxc\n```\n\nOne could also just use this to log generic events. `tttlog` just saves whatever arguments you pass it with some metadata about where/when, so could be used to track habits/my behaviour like:\n\n```bash\n#!/bin/sh\n\n# every minute, if I'm watching something, save what movie/music I'm listening to\n# using my https://github.com/purarue/mpv-sockets script\n\nwhile true; do\n  if MEDIA_PATH=\"$(mpv-currently-playing)\"; do\n    tttlog \"mpv_playing_media:$MEDIA_PATH\"\n  fi\n  sleep 60\ndone\n```\n\nFor examples of where this is used in my [dotfiles](https://github.com/purarue/dotfiles/), see [here](https://gist.github.com/purarue/996126c45a4b3ed10941c7f190ac0605).\n\n## Install\n\nRequires `go`\n\n```bash\ngit clone \"https://github.com/purarue/ttt\" \u0026\u0026 cd ./ttt\nmake\n```\n\nor with [`bpkg`](https://github.com/bpkg/bpkg): `bpkg install -g purarue/ttt`\n\nYou can change which file `tttlog` writes to by setting the `TTT_HISTFILE` environment variable. The default location is `${XDG_DATA_HOME:-$HOME/.local/share}/ttt_history.csv`\n\n### Tests\n\n```bash\ncd test\n./test\n```\n\n### Benchmarks\n\nJust to have some numbers here, the overhead that `ttt` (wrapper shell script running `tttlog`) causes is about `3ms`\n\n```\nBenchmark #1: /bin/sh\n  Time (mean ± σ):       0.6 ms ±   0.3 ms    [User: 0.5 ms, System: 0.4 ms]\n  Range (min … max):     0.0 ms …   1.5 ms    1621 runs\n\nBenchmark #2: printf hi \u003e/dev/null\n  Time (mean ± σ):       0.1 ms ±   0.1 ms    [User: 0.2 ms, System: 0.2 ms]\n  Range (min … max):     0.0 ms …   1.3 ms    1935 runs\n\nBenchmark #3: /home/username/Repos/ttt/test/../ttt printf hi \u003e/dev/null\n  Time (mean ± σ):       3.8 ms ±   0.7 ms    [User: 2.3 ms, System: 2.3 ms]\n  Range (min … max):     2.3 ms …   5.8 ms    522 runs\n```\n\n#### ttt?\n\nNaming things relating to shell history/logging is hard...\n\nI just wanted something that would be easy to type, so I can add it to wherever I want quickly. Is just the first thing that came to mind, when I was trying to figure out how to track rifle/i3 bindsyms; 'track the things'\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpurarue%2Fttt","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpurarue%2Fttt","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpurarue%2Fttt/lists"}