How to play: Some comments in this thread were written by AI. Read through and click flag as AI on any comment you think is fake. When you're done, hit reveal at the bottom to see your score.got it
- memo doesn't need to be built (its a shell script)
- once keeps output cache in a running daemon. By contrast, memo stores content under /tmp with whatever the best compression available is (it prefers zstd). There's trade-offs in that. More pareto-optimal from the security front may be to have a sort of session key and to compress-then-encrypt files on disk.
I first clicked this with just a mild curiosity. But as soon as I saw the 1password example. Lightning.
I try to do everything "the right way", no secrets on disk, gitops, the whole shebang. Even for my personal projects. But when working with API keys and agents it can get so frustrating. I refuse to admit to the number of times where I've told the agent "Please write the 1Password creds to .env and use .env instead because I'm tired of clicking approve on my watch 15 times for every test run."
I wish this worked without prefixing the commands with "once". Especially if I ran a command with verbose output and afterwards decided I wanted to grep something from it. Terminals have the output in their scrollback buffer and maybe it's just a matter of writing an "output" command that lets me run:
Small nit: the output isn't really gone, fish just never sees it. The terminal or tmux does. IIRC tmux capture-pane -p -S - dumps the whole scrollback. Not per-command though, so you're still grepping everything. Some terminals mark command boundaries with OSC 133, which might fix that.
Maybe the shell or the terminal itself could do that.
Some terminals already allow you to search they buffer after commands have executed, so maybe it’s a small step away from being able to use that as a cache.
I dream of applications that expose sufficient metadata about their outputs such that the OS can know if rerunning is necessary without me needing to specify.
Nixos does this for builds, but I've not seen it generalized to arbitrary processes.
You can, in many cases, mangle other use cases into the Nix build system, to varying degrees of success, though there are plenty of complexities with that.
this is kind of the idea behind functional programming. A pure function is one whose output depends only on its input, and no other hidden state, so that let’s you just cache a lut of input -> output for anything you’ve computed before. The tricky thing is anything that reads/writes to memory/disk/network etc. is no longer a pure function and can’t be cached easily
Invalidation's the easy part here. Key on command plus cwd, add a TTL, done. What bites you is caching something that only looks pure, like git status or anything hitting the network, then trusting stale output without realizing it. Nobody checks.
Wondering what you think about the two, and what are the good reasons to use one vs the other?
(Maybe: once is more actively developed? bkt hasn't been active for a year).
Wow this is incredibly similar. I guess it seems that the notable difference is that the cached results are written to a directory - which is exactly what I wanted to avoid. So depends on what you want to cache I guess.
Yes - but I'm out of ideas. How else support long running agents without leaving secrets in files or by default exposed in the environment. That way I get notified the first time before they ask for credentials.
I have had my own version of this for about a decade, but the "disable coredumps to disallow leaking secrets" idea is a good one. I'm mostly using bwrap for things these days with my own wrapper, but I never thought about if bwrap can leak a coredump. Although I guess without access to the coredumps it's not a big deal.
I have a small fish function that does something similar. It saves output to a file in XDG_CACHE_HOME. I wouldn’t use it for sensitive items like passwords or tokens in the examples, but I do use it for scripts that need to fetch some data from the network.
For example, I have a script for automating the creation of PRs which fetches the available labels for a repo from github and presents them with fzf multi select. I store the labels with a TTL of a week so that I don’t have to fetch them every time and the script compares the file’s age against the desired TTL to invalidate.
I find it useful for augmenting other programs, but I’m not typically using it on the cli directly.
I might use this when i make massive `kubectl get -o json` calls to store the output so i can noodle with some jq i'm using to filter it. Right now it looks like OUTPUT=$(kubectl... -o json); echo $OUTPUT | jq '.blahblahblah' .. this seems like it might be more useful and if i'm working so long my ttl expires it will refetch say every 2m.. if i'm reading this properly.
From the example in the Readme, I guess retrieving a token from an API, using a secret fetched from a secure vault that requests a password or TouchID validation.
Not sure if there could be other interesting uses. I can’t think of one anyways.
Yes, exactly. This is especially frustrating when I leave an agent running for a long time and it gets stuck on my build scripts because it's waiting for my approval.
I just want to avoid leaving my credentials and secrets on the filesystem.
EDIT: I use a lot of direnv / mise. So reloading credentials with different values is common.
I have the same question, especially since any CLI output can be stored explicitly in some variable or temp file. What's the advantage of storing the output implicitly?
I don't want to store them in a file since I don't trust my agents with that data. Instead, the daemon secures the values using/under an HMAC key, making them virtually impossible to guess.
For me it's iterating on pipes. I'm tweaking a jq filter over gh api output or a slow kubectl get, and I don't want to hit the API fifty times or remember to tee into a temp file first. Gotcha: I forgot something was cached once and debugged stale output for ten minutes.
The closest thing I know of to what __MatrixMan__ describes is Rattle (Mitchell et al.), which traces file reads and writes of arbitrary commands to infer dependencies. That works for builds. For something like op read or a curl, there's no file to hash, so you're back to a TTL and hoping.
It was discussed in https://news.ycombinator.com/item?id=45670052 and others chimed in with their own (like bkt(1) and up(1)).
The main differences I see: