{
 "number": 34721,
 "repo": "bitcoin/bitcoin",
 "url": "https://github.com/bitcoin/bitcoin/pull/34721",
 "title": "build: install shell completions via cmake",
 "author": "willcl-ark",
 "author_association": "MEMBER",
 "created_at": "2026-03-03T14:33:24Z",
 "updated_at": "2026-09-14T21:42:21Z",
 "age_days": 198,
 "draft": false,
 "labels": [
  "Build system"
 ],
 "milestone": null,
 "base": "master",
 "head_sha": "91b96bef3465eba2c4710a3b85c77ceb5809e142",
 "head_ref": "cmake-shell-completions",
 "head_repo": "willcl-ark/bitcoin",
 "head_history": [
  {
   "t": "2026-09-14T20:16:44Z",
   "sha": "91b96bef3465eba2c4710a3b85c77ceb5809e142"
  }
 ],
 "additions": 23,
 "deletions": 8,
 "changed_files": 4,
 "commit_count": 1,
 "size_bucket": "S",
 "mergeable_state": "clean",
 "bot": {
  "drahtbot": {
   "present": true,
   "reviews": {
    "ack": [
     {
      "login": "caesrcd",
      "url": "https://github.com/bitcoin/bitcoin/pull/34721#issuecomment-5671202708"
     }
    ],
    "concept_ack": [
     {
      "login": "w0xlt",
      "url": "https://github.com/bitcoin/bitcoin/pull/34721#issuecomment-3991957973"
     },
     {
      "login": "hebasto",
      "url": "https://github.com/bitcoin/bitcoin/pull/34721#pullrequestreview-3883527871"
     }
    ],
    "stale_ack": [
     {
      "login": "ryanofsky",
      "url": "https://github.com/bitcoin/bitcoin/pull/34721#pullrequestreview-4064593928"
     },
     {
      "login": "BrandonOdiwuor",
      "url": "https://github.com/bitcoin/bitcoin/pull/34721#pullrequestreview-4770881528"
     },
     {
      "login": "151henry151",
      "url": "https://github.com/bitcoin/bitcoin/pull/34721#issuecomment-5088106888"
     }
    ]
   },
   "conflicts": []
  }
 },
 "acks_parsed": {
  "w0xlt": {
   "kind": "concept_ack",
   "hash": null,
   "t": "2026-03-03T15:52:53Z",
   "stale": false
  },
  "hebasto": {
   "kind": "concept_ack",
   "hash": null,
   "t": "2026-03-03T15:57:18Z",
   "stale": false
  },
  "caesrcd": {
   "kind": "ack",
   "hash": "91b96bef3465eba2c4710a3b85c77ceb5809e142",
   "t": "2026-09-14T21:42:16Z",
   "stale": false
  },
  "BrandonOdiwuor": {
   "kind": "ack",
   "hash": "0a2d2cd11655b75b629992acb54dd2a572759fb0",
   "t": "2026-07-24T06:55:45Z",
   "stale": true
  },
  "ryanofsky": {
   "kind": "ack",
   "hash": "0a2d2cd11655b75b629992acb54dd2a572759fb0",
   "t": "2026-04-06T21:18:23Z",
   "stale": true
  },
  "151henry151": {
   "kind": "ack",
   "hash": "0a2d2cd11655b75b629992acb54dd2a572759fb0",
   "t": "2026-07-27T06:40:26Z",
   "stale": true
  }
 },
 "acks_tally": {
  "ack": 1,
  "stale_ack": 3,
  "concept_ack": 2,
  "approach_ack": 0,
  "nack": 0,
  "concept_nack": 0,
  "approach_nack": 0
 },
 "reviews": {
  "approved": 1,
  "changes_requested": 0,
  "distinct_reviewers": [
   "151henry151",
   "BrandonOdiwuor",
   "caesrcd",
   "fanquake",
   "hebasto",
   "kpcyrd",
   "luke-jr",
   "purpleKarrot",
   "ryanofsky",
   "sedited",
   "w0xlt"
  ]
 },
 "signals": {
  "needs_rebase": false,
  "ci_failed": false,
  "mergeable_state": "clean",
  "last_author_activity": "2026-09-14T20:19:37Z",
  "last_reviewer_activity": "2026-09-14T21:42:16Z",
  "last_reviewer": "caesrcd",
  "author_silent_days": 2,
  "waiting_on_author_days": 2,
  "days_since_update": 2
 },
 "refs": {
  "mentioned": [
   33385,
   33402,
   33747,
   34714
  ],
  "depends_on": [],
  "fixes": [
   34714
  ],
  "linked_issues": [
   {
    "number": 34714,
    "type": "issue",
    "state": "open",
    "merged": false,
    "merged_at": null,
    "title": "Install shell completions with cmake"
   }
  ],
  "references": [
   {
    "number": 34714,
    "type": "issue",
    "state": "open",
    "merged": false,
    "merged_at": null,
    "title": "Install shell completions with cmake"
   },
   {
    "number": 33385,
    "type": "pull",
    "state": "closed",
    "merged": true,
    "merged_at": "2026-04-07",
    "title": "contrib: Add bash completion for new bitcoin command"
   },
   {
    "number": 33402,
    "type": "pull",
    "state": "closed",
    "merged": false,
    "merged_at": null,
    "title": "contrib: Add zsh completion scripts"
   },
   {
    "number": 33747,
    "type": "pull",
    "state": "closed",
    "merged": false,
    "merged_at": null,
    "title": "contrib: zsh and fish completions for bitcoin wrapper executable"
   }
  ],
  "conflicts": []
 },
 "stack": {
  "shares_commits_with": [],
  "based_on": [],
  "base_for": []
 },
 "review_paths": [
  "CMakeLists.txt",
  "cmake/module/InstallBinaryComponent.cmake"
 ],
 "body": "Fixes #34714.\n\nPackagers currently need to copy shell completion scripts from `contrib/completions/` into the appropriate system directories. Install the scripts alongside their corresponding binaries with `cmake --install`, including when installing a binary by component.\n\nTargets declare their available bash and fish scripts explicitly, following the existing `HAS_MANPAGE` pattern. This avoids deciding what to install based on file existence at configure time.\n\nBash scripts install to `${datadir}/bash-completion/completions/`; fish scripts install to `${datadir}/fish/vendor_completions.d/`. Both are enabled by default. Use `-DINSTALL_BASH_COMPLETIONS=OFF` or `-DINSTALL_FISH_COMPLETIONS=OFF` to disable either shell\u2019s scripts.",
 "commits": [
  {
   "sha": "91b96bef3465eba2c4710a3b85c77ceb5809e142",
   "date": "2026-09-14T20:05:13Z",
   "message": "build: install shell completions via cmake\n\nPackagers currently need to copy shell completion scripts manually.\nInstall them with their corresponding binaries so component installs include\nthe matching scripts.\n\nDeclare the available scripts at each target call site. This follows the\nmanpage pattern and avoids silently omitting scripts added after CMake was\nconfigured. Allow bash and fish installation to be selected independently."
  }
 ],
 "timeline": [
  {
   "t": "2026-03-03T15:28:59Z",
   "kind": "comment",
   "who": "kpcyrd",
   "assoc": "NONE",
   "text": "I tested this patch and it works well for me :smiley_cat:"
  },
  {
   "t": "2026-03-03T15:52:53Z",
   "kind": "comment",
   "who": "w0xlt",
   "assoc": "CONTRIBUTOR",
   "text": "Concept ACK"
  },
  {
   "t": "2026-03-03T15:57:18Z",
   "kind": "review",
   "who": "hebasto",
   "assoc": "MEMBER",
   "state": "COMMENTED",
   "commit": "0a2d2cd11655b75b629992acb54dd2a572759fb0",
   "text": "Concept ACK."
  },
  {
   "t": "2026-03-03T16:08:05Z",
   "kind": "comment",
   "who": "fanquake",
   "assoc": "MEMBER",
   "text": "Will we start maintaining these, if we plan on installing them? #33747, #33402, #33385. There doesn't seem to be any interest historically from contributors."
  },
  {
   "t": "2026-03-04T11:45:02Z",
   "kind": "comment",
   "who": "willcl-ark",
   "assoc": "MEMBER",
   "text": "[quoted text omitted]\n\nFair shout. The alternative is to not maintain them and but to then also not ship them at all. My preference would be to maintain and install them.\n\nI have reviewed #33385 as I think this looks in the best shape to move forward, barring author response time."
  },
  {
   "t": "2026-03-04T18:30:02Z",
   "kind": "review",
   "who": "caesrcd",
   "assoc": "CONTRIBUTOR",
   "state": "COMMENTED",
   "commit": "0a2d2cd11655b75b629992acb54dd2a572759fb0",
   "text": "Concept ACK"
  },
  {
   "t": "2026-03-10T07:09:05Z",
   "kind": "review_comment",
   "who": "luke-jr",
   "assoc": "CONTRIBUTOR",
   "path": "CMakeLists.txt",
   "commit": "0a2d2cd11655b75b629992acb54dd2a572759fb0",
   "in_reply_to": null,
   "text": "Users are at least somewhat unlikely to use multiple shells, so it probably makes sense to have a separate option for each one"
  },
  {
   "t": "2026-03-10T09:45:18Z",
   "kind": "comment",
   "who": "purpleKarrot",
   "assoc": "MEMBER",
   "text": "I don't like the direction the `install_binary_component` command is evolving. My concerns are:\n\n* `if(EXISTS ${...})`: The problem is that adding a file may change the behavior of install, but only after cmake was manually rerun. Adding the file will not trigger the reconfiguration by itself. This leads to flakiness (similar to `file(GLOB)`).  `CMakeLists.txt` files should always explicitly describe the source tree. Things like `if(EXISTS)` and `file(GLOB)` should be reserved for `cmake -P` scripts.\n\n* `option(INSTALL_COMPLETIONS)`: This is a build option, that does not affect the build, hence the wrong tool for the job (so is `INSTALL_MAN`). Better: Use fine grained install components, to let the user decide at install time what to install. The 1:1 relationship of target and component is not helpful.\n\nThe whole `install_binary_component` command should be inlined at the call sites and then removed. This makes the `CMakeLists.txt` much more declarative:\n\n* For targets that are installed to the default location, don't specify the location but use the default.\n* For targets that have manpages and shell completions, install them. For targets that don't, just don't.\n\nAny \"convenience\" wrapper should be killed before it attracts more and more responsibilities."
  },
  {
   "t": "2026-03-11T08:23:05Z",
   "kind": "review",
   "who": "BrandonOdiwuor",
   "assoc": "CONTRIBUTOR",
   "state": "COMMENTED",
   "commit": "0a2d2cd11655b75b629992acb54dd2a572759fb0",
   "text": "Concept ACK\n\nInstalling shell completions automatically with `cmake --install` is more convenient. Tested on **Ubuntu 24.04** with bash.\n\n--prefix and --component install"
  },
  {
   "t": "2026-04-06T21:17:00Z",
   "kind": "review_comment",
   "who": "ryanofsky",
   "assoc": "MEMBER",
   "path": "cmake/module/InstallBinaryComponent.cmake",
   "commit": "0a2d2cd11655b75b629992acb54dd2a572759fb0",
   "in_reply_to": null,
   "text": "In commit \"build: install shell completions via cmake\" (0a2d2cd11655b75b629992acb54dd2a572759fb0)\n\nThis seems ok, but strictly speaking this is inconsistent with the approach used for manpages above. The manpage approach uses an explicit `HAS_MANPAGE` keyword like `install_binary_component(bitcoind HAS_MANPAGE)`, while this is automatically deciding whether to install files based on file existence.\n\nThe manpage approach seems a ilttle cleaner but also harder to maintain so I'm not sure which approach is better, but maybe it's worth considering using HAS_BASH_COMPLETEION, HAS_FISH_COMPLETION keywords here to be consistent?"
  },
  {
   "t": "2026-04-06T21:18:23Z",
   "kind": "review",
   "who": "ryanofsky",
   "assoc": "MEMBER",
   "state": "APPROVED",
   "commit": "0a2d2cd11655b75b629992acb54dd2a572759fb0",
   "text": "Code review ACK 0a2d2cd11655b75b629992acb54dd2a572759fb0"
  },
  {
   "t": "2026-07-21T08:59:24Z",
   "kind": "comment",
   "who": "sedited",
   "assoc": "MEMBER",
   "text": "@BrandonOdiwuor can you take another look here?"
  },
  {
   "t": "2026-07-24T06:55:45Z",
   "kind": "review",
   "who": "BrandonOdiwuor",
   "assoc": "CONTRIBUTOR",
   "state": "COMMENTED",
   "commit": "0a2d2cd11655b75b629992acb54dd2a572759fb0",
   "text": "ACK 0a2d2cd11655b75b629992acb54dd2a572759fb0\n\nI think installing bash (and fish) completions is a useful feature. I tested the functionality in my previous review and it worked as expected for the tools that have completion scripts.\n\nThat said, I share the same concerns with the approach raised above. This is not consistent with how manpages are handled, where a `HAS_MANPAGE` variable is passed to dictate installation.\n\n[quoted text omitted]"
  },
  {
   "t": "2026-07-27T06:40:26Z",
   "kind": "comment",
   "who": "151henry151",
   "assoc": "CONTRIBUTOR",
   "text": "Tested ACK 0a2d2cd11655b75b629992acb54dd2a572759fb0\n\nDebian 13, `BUILD_GUI=OFF`. Installed to a prefix:\n\n```console\n$ find /tmp/btc-pfx -type f \\( -path '*bash-completion*' -o -path '*fish/vendor*' \\) | sort\n/tmp/btc-pfx/share/bash-completion/completions/bitcoin-cli\n/tmp/btc-pfx/share/bash-completion/completions/bitcoind\n/tmp/btc-pfx/share/bash-completion/completions/bitcoin-tx\n/tmp/btc-pfx/share/fish/vendor_completions.d/bitcoin-cli.fish\n/tmp/btc-pfx/share/fish/vendor_completions.d/bitcoind.fish\n/tmp/btc-pfx/share/fish/vendor_completions.d/bitcoin-tx.fish\n/tmp/btc-pfx/share/fish/vendor_completions.d/bitcoin-util.fish\n/tmp/btc-pfx/share/fish/vendor_completions.d/bitcoin-wallet.fish\n```\n\nBash only ships for cli/d/tx (no scripts for util/wallet). Fish covered all five binaries I installed; `bitcoin-qt.fish` is in-tree but correctly stayed out with the GUI off. `-DINSTALL_COMPLETIONS=OFF` still installs man pages, just no completions. `DESTDIR` staging behaves the same. Sourced the installed bash completions \u2014 tab-completing from `-help` works (~138 flags for bitcoind).\n\nI can reproduce the `if(EXISTS)` issue: add `contrib/completions/bash/bitcoin-util.bash` after configuring and install just skips it, no warning. Only matters when someone adds a new completion file in-tree. Explicit `HAS_BASH_COMPLETION` / `HAS_FISH_COMPLETION` (like `HAS_MANPAGE`) would be cleaner.\n\nOn fanquake's maintenance point: these mostly pull options/commands from `-help` at completion time rather than hardcoding a full list (`bitcoin-cli.bash` does keep a small table of per-RPC arg hints). Shipping them isn't signing up to hand-maintain a flag table. Whether the project wants to own them at all is still a separate question."
  },
  {
   "t": "2026-07-27T15:40:01Z",
   "kind": "review",
   "who": "hebasto",
   "assoc": "MEMBER",
   "state": "COMMENTED",
   "commit": "0a2d2cd11655b75b629992acb54dd2a572759fb0",
   "text": "It looks like [this comment](https://github.com/bitcoin/bitcoin/pull/34721#discussion_r2909774251) is still unaddressed."
  },
  {
   "t": "2026-07-27T16:00:06Z",
   "kind": "review",
   "who": "hebasto",
   "assoc": "MEMBER",
   "state": "COMMENTED",
   "commit": "0a2d2cd11655b75b629992acb54dd2a572759fb0",
   "text": "[quoted text omitted]\n\nI agree. On the master branch, we have a [single](https://github.com/bitcoin/bitcoin/blob/a2aab6df97d9f3e1186e8c3fc57ad909cc8aef9b/src/test/CMakeLists.txt#L183-L185) use case, which will eventually go away once we switch to the test discovery approach. I suggest avoiding introducing more use cases for `if(EXISTS ${...})`.\n\n[quoted text omitted]\nI'm not convinced that using fine-grained install components is better because, for example, installing everything except manpages would be a headache due to limitations of the command syntax.\n\n[quoted text omitted]\nMany large projects, such as LLVM and Qt, use convenience wrappers extensively. In my opinion, they improve code maintainability as well,"
  },
  {
   "t": "2026-07-27T16:01:38Z",
   "kind": "review_comment",
   "who": "hebasto",
   "assoc": "MEMBER",
   "path": "cmake/module/InstallBinaryComponent.cmake",
   "commit": "0a2d2cd11655b75b629992acb54dd2a572759fb0",
   "in_reply_to": 3041745596,
   "text": "[quoted text omitted]\n\nI agree."
  },
  {
   "t": "2026-09-14T17:59:08Z",
   "kind": "comment",
   "who": "ryanofsky",
   "assoc": "MEMBER",
   "text": "@willcl-ark there seem to be more reasons given here to switch away from `if(EXISTS ${...})` to explicit keywords folllowing `HAS_MANPAGE` pattern. There are also other questions that could be addressed, but it seems like this is the only potentially blocking one?"
  },
  {
   "t": "2026-09-14T20:16:44Z",
   "kind": "force_push",
   "who": "willcl-ark",
   "commit": "91b96bef3465eba2c4710a3b85c77ceb5809e142"
  },
  {
   "t": "2026-09-14T20:19:37Z",
   "kind": "comment",
   "who": "willcl-ark",
   "assoc": "MEMBER",
   "text": "Thanks for the reviews (and the nudge!).\n\nI replaced the `if(EXISTS)` checks with explicit `HAS_BASH_COMPLETION` and `HAS_FISH_COMPLETION` keywords. I also split the install option into `INSTALL_BASH_COMPLETIONS` and `INSTALL_FISH_COMPLETIONS`, both enabled by default.\n\nAlso included is the (new-ish) bitcoin.bash."
  },
  {
   "t": "2026-09-14T21:42:16Z",
   "kind": "comment",
   "who": "caesrcd",
   "assoc": "CONTRIBUTOR",
   "text": "Tested ACK 91b96bef3465eba2c4710a3b85c77ceb5809e142\n\nArch Linux with bash, `cmake -B build -DINSTALL_FISH_COMPLETIONS=OFF`:"
  }
 ],
 "labels_log": [
  {
   "t": "2026-03-03T14:33:28Z",
   "action": "labeled",
   "label": "Build system",
   "who": "DrahtBot"
  },
  {
   "t": "2026-03-03T15:52:48Z",
   "action": "labeled",
   "label": "CI failed",
   "who": "DrahtBot"
  },
  {
   "t": "2026-03-03T21:11:43Z",
   "action": "unlabeled",
   "label": "CI failed",
   "who": "DrahtBot"
  }
 ],
 "state_log": [],
 "text_chars": 7814,
 "text_tokens_estimate": 1953,
 "changed_paths": [
  "CMakeLists.txt",
  "cmake/module/InstallBinaryComponent.cmake",
  "src/CMakeLists.txt",
  "src/qt/CMakeLists.txt"
 ],
 "files": [
  {
   "path": "CMakeLists.txt",
   "add": 2,
   "del": 0
  },
  {
   "path": "cmake/module/InstallBinaryComponent.cmake",
   "add": 14,
   "del": 1
  },
  {
   "path": "src/CMakeLists.txt",
   "add": 6,
   "del": 6
  },
  {
   "path": "src/qt/CMakeLists.txt",
   "add": 1,
   "del": 1
  }
 ],
 "test_lines": 0,
 "git": {
  "head": "91b96bef3465eba2c4710a3b85c77ceb5809e142",
  "head_matches_backup": true,
  "base": "cff00c547e7460fa1ec4aa1e38217793593d4263",
  "commits": [
   {
    "sha": "91b96bef34",
    "subject": "build: install shell completions via cmake",
    "files": 4,
    "add": 23,
    "del": 8
   }
  ],
  "patch_truncated": false
 },
 "input_hash": "eabc5ca6ced43310",
 "extracted_at": "2026-09-17T16:15:31+00:00"
}