[
  {
    "description": "The cheat sheet of Jujutsu.",
    "languages": [
      "JavaScript",
      "CSS"
    ],
    "last_updated": "2026-08-11T19:43:47Z",
    "license": [
      {
        "name": "MIT License",
        "spdx": "mit",
        "url": "http://choosealicense.com/licenses/mit/"
      }
    ],
    "links": [
      {
        "label": "logo",
        "url": "https://tamada.github.io/api/assets/jj-cheat-sheet.svg"
      },
      {
        "label": "sbom",
        "url": "https://api.github.com/repos/tamada/jj-cheat-sheet/dependency-graph/sbom"
      },
      {
        "label": "repository",
        "url": "https://github.com/tamada/jj-cheat-sheet"
      },
      {
        "label": "www",
        "url": "https://tamada.github.io/jj-cheat-sheet"
      }
    ],
    "name": "jj-cheat-sheet",
    "owner": "tamada",
    "releases": [],
    "topics": [
      "cheatsheet",
      "jujutsu"
    ]
  },
  {
    "description": "My home-brew recipes.",
    "languages": [
      "Ruby",
      "Rust"
    ],
    "last_updated": "2026-08-22T06:18:51Z",
    "license": [
      {
        "name": "Creative Commons Zero v1.0 Universal",
        "spdx": "cc0-1.0",
        "url": "http://choosealicense.com/licenses/cc0-1.0/"
      }
    ],
    "links": [
      {
        "label": "repository",
        "url": "https://github.com/tamada/homebrew-tap"
      },
      {
        "label": "logo",
        "url": "https://tamada.github.io/api/assets/homebrew-tap.png"
      }
    ],
    "name": "homebrew-tap",
    "owner": "tamada",
    "releases": [],
    "topics": []
  },
  {
    "description": "Pseudo-REST static API generator",
    "languages": [
      "Dockerfile",
      "Just",
      "Elvish",
      "Shell",
      "PowerShell"
    ],
    "last_updated": "2026-08-05T06:21:23Z",
    "license": [
      {
        "name": "MIT License",
        "spdx": "mit",
        "url": "http://choosealicense.com/licenses/mit/"
      }
    ],
    "links": [
      {
        "label": "logo",
        "url": "https://tamada.github.io/api/assets/fauxrest.svg"
      },
      {
        "label": "docs",
        "url": "https://docs.rs/fauxrest/latest"
      },
      {
        "label": "registry",
        "url": "https://crates.io/crates/fauxrest"
      },
      {
        "label": "container",
        "url": "https://quay.io/repository/tama5/fauxrest"
      },
      {
        "label": "sbom",
        "url": "https://api.github.com/repos/tamada/fauxrest/dependency-graph/sbom"
      },
      {
        "label": "repository",
        "url": "https://github.com/tamada/fauxrest"
      },
      {
        "label": "www",
        "url": "https://tamada.github.io/fauxrest"
      }
    ],
    "name": "fauxrest",
    "owner": "tamada",
    "releases": [
      {
        "description": "## What's Changed\n* test: cover numeric derive type preservation by @atharvafulay in https://github.com/tamada/fauxrest/pull/14\n* fix: reject $filter comparisons whose operand kinds cannot be evaluated by @tamada in https://github.com/tamada/fauxrest/pull/24\n* feat: derive template values from filtered data, and add $derive.exclude by @tamada in https://github.com/tamada/fauxrest/pull/25\n* fix: publish output only after the whole build succeeds by @tamada in https://github.com/tamada/fauxrest/pull/26\n* docs: correct the serializer configuration example by @tamada in https://github.com/tamada/fauxrest/pull/30\n* chore: drop the directives $emit replaced by @tamada in https://github.com/tamada/fauxrest/pull/31\n* fix: reject a $-prefixed key that is not a directive by @tamada in https://github.com/tamada/fauxrest/pull/35\n* feat: land $skip and the unknown-directive check on main by @tamada in https://github.com/tamada/fauxrest/pull/36\n* feat: write the whole API as one file with bundle by @tamada in https://github.com/tamada/fauxrest/pull/37\n* fix: send --help and --version to stdout with status 0 by @tamada in https://github.com/tamada/fauxrest/pull/39\n* Release v0.0.5 by @tamada in https://github.com/tamada/fauxrest/pull/40\n\n## New Contributors\n* @atharvafulay made their first contribution in https://github.com/tamada/fauxrest/pull/14\n\n**Full Changelog**: https://github.com/tamada/fauxrest/compare/v0.0.4...v0.0.5",
        "name": "Release v0.0.5",
        "release_date": "2026-08-05T06:24:37Z"
      }
    ],
    "topics": [
      "rest-api",
      "static-api",
      "static-api-generator"
    ]
  },
  {
    "description": "Simple options picker in CLI.",
    "languages": [
      "Rust"
    ],
    "last_updated": "2026-02-09T03:20:15Z",
    "license": [
      {
        "name": "MIT License",
        "spdx": "mit",
        "url": "http://choosealicense.com/licenses/mit/"
      }
    ],
    "links": [
      {
        "label": "docs",
        "url": "https://docs.rs/pick-a-boo/latest"
      },
      {
        "label": "registry",
        "url": "https://crates.io/crates/pick-a-boo"
      },
      {
        "label": "logo",
        "url": "https://tamada.github.io/api/assets/pick-a-boo.png"
      },
      {
        "label": "sbom",
        "url": "https://api.github.com/repos/tamada/pick-a-boo/dependency-graph/sbom"
      },
      {
        "label": "repository",
        "url": "https://github.com/tamada/pick-a-boo"
      }
    ],
    "name": "pick-a-boo",
    "owner": "tamada",
    "releases": [
      {
        "description": "- Add short labels to items (#9 , #10 ).\r\n- As a result, the macro became bloated, so it was separated into a different crate ([pick-a-boo-macros](https://crates.io/crates/pick-a-boo-macros)).\r\n  - This macro's crate is publicly available.\r\n- Subsequently, the version number increased due to changes like GitHub Actions scripts for automated releases, but the core functionality remains unchanged.\r\n\r\nThe binaries of `pick-a-boo` are not available on GitHub. \r\nPlease use `pick-a-boo` with `cargo`.",
        "name": "v0.1.6",
        "release_date": "2026-02-09T03:30:17Z"
      }
    ],
    "topics": [
      "library",
      "select-options",
      "terminal",
      "yes-or-no"
    ]
  },
  {
    "description": "The software birthmark toolkit for real-world executables",
    "languages": [
      "Rust",
      "Shell",
      "Java",
      "Python",
      "Just"
    ],
    "last_updated": "2026-09-02T08:54:36Z",
    "license": [
      {
        "name": "MIT License",
        "spdx": "mit",
        "url": "http://choosealicense.com/licenses/mit/"
      }
    ],
    "links": [
      {
        "label": "logo",
        "url": "https://tamada.github.io/api/assets/oinkie.png"
      },
      {
        "label": "container",
        "url": "https://quay.io/repository/tama5/oinkie"
      },
      {
        "label": "sbom",
        "url": "https://api.github.com/repos/tamada/oinkie/dependency-graph/sbom"
      },
      {
        "label": "repository",
        "url": "https://github.com/tamada/oinkie"
      },
      {
        "label": "www",
        "url": "https://tamada.github.io/oinkie/"
      }
    ],
    "name": "oinkie",
    "owner": "tamada",
    "releases": [
      {
        "description": "## Upgrading from v0.3.0\n\nTwo changes in this release alter files that oinkie generates. Neither affects\nsimilarity scores, but both matter if you keep a working directory between runs.\n\n**The `-B/--binary-type` flag is gone.** `oinkie extract` accepted it but never\nread it, so passing `-B llvm` silently did Ghidra parsing anyway. Scripts that\npass the flag will now fail with an unknown-argument error; remove it. Backend\nselection lives on `oinkie lift --lifter-type`, which is the option that has\nalways actually chosen a backend.\n\n**Birthmark file names have changed again.** `oinkie extract` derives the output\nname as `{file_stem}_{hash}.json`, and the hash prefix widened from 8 to 16 hex\ncharacters (#30) so that the disambiguator carries 64 bits instead of 32. At 32\nbits a collision became likely at roughly 77,000 files, and a collision was\nsilent — one binary's birthmark simply overwrote another's.\n\nNames from v0.3.0 therefore do not match those from v0.4.0. On the first run\nwith `--skip`, every input is re-extracted. That is expected, not an error.\nOlder files remain valid inputs to `compare` and `reaggregate`; the only cost of\nkeeping them is that the same binary ends up present under two names.\n\n**Similarity CSVs record the pair in the correct order.** The `left` record used\nto hold the *second* birthmark and `right` the first (#29), so a `--skip` rerun\nread the pair back in the opposite order from a fresh run. The score was never\naffected — the metrics are symmetric — but `results.csv` could not be relied on\nto say which file was on which side.\n\nOnly the writer changed. Similarity CSVs written by v0.3.0 or earlier still\ncarry the old ordering and will keep being read reversed, and mixing old and new\nfiles in one directory means the interpretation varies per file. Regenerate the\ndirectory to get consistent results.\n\n**Shell completions moved.** They are now generated under `assets/completions`,\none directory per shell, with conventional file names (`oinkie`, `oinkie.elv`,\n`oinkie.fish`, `oinkie.ps1`, `_oinkie`). Packaging scripts that referenced the\nold `completions` directory need updating.\n\n**`fc-*` analyses produced a false positive.** The symbol lookup compared the\ncall operand `\"(ram, 0x100000480, 8)\"` against a symbol table keyed\n`\"0x100000480\"`, so every call was discarded and every `fc-*` birthmark came out\nempty (#40). Two empty sets are identical, so any two programs compared as a\nperfect match through `fc-freq-cosine`, `fc-set-dice`, `fc-freq-euclidean`,\n`fc-set-jaccard`, `fc-seq-levenshtein`, `fc-seq-lcs`, `fc-set-simpson` and\n`fc-freq-weightedjaccard`.\n\nAny conclusion drawn from an `fc-*` comparison on v0.3.0 or earlier should be\ntreated as unreliable and the comparison re-run. Birthmark files extracted with\n`fc-*` are empty and carry no information; regenerate them.\n\n**Extracting an `fc-*` birthmark from a program that calls nothing is now an\nerror** (#44). It used to succeed and write an empty birthmark, which is the\nshape of the bug above: empty birthmarks compare as a perfect match, so the\noutput was worse than no output. `oinkie extract -b fc-set` on such a program\nnow stops with\n\n```\nbin/sample: no operation is a call, so every fc-* birthmark of it would be\nempty -- and two empty birthmarks score as a perfect match. Either the program\nreally calls nothing, or oinkie's reader for ghidra-pcode does not recognise\nthat representation's call operations\n```\n\nThe `op-*` families are unaffected, and so is any program that makes at least\none call — which, for a lifted binary, means every realistic input.\n\n**k-grams are named the same way everywhere, and it is the library's way**\n(#25). The command line had invented two spellings of its own, neither of them\nthe one the documentation and the file format use:\n\n| | v0.3.0 | v0.4.0 |\n| --- | --- | --- |\n| `extract -b` | `op-tri-gram-set` | `op-3gram-set` |\n| `run -a` | `op3gram-set-dice` | `op-3gram-set-dice` |\n\nBoth came from hand-written `ValueEnum`s whose command-line names were derived\nfrom Rust identifiers, so `OpTriGramSet` became `op-tri-gram-set` and\n`Op3gramSetDice` became `op3gram-set-dice`. The library has always parsed\n`op-3gram-set`, and `oinkie info` has always *printed* `op-3gram-set` — which\n`-b` then refused. Scripts passing a k-gram to `-b` or `-a` need updating;\n`fc-*`, `op-seq`, `op-set`, `op-freq` and their analyses are unchanged.\n\nTwo things follow from deleting the hand-written lists. **Any k now works**:\n`--analysis op-12gram-set-jaccard` and `-b op-12gram-set` run, where `-a`\nstopped at k=6. And **`-b` and `-a` now agree on what exists** — `-b` reached\nk=8 while `-a` reached k=6, so three k-gram families could be extracted but not\nanalysed in one step.\n\n`oinkie info` and shell completion list up to k=8. That bound is only what gets\n*suggested*; it is not what parses.\n\n**A half-written similarity file is no longer read as a score of zero.**\n`compare --skip` and `run --skip` reuse the CSVs an earlier run left behind. A\nfile holding the pair but no `result,` line — what an interrupted run leaves —\nwas accepted, and the missing score defaulted to **0.0**: two programs reported\nas having nothing in common, written into `results.csv` beside real scores,\nwith the run exiting successfully.\n\nSuch a file is now refused, naming it:\n\n```\nError: Parse error: Result line not found in similarities/00000.csv\n```\n\nA `--skip` run over a directory containing one used to succeed and will now\nstop. Delete the offending file, or drop `--skip` to recompute. Any\n`results.csv` produced by a `--skip` run over an interrupted directory should\nbe treated as unreliable in the same way as the `fc-*` scores above: a zero\nthere is indistinguishable from a real one.\n\n`reaggregate` is unaffected. It recomputes the score from the stored matrix\nrather than reading it, and a truncated file has no matrix either — which it\nalready refuses.\n\n**A usage error is no longer announced twice.** clap's own message begins\n`error: `, and oinkie printed it behind `Error: `, so a mistyped flag came back\nas `Error: error: unexpected argument ...` (#62). The prefix is gone from that\npath. oinkie's own errors carry no prefix of their own and keep theirs:\n\n```\n$ oinkie run --bogus-flag\nerror: unexpected argument '--bogus-flag' found\n\n$ oinkie extract no-such-file.json\nError: IO error for no-such-file.json: No such file or directory (os error 2)\n```\n\nScripts matching on the old `Error: error:` text need updating. The exit codes\nare unchanged: 1 for a usage error, 2 for anything else.\n\n**`op-*gram-freq` birthmarks can be extracted at all.** Every non-empty one\nfailed at write time with\n\n```\nError: hello_clang_3380b9841726541e.json: JSON error: key must be a string\n```\n\nA k-gram is a list of operations and a JSON object's keys are strings, so\n`serde_json` refused the map outright (#59). `op-1gram-freq` through\n`op-8gram-freq` — **eight of the thirty birthmark types** the CLI advertises,\nand one of the three shapes a k-gram comes in — could not produce a file, and\nwith them **twenty-four of its eighty analyses** could not be reached through\n`extract` + `compare`.\n\nIt looked as though only small k were affected. It was not: a program with\nfewer than k operations yields an empty map, and an empty map has no key to\nrefuse. Any k fails on any program long enough to produce a k-gram.\n\nThe frequency map is now written as a list of `[kgram, count]` pairs, sorted,\nso extracting the same program twice writes the same bytes:\n\n```json\n{\"KgramFreq\": [[[\"CALL\", \"COPY\"], 1], [[\"COPY\", \"COPY\"], 1]]}\n```\n\n**Birthmark files are written in a canonical order.** A map and a set have no\norder of their own, and oinkie wrote them in hash order — which comes from the\ninsertion history and the hasher rather than from what the birthmark holds\n(#68). Two equal birthmarks could be written differently, and a `rustc-hash`\nbump would relay every file for no reason.\n\n`Freq`, `Set` and `KgramSet` are sorted on the way out now, joining `KgramFreq`.\n`Seq` and `KgramSeq` are untouched and must be: their order is the program's,\nand sorting them would not canonicalise the file but destroy the birthmark.\n\nNothing about any file's meaning changes, every existing file still reads, and\nscores are unaffected — checked against a build of the previous commit across\nnine families. What changes is the byte layout of newly written files, so a\nchecksum taken over a birthmark from an earlier version will not match one\ntaken now, and a `--skip` rerun still skips because it goes by the file\nexisting rather than by its contents.\n\n**A frequency stated more than once is refused, in both shapes.** `op-freq`\nand `fc-freq` used serde's derived map deserializer, which inserts in a loop,\nso a birthmark saying `{\"COPY\": 3, \"COPY\": 5}` loaded as 5 and was scored with\nnothing said (#66). It is refused now, naming the operation:\n\n```\nCOPY: listed more than once; a birthmark names each operation once\n```\n\nEvery repeat is refused, including `{\"COPY\": 3, \"COPY\": 3}`, whose counts\nagree: a repeated key is a malformed object however the values fall, and\nreading it would mean accepting a broken file whenever it was broken\nconsistently.\n\nOnly the frequency shapes changed. A `Set` repeating an element denotes the\nsame set and a `Seq` repeating one is a sequence doing its job — neither can\nmean two things, and both still load. Nothing oinkie writes can produce a\nrepeat in any of them, since every map and set is serialized from a map or a\nset, so no file it wrote is affected.\n\nA k-gram listed more than once is refused rather than resolved. The list stands for a\nmap, so collecting it would let the last pair win: a file saying a k-gram\noccurred 3 times and again 5 times would load as 5 and be scored, with nothing\nsaid. Nothing oinkie writes can produce one, since the pairs come from a map.\n\nNo existing file changes. `op-*gram-seq` and `op-*gram-set` already wrote a\nk-gram as a plain list and still do — which is why the map was changed rather\nthan the k-gram, since making `Kgram` itself serialize as a string would have\nrewritten the two families that work. `run -a op-Kgram-freq-*` was never\naffected: it compares in memory and never writes a birthmark, which is why the\nwhole thing went unnoticed.\n\n**`compare` stopped making one syscall per byte.** `Birthmark::try_from` and\n`Program::try_from` handed `serde_json::from_reader` a bare `std::fs::File`.\nserde_json's `IoRead` takes one byte at a time, so an unbuffered file meant one\n`read` syscall per byte of JSON (#51). Loading a 9 MB birthmark took **2.7 s**;\nit now takes 15 ms.\n\n`compare` loads its inputs once per *pair*, so the loader runs O(n²) times.\nOver three pairs of 9 MB birthmarks the whole command went from **22.0 s to\n7.8 s**, and the kernel time in it from **37.5 s to 0.08 s** — the parsing was\nnever the cost. Output is byte-identical.\n\nNothing to change on your side, and **`compare` is the only subcommand\naffected**. `extract` and `run` read their programs through `AnyProgram::load`,\nwhich has read whole files since #45, and neither of them loads a birthmark\nfrom disk. The other half of the fix is for library callers: `Program::try_from`\nand `Birthmark::try_from` were both slow, and both are public.\n\n**An analysis name built from what `oinkie info` prints now parses.** `info`\nlists the algorithms as `weighted-jaccard`, but `run --analysis` only accepted\n`op-freq-weightedjaccard` — a name assembled from what the tool itself showed\nyou was refused (#71). Both spellings work now, and so does\n`compare --algorithm weighted-jaccard`, which was always the only one it took.\n\nThe other seven algorithms are single words and were already spelled the same\nin both places.\n\nThe two halves of an analysis name are no longer split on the last hyphen.\nEach hyphen is tried, rightmost first, and the split whose tail names an\nalgorithm and whose head is a birthmark type wins — so an algorithm added\nlater may be two words without breaking anything. Every name that parsed\nbefore still parses, and a name whose birthmark half is wrong still reports\nthat half:\n\n```\nop-nonsense-jaccard  ->  op-nonsense: unknown birthmark type\n```\n\n## Library API\n\nThese affect code using oinkie as a crate. The command-line interface is\nunchanged by them.\n\n**`AnalysisType::new` now returns `Result`.** It validates that the algorithm\noperates on the birthmark's shape, which `try_from` already did and `new` did\nnot — so the check could be walked around by constructing the pair directly.\nCallers add a `?` or handle `Error::IncompatibleAnalysis`, a new variant.\n\n**Analysis names that pair an algorithm with the wrong shape are rejected.**\nEach algorithm computes over one representation and converts anything else\nfirst, so `op-seq-euclidean` returned exactly what `op-freq-euclidean` returns\nwhile its name promised a comparison over sequences, and `op-set-levenshtein`\nscored 0.0 because no conversion exists. The error names the pairing that was\nmeant:\n\n```\nop-seq-euclidean: euclidean operates on frequency vectors; use op-freq-euclidean\n```\n\nIn practice this only changes k-gram names: `op-3gram-set-levenshtein` and its\nkind used to parse and now do not. Every pairing the CLI offers is canonical, so\nnothing reachable through `--analysis` is affected.\n\n**More names parse than before.** `AnalysisType::try_from` reads the algorithm\nand hands the rest to `BirthmarkType::try_from` (#38), so the eight `fc-*`\ncombinations and the seven `*-lcs` ones now work, as does any `k` — previously\nfifteen of the sixty-four combinations the CLI offers could not be parsed at all.\n\n**`Program::new` takes the representation.** A lifted program now records\nwhich intermediate representation its operations are written in, and the\nconstructor requires it rather than assuming one. Code building a `Program`\ndirectly needs the extra argument; reading one from JSON does not, since the\nfield is defaulted for files written before it existed.\n\nThe argument is required rather than defaulted on purpose. A constructor that\nfilled it in would let a program lifted by one tool be labelled as another's,\nwhich is the confusion the field exists to prevent.\n\n**Birthmarks record the representation they were extracted from, and a\ncomparison across two of them is refused.** A birthmark is only meaningful\nagainst another built the same way, and two lifters describe the same\ninstruction with different operations, so comparing across them would measure\nthe disagreement between the tools rather than anything about the programs\n(#42, #43). Only Ghidra exists today, so nothing currently reachable is\nrefused.\n\n`Metadata` gains an `ir` field, and the `birthmark` record in a similarity CSV\ngains a seventh column for it. The column is appended rather than inserted, so\nthe positions earlier readers depend on are unchanged, and a six-column record\nwritten by an earlier version still parses.\n\n**`Op` gains a required method, `symbol_key`.** Any crate implementing `Op` for\nits own lifter must add it. It renders the operation's first operand as the\nprogram's symbol table keys it, so a call target can be resolved; returning\n`None` when the operand cannot name a symbol is what keeps an unresolvable\ntarget distinguishable from a lookup that found nothing. Ghidra's\nimplementation parses the operand through the existing `Value` type.\n\n**`Op` gains a second required method, `is_call`.** Which operation is a call\nwas decided in the extractor by comparing the mnemonic against the literal\n`\"CALL\"`, which is P-Code's spelling; the Hex-Rays microcode and Binary Ninja's\nLLIL name it differently and some name more than one operation, so any other\nlifter would have matched nothing (#44). The question now belongs to the\noperation, and so to the lifter that defines it.\n\nThe method has no default on purpose. A `false` default would let a new lifter\ncompile while recognising no call at all, which produces empty `fc-*`\nbirthmarks rather than an error — and empty birthmarks score as a perfect\nmatch. Requiring it makes that a build failure. Ghidra answers for `CALL` and\n`CALLIND`, but not `CALLOTHER`, which indexes a table of user-defined\noperations rather than naming a function. Nothing changes in what Ghidra\nextracts today: `CALLIND` reaches its target through a register, so no symbol\nresolves for it.\n\n**`Op` loses `code`.** It returned the numeric opcode and had no callers: the\nbirthmark is built from `mnemonic`, a string. Keeping it would have made every\nfuture lifter invent a numbering for a value nothing reads (#45).\n\n**Which operation type reads a lifted file is now decided by the file.**\n`Program<T>` was generic, but nothing chose `T` — every caller wrote\n`Program<ghidra::Op>`, so a file lifted by another tool would have been read\nagainst P-Code's vocabulary. `AnyProgram::load` reads the `ir` field first and\npicks the reader from it, and `Extractor::extract_any` and\n`Comparator::compare_any` take what it returns (#45).\n\nA representation with no reader is now refused by name:\n\n```\nforeign.json: no reader for ida-microcode; this build can read ghidra-pcode\n```\n\nRead as P-Code it would have failed anyway, since the opcode enum is closed —\nbut on whichever foreign opcode it happened to meet first, reported as an\nunknown variant among seventy-five alternatives. That check is unchanged for\nfiles that really are Ghidra's; an unknown opcode is still an error.\n\n`Program::new` and the typed `Extractor::extract_each` and\n`Comparator::compare_programs` are unchanged, so code that knows its operation\ntype keeps working.\n\n**`lift::find_ghidra_home` is gone; use `LifterType::find_home`.** Discovery was\na Ghidra function re-exported as if it were the general one. It is now a method\non the backend, so each names its own environment variable and its own default\nlocations, and the error says which variable to set rather than naming\n`GHIDRA_HOME` for whatever tool was asked for (#46). `LifterType` also gains\n`name` and `home_spec`; `home_spec` is `None` for angr, which is imported as a\nPython library and has no installation directory to point at.\n\n**New public items** for asking whether a pairing is valid before building one:\n`Shape`, `BirthmarkType::shape`, `BirthmarkType::with_shape`,\n`BirthmarkType::pairs_with` and `Algorithm::shape`.\n\n**`Error` reports its cause.** `impl std::error::Error for Error` was empty, so\n`source()` returned `None` even for the seven variants holding a wrapped error\n(#62). Each now returns it, and an error chain has the depth it should. Nothing\ncalled `source()` before, because there was nothing to get.\n\n`Error` is derived with `thiserror` rather than hand-writing `Display`, so the\nmessage sits on the variant it belongs to. Every variant renders exactly as it\ndid, with one deliberate exception: `Error::Clap` no longer prefixes clap's\nmessage with `Clap error: `, since clap's already begins `error: `. No `#[from]`\nimpls were added, so nothing converts implicitly through `?` that did not\nbefore.\n\n**New public items for listing the vocabulary rather than hand-writing it**:\n`BirthmarkType::advertised`, `BirthmarkType::description`,\n`AnalysisType::advertised_names` and `MAX_ADVERTISED_K`; `Algorithm::cli_name`\nbecame public. `advertised_names` pairs each birthmark with the algorithms that\noperate on its shape, so a generated list cannot offer a pairing that\n`AnalysisType::new` refuses. These exist for building a completion list, and\nnone of them bounds what `try_from` accepts.\n\n**`oinkie lift` now lifts one file at a time.** It used to lift every input\nconcurrently with no bound. Pass `-j/--jobs N` to get the old behaviour, with N\nnaming how many files may be lifted at once (#55).\n\nLifting runs a whole decompiler process per file, and every input went to\nrayon's global pool, whose size is the machine's core count -- ten JVMs at once\non a ten-core laptop, with no way to ask for fewer. It is also unsafe on a fresh\ninstallation: Ghidra compiles its SLEIGH language definitions on first use and\ncaches them **inside its own installation**, so parallel lifts race to write the\nsame file and the loser reads a half-written one. `analyzeHeadless` exits\nsuccessfully regardless, so this arrives as a missing output rather than an\nerror (#54). Once the cache is built it cannot happen again, which is why `-j`\nprints a notice rather than being refused:\n\n```\nnotice: lifting up to 4 files at a time.\nGhidra builds its language cache on first use, inside its own installation,\nand parallel lifts can corrupt a cache that has not been built yet --\nreported as a missing output, not as an error.\nIf Ghidra was installed recently, lift one file without -j first.\n```\n\nScripts that lift more than one file and depend on the old speed need `-j`\nadded. `extract` and `compare` are unchanged and remain parallel: they are\ncomputation over local files, with no shared external state and no separate\nprocess per input.\n\n**`oinkie lift --intermediate` is the lifter's working directory.** It was\ndescribed as somewhere to keep \"Ghidra project directories\". Every headless\nlifter needs a directory to run in, because that is where its script writes its\nJSON; Ghidra additionally keeps its project there. The option, the flag and the\nbehaviour are unchanged — only what it is documented to mean, which now holds\nfor a lifter that is not Ghidra's.\n\n`--home` and `--script` keep one help string each. They mean the same thing for\nevery backend — an installation directory, and a script in whatever language\nthat backend runs — and the part that has to be per-lifter is the error, which\nnow is.\n\n## Highlights\n\n- **#30** — widened the birthmark hash prefix to 64 bits, removing a silent\n  overwrite that was reachable at corpus scale\n- **#29** — fixed the `left`/`right` inversion in similarity CSVs\n- **#40** — `fc-*` birthmarks resolve their symbols again; they were empty, so\n  unrelated programs scored a perfect match through all eight of them\n- **#36** — `lift -i` with a relative path no longer resolves it twice into\n  `irs/irs`, and the directory is created rather than having to exist\n- **#38** — analysis names are parsed in one place, and a pairing that cannot\n  mean what it says is rejected with the canonical form named\n- **#44** — which operation is a call is now the lifter's answer rather than a\n  literal `\"CALL\"` in the extractor, and a program in which nothing is a call is\n  refused instead of yielding an empty `fc-*` birthmark\n- **#45** — the lifted file decides which operation type reads it, so the\n  pipeline no longer assumes P-Code; a representation with no reader is refused\n  by name\n- **#54** — the tests that run a real Ghidra no longer run at the same time as\n  each other, so they cannot corrupt its language cache; two of them that\n  differed only in their `-i` path are now one\n- **#71** — an analysis name built from what `oinkie info` prints parses;\n  the split between the two halves is searched for rather than assumed to be\n  the last hyphen, so `weighted-jaccard` works inside a name and a two-word\n  algorithm added later needs no special care\n- **LLVM IR/BC is no longer named as a target.** The tagline and the site\n  described oinkie as a toolkit for \"Ghidra Pcode, LLVM IR/BC, and Binary\n  Ninja\", but LLVM is in neither `Ir` nor `LifterType` and is not in the\n  multi-lifter design work, which is about Binary Ninja and IDA Pro. The\n  documentation says what is there and what is planned\n- **The publication list is current, and the same in both places.** Three\n  papers are added to the README's references, and the two that\n  `docs/content/academic.md` was missing are added there with a description of\n  what each contributes\n- **The release script no longer rewrites text that merely contains the old\n  version.** It replaced the bare number everywhere in `README.md` and the\n  landing page, so cutting 0.3.0 to 0.4.0 would have turned a cited paper's\n  NII CRID `1572824500.3.007232` into `...500.4.007232` — silently, in the\n  released README (#75). Each replacement is anchored to the badge or link it\n  belongs to\n- **The CLI reference matches the CLI.** `cli/README.md` documented\n  `-B/--binary-type`, which this release removes, and was missing `lift -j`\n  and `run -A`; `lift`'s lifter list still read `ghidra, llvm, binary-ninja`\n  where it is `ghidra, angr, ida-pro, binary-ninja`; and the `oinkie info`\n  sample in the site docs was from v0.2.0 and showed a section the command\n  does not print. All of it is regenerated from the real output\n- **#68** — birthmark files are written in a canonical order, so the bytes are\n  a function of what the birthmark holds rather than of hash order; sequences\n  keep the program's order, which is theirs to keep\n- **#66** — a birthmark stating one operation's frequency twice is refused\n  rather than silently read as the last of them, in `op-freq` and `fc-freq` as\n  well as the k-gram shapes\n- **#59** — `op-*gram-freq` birthmarks can be written. Every non-empty one\n  failed with \"key must be a string\", so eight of the thirty birthmark types\n  the CLI advertises could not produce a file and twenty-four of its eighty\n  analyses were unreachable; the frequency map is a list of `[kgram, count]`\n  pairs now, and no existing file changes\n- **#51** — birthmark and program files are read whole and parsed from the\n  bytes, rather than through `serde_json::from_reader` on an unbuffered\n  `File`, which cost one syscall per byte. A 9 MB birthmark loads in 15 ms\n  where it took 2.7 s, and a `compare` over three such pairs went from 22.0 s\n  to 7.8 s\n- **`--skip` no longer reads a half-written similarity file as a score of\n  zero.** Found by covering the parser it lives in: the score defaulted when\n  the `result,` line was absent, so an interrupted run's leftovers came back\n  as a successful comparison finding nothing in common\n\n- **#62** — `Error` is derived rather than hand-written, and reports its\n  cause: `source()` was `None` for every variant, including the seven wrapping\n  a foreign error. A usage error is also no longer printed as\n  `Error: error: ...`\n- **#28** — line coverage is **95.3%**, up from 91.3%. `Error`'s `Display` is\n  covered for every variant, and the CLI's own parsers — the `--skip` reader\n  for a stored comparison, and everything `reaggregate` loads — are tested\n  against fixture files rather than only through end-to-end runs. Six of the\n  new tests were checked by breaking the code they cover\n- **#25** — the CLI stopped keeping its own copy of the analysis vocabulary.\n  Two hand-written `ValueEnum`s — 64 variants with 64 mapping arms, and 31 more\n  — are gone, and `--analysis` and `--birthmark-type` are parsed by the library\n  that already parsed those names. The k ceiling went with them, the two\n  options now agree with each other and with `oinkie info`, and the completion\n  list is generated from the pairing rules, so it cannot offer a pairing that\n  would be refused\n- **#24** — the tests no longer set `GHIDRA_HOME` and put it back afterwards.\n  Two of them ran at once in the same binary and saw each other's writes, which\n  is what made CI fail on a branch whose own checks were green; in edition 2024\n  `set_var` is `unsafe` precisely because a concurrent read of the environment\n  is undefined behaviour rather than merely a wrong answer. The search now takes\n  its environment, and its test for whether a path exists, as parameters — so a\n  test describes a machine instead of having to become one, and the case where\n  nothing is installed can be asserted for the first time\n- **#55** — `lift` is serial by default, with `-j/--jobs N` to opt back into\n  parallelism; the old default could corrupt Ghidra's language cache on a fresh\n  installation, and the corruption was reported as a missing output\n- **#46** — home discovery is per-backend, and the path handling around a\n  headless lifter — resolving before the working directory changes, running in\n  its own directory, moving the result across file systems — is written once\n  instead of once per tool. A lift that produced nothing now reports what the\n  tool said, since Ghidra exits successfully even when its script throws\n- The crate is now formatted with `cargo fmt`, and CI enforces it with\n  `cargo fmt --all -- --check`\n\n## What's Changed\n* fix: write the left CSV record from the first birthmark, not the second by @tamada in https://github.com/tamada/oinkie/pull/29\n* fix: widen the birthmark file name hash to 64 bits by @tamada in https://github.com/tamada/oinkie/pull/30\n* ci: take release notes from a file kept in the repository by @tamada in https://github.com/tamada/oinkie/pull/32\n* fix: remove the -B/--binary-type flag that was never read by @tamada in https://github.com/tamada/oinkie/pull/34\n* refactor: build completions from a separate gencomp binary by @tamada in https://github.com/tamada/oinkie/pull/35\n* fix: resolve the -i path before handing it to Ghidra by @tamada in https://github.com/tamada/oinkie/pull/37\n* refactor: delegate the birthmark half, and reject pairings that cannot mean what they say by @tamada in https://github.com/tamada/oinkie/pull/39\n* fix: resolve the symbol a call refers to, so fc-* is not empty by @tamada in https://github.com/tamada/oinkie/pull/47\n* feat: record which intermediate representation a lifted file holds by @tamada in https://github.com/tamada/oinkie/pull/48\n* feat: refuse to compare birthmarks from different representations by @tamada in https://github.com/tamada/oinkie/pull/49\n* feat: let the lifter say which operation is a call by @tamada in https://github.com/tamada/oinkie/pull/50\n* feat: let the lifted file choose the type that reads it by @tamada in https://github.com/tamada/oinkie/pull/52\n* refactor: write the headless lifter shape once, not once per tool by @tamada in https://github.com/tamada/oinkie/pull/53\n* feat: lift one file at a time unless asked for more by @tamada in https://github.com/tamada/oinkie/pull/56\n* test: stop the Ghidra tests from running at the same time by @tamada in https://github.com/tamada/oinkie/pull/57\n* test: hand the home search its environment instead of writing to ours by @tamada in https://github.com/tamada/oinkie/pull/58\n* refactor: let the library parse the names it already parses by @tamada in https://github.com/tamada/oinkie/pull/60\n* test: cover the error messages and the CLI's own parsers by @tamada in https://github.com/tamada/oinkie/pull/61\n* refactor: derive Error, and let it report its cause by @tamada in https://github.com/tamada/oinkie/pull/63\n* perf: read a JSON file whole instead of one syscall per byte by @tamada in https://github.com/tamada/oinkie/pull/64\n* fix: write a k-gram frequency as pairs, not as object keys by @tamada in https://github.com/tamada/oinkie/pull/65\n* fix: land #66 and #68, which merged into a dead end by @tamada in https://github.com/tamada/oinkie/pull/70\n* fix: find where an analysis name splits, rather than assume it by @tamada in https://github.com/tamada/oinkie/pull/72\n* docs: regenerate the CLI reference from the CLI by @tamada in https://github.com/tamada/oinkie/pull/73\n* fix: anchor the version replace to what it is replacing by @tamada in https://github.com/tamada/oinkie/pull/76\n* chore: update version to 0.4.0 by @tamada in https://github.com/tamada/oinkie/pull/74\n\n\n**Full Changelog**: https://github.com/tamada/oinkie/compare/v0.3.0...v0.4.0\n",
        "name": "Release v0.4.0",
        "release_date": "2026-09-02T09:16:43Z"
      }
    ],
    "topics": [
      "birthmark-toolkit",
      "birthmarks",
      "plagiarism-detection",
      "software-theft-detection",
      "ghidra-pcode"
    ]
  },
  {
    "description": "Minimal and alternative ls implementation in Rust.",
    "languages": [
      "Rust",
      "Dockerfile",
      "Just"
    ],
    "last_updated": "2026-07-25T08:06:22Z",
    "license": [
      {
        "name": "Creative Commons Zero v1.0 Universal",
        "spdx": "cc0-1.0",
        "url": "http://choosealicense.com/licenses/cc0-1.0/"
      }
    ],
    "links": [
      {
        "label": "logo",
        "url": "https://tamada.github.io/api/assets/lis.png"
      },
      {
        "label": "container",
        "url": "https://quay.io/repository/tama5/lis"
      },
      {
        "label": "sbom",
        "url": "https://api.github.com/repos/tamada/lis/dependency-graph/sbom"
      },
      {
        "label": "repository",
        "url": "https://github.com/tamada/lis"
      },
      {
        "label": "www",
        "url": "https://tamada.github.io/lis"
      }
    ],
    "name": "lis",
    "owner": "tamada",
    "releases": [
      {
        "description": "## What's Changed\n* Improve tests and docs by @tamada in https://github.com/tamada/lis/pull/14\n* Gemini by @tamada in https://github.com/tamada/lis/pull/13\n* feat: add Containerfile and Justfile for Docker containerization by @tamada in https://github.com/tamada/lis/pull/16\n* feat: add documentation and configuration files for lis project by @tamada in https://github.com/tamada/lis/pull/15\n* Releases/v0.0.11 by @tamada in https://github.com/tamada/lis/pull/17\n\n\n**Full Changelog**: https://github.com/tamada/lis/compare/v0.0.10...v0.0.11",
        "name": "Release v0.0.11",
        "release_date": "2026-06-19T03:22:04Z"
      }
    ],
    "topics": [
      "filesystem",
      "list-files"
    ]
  },
  {
    "description": "A phonetic code encoder/decoder written in Rust",
    "languages": [
      "Shell",
      "Rust",
      "Dockerfile"
    ],
    "last_updated": "2026-02-20T04:36:31Z",
    "license": [
      {
        "name": "MIT License",
        "spdx": "mit",
        "url": "http://choosealicense.com/licenses/mit/"
      }
    ],
    "links": [
      {
        "label": "logo",
        "url": "https://tamada.github.io/api/assets/spellout.svg"
      },
      {
        "label": "docs",
        "url": "https://docs.rs/spellout/latest"
      },
      {
        "label": "registry",
        "url": "https://crates.io/crates/spellout"
      },
      {
        "label": "container",
        "url": "https://ghcr.io/tamada/spellout"
      },
      {
        "label": "sbom",
        "url": "https://api.github.com/repos/tamada/spellout/dependency-graph/sbom"
      },
      {
        "label": "repository",
        "url": "https://github.com/tamada/spellout"
      },
      {
        "label": "www",
        "url": "https://tamada.github.io/spellout/"
      }
    ],
    "name": "spellout",
    "owner": "tamada",
    "releases": [
      {
        "description": "## Commits\n- 67c9b83: Add permissions for id-token in publish_to_crates_io job (Haruaki Tamada) [#3](https://github.com/tamada/spellout/pull/3)",
        "name": "Release v0.1.1",
        "release_date": "2026-02-20T04:36:32Z"
      }
    ],
    "topics": [
      "encoder-decoder",
      "phonetic-code"
    ]
  },
  {
    "description": "Git Ignore Managenement System for Multiple Repositories.",
    "languages": [
      "Rust",
      "Dockerfile",
      "Just",
      "HTML"
    ],
    "last_updated": "2026-08-08T12:10:13Z",
    "license": [
      {
        "name": "MIT License",
        "spdx": "mit",
        "url": "http://choosealicense.com/licenses/mit/"
      }
    ],
    "links": [
      {
        "label": "logo",
        "url": "https://tamada.github.io/api/assets/gixor.svg"
      },
      {
        "label": "docs",
        "url": "https://docs.rs/gixor/latest"
      },
      {
        "label": "registry",
        "url": "https://crates.io/crates/gixor"
      },
      {
        "label": "container",
        "url": "https://quay.io/repository/tama5/gixor"
      },
      {
        "label": "sbom",
        "url": "https://api.github.com/repos/tamada/gixor/dependency-graph/sbom"
      },
      {
        "label": "repository",
        "url": "https://github.com/tamada/gixor"
      },
      {
        "label": "www",
        "url": "https://tamada.github.io/gixor/"
      }
    ],
    "name": "gixor",
    "owner": "tamada",
    "releases": [
      {
        "description": "## What's Changed\n* Release v0.5.2 by @tamada in https://github.com/tamada/gixor/pull/52\n\n\n**Full Changelog**: https://github.com/tamada/gixor/compare/v0.5.1...v0.5.2",
        "name": "Release v0.5.2",
        "release_date": "2026-08-08T11:44:53Z"
      }
    ],
    "topics": [
      "gitignore",
      "gitignore-generator",
      "cli",
      "command-line-tool",
      "git"
    ]
  },
  {
    "description": "A tool for extracting/archiving files and directories in several formats.",
    "languages": [
      "Rust",
      "Dockerfile",
      "Just"
    ],
    "last_updated": "2026-08-12T11:21:07Z",
    "license": [
      {
        "name": "MIT License",
        "spdx": "mit",
        "url": "http://choosealicense.com/licenses/mit/"
      }
    ],
    "links": [
      {
        "label": "logo",
        "url": "https://tamada.github.io/api/assets/totebag.jpg"
      },
      {
        "label": "docs",
        "url": "https://docs.rs/totebag/latest"
      },
      {
        "label": "registry",
        "url": "https://crates.io/crates/totebag"
      },
      {
        "label": "container",
        "url": "https://ghcr.io/tamada/totebag"
      },
      {
        "label": "sbom",
        "url": "https://api.github.com/repos/tamada/totebag/dependency-graph/sbom"
      },
      {
        "label": "repository",
        "url": "https://github.com/tamada/totebag"
      },
      {
        "label": "www",
        "url": "https://tamada.github.io/totebag"
      }
    ],
    "name": "totebag",
    "owner": "tamada",
    "releases": [
      {
        "description": "## What's Changed\n* Release v0.9.0: pure Rust dependencies and consistency cleanup by @tamada in https://github.com/tamada/totebag/pull/93\n\n\n**Full Changelog**: https://github.com/tamada/totebag/compare/v0.8.16...v0.9.0",
        "name": "Release v0.9.0",
        "release_date": "2026-08-12T08:26:20Z"
      }
    ],
    "topics": [
      "archiver",
      "command-line-utilities",
      "compressor",
      "decompressor",
      "unarchiver"
    ]
  },
  {
    "description": "Detecting the build tools in use.",
    "languages": [
      "Rust",
      "Dockerfile",
      "HTML",
      "CSS",
      "Pkl"
    ],
    "last_updated": "2026-07-20T06:40:13Z",
    "license": [
      {
        "name": "MIT License",
        "spdx": "mit",
        "url": "http://choosealicense.com/licenses/mit/"
      }
    ],
    "links": [
      {
        "label": "logo",
        "url": "https://tamada.github.io/api/assets/btmeister.svg"
      },
      {
        "label": "docs",
        "url": "https://docs.rs/btmeister/latest"
      },
      {
        "label": "registry",
        "url": "https://crates.io/crates/btmeister"
      },
      {
        "label": "container",
        "url": "https://ghcr.io/tamada/btmeister"
      },
      {
        "label": "sbom",
        "url": "https://api.github.com/repos/tamada/btmeister/dependency-graph/sbom"
      },
      {
        "label": "repository",
        "url": "https://github.com/tamada/btmeister"
      },
      {
        "label": "www",
        "url": "https://tamada.github.io/btmeister"
      }
    ],
    "name": "btmeister",
    "owner": "tamada",
    "releases": [
      {
        "description": "",
        "name": "Release v0.7.4",
        "release_date": "2025-01-31T11:47:39Z"
      }
    ],
    "topics": [
      "build-tool",
      "project-analysis"
    ]
  },
  {
    "description": "Heatmap generator.",
    "languages": [
      "Shell",
      "Dockerfile",
      "Rust"
    ],
    "last_updated": "2026-07-25T08:08:04Z",
    "license": [
      {
        "name": "MIT License",
        "spdx": "mit",
        "url": "http://choosealicense.com/licenses/mit/"
      }
    ],
    "links": [
      {
        "label": "logo",
        "url": "https://tamada.github.io/api/assets/heatman.svg"
      },
      {
        "label": "docs",
        "url": "https://docs.rs/heatman/latest"
      },
      {
        "label": "registry",
        "url": "https://crates.io/crates/heatman"
      },
      {
        "label": "container",
        "url": "https://ghcr.io/tamada/heatman"
      },
      {
        "label": "sbom",
        "url": "https://api.github.com/repos/tamada/heatman/dependency-graph/sbom"
      },
      {
        "label": "repository",
        "url": "https://github.com/tamada/heatman"
      },
      {
        "label": "www",
        "url": "https://tamada.github.io/heatman"
      }
    ],
    "name": "heatman",
    "owner": "tamada",
    "releases": [
      {
        "description": "",
        "name": "Release v0.1.1",
        "release_date": "2026-06-19T07:09:27Z"
      }
    ],
    "topics": [
      "command-line-utilities",
      "csv",
      "data-visualization",
      "heatmap"
    ]
  },
  {
    "description": "Small Object Programming Checker.",
    "languages": [
      "Java",
      "HTML",
      "Shell",
      "Makefile",
      "Dockerfile"
    ],
    "last_updated": "2026-07-20T06:41:06Z",
    "license": [
      {
        "name": "Apache License 2.0",
        "spdx": "apache-2.0",
        "url": "http://choosealicense.com/licenses/apache-2.0/"
      }
    ],
    "links": [
      {
        "label": "logo",
        "url": "https://tamada.github.io/api/assets/9rules.svg"
      },
      {
        "label": "sbom",
        "url": "https://api.github.com/repos/tamada/9rules/dependency-graph/sbom"
      },
      {
        "label": "repository",
        "url": "https://github.com/tamada/9rules"
      },
      {
        "label": "www",
        "url": "https://tamada.github.io/9rules/"
      }
    ],
    "name": "9rules",
    "owner": "tamada",
    "releases": [
      {
        "description": "",
        "name": "v1.1.1",
        "release_date": "2020-09-23T07:22:55Z"
      }
    ],
    "topics": [
      "java8",
      "code-analysis",
      "code-review",
      "code-quality"
    ]
  },
  {
    "description": "peripheral utility commands for the shell.",
    "languages": [
      "Dockerfile",
      "Makefile",
      "Go",
      "HTML",
      "CSS"
    ],
    "last_updated": "2023-08-05T08:56:35Z",
    "license": [
      {
        "name": "MIT License",
        "spdx": "mit",
        "url": "http://choosealicense.com/licenses/mit/"
      }
    ],
    "links": [
      {
        "label": "logo",
        "url": "https://tamada.github.io/api/assets/peripherals.svg"
      },
      {
        "label": "sbom",
        "url": "https://api.github.com/repos/tamada/peripherals/dependency-graph/sbom"
      },
      {
        "label": "repository",
        "url": "https://github.com/tamada/peripherals"
      },
      {
        "label": "www",
        "url": "https://tamada.github.io/peripherals"
      }
    ],
    "name": "peripherals",
    "owner": "tamada",
    "releases": [
      {
        "description": "",
        "name": "Release v1.0.1",
        "release_date": "2023-08-05T08:56:35Z"
      }
    ],
    "topics": []
  },
  {
    "description": "Java birthmark toolkit, detecting the software theft by native characteristics of the programs.",
    "languages": [
      "Java",
      "HTML",
      "JavaScript",
      "CSS",
      "Dockerfile"
    ],
    "last_updated": "2026-05-08T17:53:32Z",
    "license": [
      {
        "name": "Apache License 2.0",
        "spdx": "apache-2.0",
        "url": "http://choosealicense.com/licenses/apache-2.0/"
      }
    ],
    "links": [
      {
        "label": "logo",
        "url": "https://tamada.github.io/api/assets/pochi.png"
      },
      {
        "label": "container",
        "url": "https://ghcr.io/tamada/pochi"
      },
      {
        "label": "sbom",
        "url": "https://api.github.com/repos/tamada/pochi/dependency-graph/sbom"
      },
      {
        "label": "repository",
        "url": "https://github.com/tamada/pochi"
      },
      {
        "label": "www",
        "url": "https://tamada.github.io/pochi"
      }
    ],
    "name": "pochi",
    "owner": "tamada",
    "releases": [
      {
        "description": "",
        "name": "Release v2.6.0",
        "release_date": "2021-12-13T05:24:16Z"
      }
    ],
    "topics": [
      "birthmarks",
      "plagiarism-detection",
      "software-theft-detection",
      "java9module",
      "birthmark-toolkit"
    ]
  },
  {
    "description": "get next/previous sibling directory name.",
    "languages": [
      "Shell",
      "Rust",
      "Just",
      "AppleScript",
      "Elvish"
    ],
    "last_updated": "2026-08-07T11:43:04Z",
    "license": [
      {
        "name": "Do What The F*ck You Want To Public License",
        "spdx": "wtfpl",
        "url": "http://choosealicense.com/licenses/wtfpl/"
      }
    ],
    "links": [
      {
        "label": "logo",
        "url": "https://tamada.github.io/api/assets/sibling.png"
      },
      {
        "label": "docs",
        "url": "https://docs.rs/sibling/latest"
      },
      {
        "label": "registry",
        "url": "https://crates.io/crates/sibling"
      },
      {
        "label": "sbom",
        "url": "https://api.github.com/repos/tamada/sibling/dependency-graph/sbom"
      },
      {
        "label": "repository",
        "url": "https://github.com/tamada/sibling"
      },
      {
        "label": "www",
        "url": "https://tamada.github.io/sibling/"
      }
    ],
    "name": "sibling",
    "owner": "tamada",
    "releases": [
      {
        "description": "## Bug Fixes\n- build the document site with the Hugo which the theme asks for [#47](https://github.com/tamada/sibling/pull/47) ([Haruaki Tamada](https://github.com/tamada/sibling/commit/37955eb3e39191c6db73078eab6aa2aefaa62d71))",
        "name": "Release v3.0.0",
        "release_date": "2026-08-07T04:51:08Z"
      }
    ],
    "topics": [
      "directory-traversal",
      "utility",
      "shell"
    ]
  },
  {
    "description": "another implementation of wc (word count) accepting archives, directories, and file lists.",
    "languages": [
      "Makefile",
      "Go",
      "Dockerfile",
      "Shell"
    ],
    "last_updated": "2026-07-20T06:39:06Z",
    "license": [
      {
        "name": "Apache License 2.0",
        "spdx": "apache-2.0",
        "url": "http://choosealicense.com/licenses/apache-2.0/"
      }
    ],
    "links": [
      {
        "label": "logo",
        "url": "https://tamada.github.io/api/assets/wildcat.svg"
      },
      {
        "label": "container",
        "url": "https://ghcr.io/tamada/wildcat"
      },
      {
        "label": "sbom",
        "url": "https://api.github.com/repos/tamada/wildcat/dependency-graph/sbom"
      },
      {
        "label": "repository",
        "url": "https://github.com/tamada/wildcat"
      },
      {
        "label": "www",
        "url": "https://tamada.github.io/wildcat"
      }
    ],
    "name": "wildcat",
    "owner": "tamada",
    "releases": [
      {
        "description": "* show progress bar (#30),\r\n* do not read the hidden files by the default (#32),\r\n* show entry count in the total line (#33),\r\n* fix the bug fails to open the directory contains the space on the PowerShell, Windows (#34), and\r\n* change order of options in the help message.",
        "name": "v1.2.0",
        "release_date": "2021-04-28T06:47:01Z"
      }
    ],
    "topics": [
      "word-count",
      "golang",
      "rest-api",
      "docker",
      "cli-app"
    ]
  }
]