{"id":47287778,"url":"https://github.com/quodlibetor/vcs-status-daemon","last_synced_at":"2026-04-02T19:03:18.809Z","repository":{"id":344713037,"uuid":"1182760527","full_name":"quodlibetor/vcs-status-daemon","owner":"quodlibetor","description":"A tool to keep track of version control status in the background so your shell prompt can be fast","archived":false,"fork":false,"pushed_at":"2026-03-31T23:39:56.000Z","size":3352,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-04-01T01:55:39.685Z","etag":null,"topics":["git","jujutsu","prompt"],"latest_commit_sha":null,"homepage":"","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/quodlibetor.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":null,"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,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-03-15T23:34:04.000Z","updated_at":"2026-03-31T23:39:30.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/quodlibetor/vcs-status-daemon","commit_stats":null,"previous_names":["quodlibetor/jj-status-daemon"],"tags_count":13,"template":false,"template_full_name":null,"purl":"pkg:github/quodlibetor/vcs-status-daemon","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/quodlibetor%2Fvcs-status-daemon","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/quodlibetor%2Fvcs-status-daemon/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/quodlibetor%2Fvcs-status-daemon/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/quodlibetor%2Fvcs-status-daemon/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/quodlibetor","download_url":"https://codeload.github.com/quodlibetor/vcs-status-daemon/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/quodlibetor%2Fvcs-status-daemon/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31313873,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-02T12:59:32.332Z","status":"ssl_error","status_checked_at":"2026-04-02T12:54:48.875Z","response_time":89,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"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":["git","jujutsu","prompt"],"created_at":"2026-03-16T06:18:33.072Z","updated_at":"2026-04-02T19:03:18.798Z","avatar_url":"https://github.com/quodlibetor.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"# vcs-status-daemon\n\nA background daemon that pre-caches [Jujutsu](https://github.com/jj-vcs/jj) and Git repository status, so shell prompts can retrieve it in milliseconds instead of waiting for `jj` or `git` to run on every prompt.\n\n\u003e [!WARNING]\n\u003e This project is entirely AI generated but it seems to work 🤖 🤷\n\n## Problem\n\nVCS tools like `jj` and `git` can be slow in large repositories. Shell prompt integrations that call them on every prompt add noticeable latency. This daemon watches for repository changes via filesystem notifications and keeps a formatted status string in memory, ready to serve instantly — giving you a single, fast status tool for both Jujutsu and Git repos.\n\n## Featrues\n\n* Daemon pre-renders templates and writes them to a cache, fully formatted\n  status is read into an env var by the shell integration.\n* Very fast (~2ms when run as a binary, microseconds with shell integration)\n  prompt display for both git and jujutsu.\n* Several built-in themes, including clones of several popular ones.\n* Write your on themes in tera, a Jinja-like templating language. (Take\n  inspiration from the [src/templates](./src/templates) directory.)\n* Works well with starship since the fully rendered template can be displayed\n  directly by the env_var module.\n\n## Installation\n\nRequires a working `jj` and/or `git` CLI installation.\n\nInstall prebuilt binaries via shell script\n\n```shell\ncurl --proto '=https' --tlsv1.2 -LsSf 'https://github.com/quodlibetor/vcs-status-daemon/releases/latest/download/vcs-status-daemon-installer.sh' | sh\n```\n\nInstall prebuilt binaries via Homebrew or Linuxbrew:\n\n```shell\nbrew install 'quodlibetor/tap/vcs-status-daemon'\n```\n\nInstall prebuilt binaries via [mise](https://mise.jdx.dev/)\n\n```shell\nmise use -g 'github:quodlibetor/vcs-status-daemon@latest'\n```\n\nInstall via cargo:\n\n```shell\ncargo install --git 'https://github.com/quodlibetor/vcs-status-daemon'\n```\n\nOr go to the [Releases](https://github.com/quodlibetor/vcs-status-daemon/releases) and download an artifact directly.\n\n## Usage\n\n### Shell prompt integration\n\nThe easiest thing to do is to just stick it in your prompt, this will work and averages ~2ms for me:\n\n```zsh\nPS1='$(vcs-status-daemon) \\$ '\n```\n\nTo be even faster you can avoid a subprocess spawn by initializing a shell function.\n\nAdd the following to your shell rc file. This sets a `VCS_STATUS` environment variable before each prompt — use it in your prompt however you like.\n\n```zsh\n# .zshrc\neval \"$(vcs-status-daemon init zsh)\"\nPS1='%~ ${VCS_STATUS}%# '\n```\n\n```bash\n# .bashrc\neval \"$(vcs-status-daemon init bash)\"\nPS1='\\w ${VCS_STATUS}\\$ '\n```\n\n```fish\n# config.fish\nvcs-status-daemon init fish | source\nset -g fish_prompt_vcs_status '$VCS_STATUS '\n```\n\n```nu\n# config.nu (paste the output, or save to a file and source it)\n# vcs-status-daemon init nu | save -f ~/.cache/vcs-status-daemon.nu\n# source ~/.cache/vcs-status-daemon.nu\n```\n\n#### With starship\n\n```zsh\n# .zshrc\neval \"$(vcs-status-daemon init zsh --starship)\"\n```\n\n```bash\n# .bashrc\neval \"$(vcs-status-daemon init bash --starship)\"\n```\n\n```fish\n# config.fish\nvcs-status-daemon init fish --starship | source\n```\n\n```nu\n# config.nu\n# vcs-status-daemon init nu --starship | save -f ~/.cache/vcs-status-daemon.nu\n# source ~/.cache/vcs-status-daemon.nu\n```\n\nThe `--starship` flag warns if it can't find your `starship.toml` or if it's missing the `[env_var.VCS_STATUS]` section. Add this to your `starship.toml`:\n\n\u003cdetails\u003e\u003csummary\u003eRecommended starship.toml configuration\u003c/summary\u003e\n\n```toml\n# Disable starship's built-in git modules (vcs-status-daemon handles both jj and git)\n[git_branch]\ndisabled = true\n\n[git_commit]\ndisabled = true\n\n[git_status]\ndisabled = true\n\n[git_state]\ndisabled = true\n\n[env_var.VCS_STATUS]\nformat = \"$env_value \"\n```\n\n\u003c/details\u003e\n\n### Themes\n\nThe exact output is configured via [tera](https://keats.github.io/tera/docs/#templates) templates.\n\nBuilt in templates are defined in [src/templates](./src/templates), you can use them as inspiration\nand define new ones in your config file via `vcs-status-daemon config edit`.\n\nYou can set any named template with `vcs-status-daemon config set template.name NAME`.\nAnd you can view the source code defining a template with the\n`vcs-status-daemon template print NAME` command.\n\nThere are several built-in templates that you can view with the\n`vcs-status-daemon template show` command:\n\n#### vcs-status-daemin detailed templates\n\nThese include line counts in addition to file counts:\n\n\u003cimg alt=\"detailed templates\" src=\"static/templates-detailed.png\" width=\"400\" /\u003e\n\n#### `vcs-status-daemon` simple templates\n\nThese just use color and minimal symbols to represent the status:\n\n\u003cimg alt=\"simple templates\" src=\"./static/templates-simple.png\" width=\"400\" /\u003e\n\n#### Clones of popular git prompts\n\nClones of templates from [gitstatus / p10k](https://github.com/romkatv/gitstatus),\n[starship](https://starship.rs/),\n[oh-my-zsh](https://github.com/ohmyzsh/ohmyzsh/blob/master/plugins/git-prompt/README.md),\nand [pure](https://github.com/factcondenser/pure-prompt):\n\n\u003cimg alt=\"cloned prompts\" src=\"./static/templates-imitations.png\" width=\"400\" /\u003e\n\nAnd see \"Format templates\" and \"Configuration\" below to write your own.\n\n### Commands\n\n```sh\n# Query status for the current directory (default, auto-starts daemon)\nvcs-status-daemon\n\n# Generate shell integration code (sets $VCS_STATUS before each prompt)\nvcs-status-daemon init (zsh|bash|fish|nu) [--starship]\n\n# Manage config\nvcs-status-daemon config set  K=V  # set a config value\nvcs-status-daemon config edit      # open config in $EDITOR, with\nvcs-status-daemon config path      # print config file path\n\n# Preview and manage templates\nvcs-status-daemon template show [NAMES...] [-n]      # show templates (all, or filtered by name)\nvcs-status-daemon template print NAME                # print raw template source\nvcs-status-daemon template format \"{{ change_id }}\"  # test a custom template\nvcs-status-daemon template set --name nerdfont       # set active template by name (alias for config set)\nvcs-status-daemon template set --format \"{{ ... }}\"  # set an inline format template (alias for config set)\nvcs-status-daemon template debug [--repo PATH]       # show template with variable values annotated inline\n\n# Restart the daemon (graceful shutdown + restart)\nvcs-status-daemon restart\n\n# Show daemon status (running, PID, uptime, watched repos)\nvcs-status-daemon status\n```\n\nThe client sends its current directory to the daemon, which walks up the directory tree to find a repo root (`.jj/` or `.git/`). The mapping from directory to repo root is cached. When run outside a recognized repository, the client exits silently with exit code 0, making it safe for unconditional prompt use.\n\n### Runtime directory\n\nBoth client and daemon resolve paths from a shared runtime directory:\n\n1. `VCS_STATUS_DAEMON_DIR` environment variable (if set)\n2. Default: `/tmp/vcs-status-daemon-$USER/`\n\nThe directory contains:\n- `sock` — Unix domain socket\n- `pid` — daemon PID file (for `restart` and `status`)\n- `cache/` — cached status files (read by the shell function for the fastest path)\n- `daemon.log` — log output (rotated at 5 MB)\n\nThe daemon also accepts a `--dir` CLI flag, which takes priority over the environment variable. When the client auto-starts the daemon, it always passes its resolved directory via `--dir` to ensure both sides agree.\n\n## Configuration\n\nConfiguration is loaded from `~/.config/vcs-status-daemon/config.toml`. All fields are optional and have sensible defaults.\n\n```toml\n# How many ancestor commits to search for bookmarks in jj repos (default: 10)\nbookmark_search_depth = 10\n\n# Enable ANSI color output (default: true)\ncolor = true\n\n[template]\n# Built-in template to use: \"ascii\" (default), \"nerdfont\", \"unicode\", \"simple\", or \"minimal\"\nname = \"ascii\"\n\n# Explicit format template (Tera syntax, overrides name if set)\n# format = \"...\"\n\n# User-defined variables injected into the template rendering context.\n# Built-in templates use these to control bookmark limiting.\n[template.vars]\n# max_bookmarks = \"5\"            # show at most 5 bookmarks, then \"(+N more)\"\n# prioritize_branches = \"bwm/*\"  # glob: matching bookmarks are shown first\n\n# User-defined named templates (selected via template.name)\n# [templates]\n# my_template = \"{{ change_id }} {{ description }}\"\n```\n\n## Format template\n\nThe `format` field is a [Tera](https://keats.github.io/tera/docs/) template string. Tera uses `{{ variable }}` for interpolation, `{% if %}` / `{% elif %}` / `{% endif %}` for conditionals, and `{% for x in list %}` / `{% endfor %}` for loops.\n\n### VCS type detection\n\nThe daemon detects whether a repository uses jj or git (jj wins if both `.jj/` and `.git/` are present) and exposes `is_jj` and `is_git` booleans. Use these to write templates that work for both:\n\n```tera\n{% if is_jj %}{{ change_id }}{% elif is_git %}{% if has_branch %}{{ branch }}{% else %}{{ commit_id }}{% endif %}{% endif %}\n```\n\n### Template variables\n\n#### VCS type\n\n| Variable | Type | Description |\n|---|---|---|\n| `is_jj` | bool | `true` if the repo is a jj repository. |\n| `is_git` | bool | `true` if the repo is a plain git repository (no `.jj/`). |\n\n#### Shared fields (both jj and git)\n\n| Variable | Type | Description |\n|---|---|---|\n| `commit_id` | string | Short commit ID. For jj repos with `color = true`, includes jj's native ANSI coloring. |\n| `description` | string | First line of the commit description (jj) or commit message summary (git). |\n| `empty` | bool | `true` if the working commit (jj) or HEAD commit (git) has no changes. |\n| `conflict` | bool | `true` if there are conflicts (jj conflict markers or git merge conflicts). |\n\n#### Diff stats\n\nThere are three groups of diff stat variables. For jj repos (which have no staging area), `*_working_tree` and unsuffixed/`*_total` are identical, and `*_staged` is always 0. For git repos, all three groups are independently populated.\n\n`file_mad_count` is the total number of **m**odified + **a**dded + **d**eleted files (i.e., `files_modified + files_added + files_deleted`).\n\n| Variable | Type | jj | git |\n|---|---|---|---|\n| `file_mad_count_working_tree` | integer | Files changed in `@` vs parent | Unstaged: working tree vs index |\n| `lines_added_working_tree` | integer | Lines added in `@` | Unstaged lines added |\n| `lines_removed_working_tree` | integer | Lines removed in `@` | Unstaged lines removed |\n| `file_mad_count_staged` | integer | Always 0 | Staged: index vs HEAD |\n| `lines_added_staged` | integer | Always 0 | Staged lines added |\n| `lines_removed_staged` | integer | Always 0 | Staged lines removed |\n| `file_mad_count` | integer | Same as `file_mad_count_working_tree` | Total: working tree vs HEAD |\n| `lines_added_total` | integer | Same as `lines_added_working_tree` | Total lines added |\n| `lines_removed_total` | integer | Same as `lines_removed_working_tree` | Total lines removed |\n\nThe default template uses unsuffixed/`*_total` since it gives the complete picture for both VCS types.\n\n#### jj-only fields\n\nThese are populated only for jj repositories. In git repositories they are empty/false/zero.\n\n| Variable | Type | Description |\n|---|---|---|\n| `change_id` | string | Short change ID (8 chars). With `color = true`, includes jj's native ANSI coloring. |\n| `bookmarks` | list | List of bookmark objects (see below). |\n| `has_bookmarks` | bool | `true` if any bookmarks were found in the ancestor search range. |\n| `divergent` | bool | `true` if the working commit is divergent. |\n| `hidden` | bool | `true` if the working commit is hidden. |\n| `immutable` | bool | `true` if the working commit is immutable. |\n\n\n#### git-only fields\n\nThese are populated only for git repositories. In jj repositories they are empty/false.\n\n| Variable | Type | Description |\n|---|---|---|\n| `branch` | string | Current branch name. Empty when HEAD is detached. |\n| `has_branch` | bool | `true` if on a branch, `false` if HEAD is detached. |\n| `rebasing` | bool | `true` if a rebase is in progress (interactive or non-interactive). |\n\n#### Workspace/worktree fields\n\n| Variable | Type | Description |\n|---|---|---|\n| `workspace_name` | string | Workspace name (jj) or worktree directory name (git). `\"default\"` / `\"main\"` for the primary workspace/worktree. |\n| `is_default_workspace` | bool | `true` if this is the default workspace (jj) or main worktree (git). |\n\n#### Bookmark objects (jj only)\n\nEach item in the `bookmarks` list has:\n\n| Field | Type | Description |\n|---|---|---|\n| `name` | string | Bookmark name, e.g. `\"main\"`. |\n| `distance` | integer | Number of commits between `@` and the bookmarked commit. `0` means the bookmark is on `@`. |\n| `display` | string | Pre-formatted display string: `\"main\"` when distance is 0, `\"main+2\"` otherwise. |\n| `tracking` | string | Tracking status: `\"tracked\"`, `\"untracked\"`, `\"ahead\"`, `\"behind\"`, or `\"sideways\"`. |\n\n#### Template variables (`[template.vars]`)\n\nUser-defined variables from `[template.vars]` are injected into the Tera rendering context alongside VCS variables. Built-in templates use these to control bookmark limiting:\n\n| Variable | Effect |\n|---|---|\n| `max_bookmarks` | Maximum number of bookmarks to display. Excess bookmarks are replaced with a \"(+N more)\" entry. |\n| `prioritize_branches` | Glob pattern (e.g. `bwm/*`, `*main*`). Matching bookmarks are sorted first before the limit is applied. |\n\nExample config:\n\n```toml\n[template.vars]\nmax_bookmarks = \"5\"\nprioritize_branches = \"bwm/*\"\n```\n\nYou can also define arbitrary variables for use in custom templates — any key in `[template.vars]` becomes available as a Tera variable.\n\n#### `limit_bookmarks` filter\n\nThe `limit_bookmarks` filter truncates a bookmark list and appends a \"(+N more)\" indicator:\n\n```tera\n{{ bookmarks | limit_bookmarks(count=3, prioritize=\"bwm/*\") }}\n```\n\n| Argument | Type | Description |\n|---|---|---|\n| `count` | integer (required) | Maximum number of bookmarks to show. |\n| `prioritize` | string (optional) | Glob pattern — matching bookmarks are sorted first. Supports `*` wildcards. |\n\nWhen `bookmarks.len() \u003e count`, the filter returns the first `count` items plus a synthetic entry with `display: \"(+N more)\"`. You can use it in custom templates directly, or let the built-in templates apply it automatically via `max_bookmarks` / `prioritize_branches` template vars.\n\n#### Color filters\n\nColors are applied using Tera's filter syntax: `{{ value | green }}`. When `color = true`, filters wrap the value in ANSI escape codes. When `color = false`, filters are no-ops (the value passes through unchanged).\n\n| Filter | ANSI code |\n|---|---|\n| `bold` | `\\e[1m` |\n| `dim` | `\\e[2m` |\n| `italic` | `\\e[3m` |\n| `underline` | `\\e[4m` |\n| `red` | `\\e[31m` |\n| `green` | `\\e[32m` |\n| `yellow` | `\\e[33m` |\n| `blue` | `\\e[34m` |\n| `magenta` | `\\e[35m` |\n| `cyan` | `\\e[36m` |\n| `white` | `\\e[37m` |\n| `bright_red` | `\\e[91m` |\n| `bright_green` | `\\e[92m` |\n| `bright_yellow` | `\\e[93m` |\n| `bright_blue` | `\\e[94m` |\n| `bright_magenta` | `\\e[95m` |\n| `bright_cyan` | `\\e[96m` |\n| `bright_white` | `\\e[97m` |\n\nYou can apply filters to variables (`{{ branch | green }}`), string literals (`{{ \"CONFLICT\" | bright_red }}`), or concatenated values (`{{ \"+\" ~ lines_added_total | bright_green }}`).\n\n### Built-in templates\n\nFive templates are included. Select one with `template.name` in your config:\n\n```toml\n[template]\nname = \"nerdfont\"\n```\n\n\n#### `ascii` (default)\n\nWorks in any terminal. Example output:\n\n- **jj**: `JJ xlvlt main [3 +10-5]` or `JJ xlvlt (EMPTY)`\n- **git**: `+- main [3 +10-5]` or `+- abc1234` (detached HEAD)\n\n#### `nerdfont`\n\nRequires a [Nerd Font](https://www.nerdfonts.com/). Uses iconic glyphs for VCS type, conflicts, divergence, etc. Example output:\n\n- **jj**: `󱗆 xlvlt main [3 +10-5]` or `󱗆 xlvlt ∅`\n- **git**: `󰊢 main [3 +10-5]` or `󰊢 abc1234` (detached HEAD)\n\n#### `unicode`\n\nUses standard Unicode symbols (no Nerd Fonts needed). Example output:\n\n- **jj**: `⋈ xlvlt ≡ main [3 +10-5]`\n- **git**: `± main [3 +10-5]` or `± abc1234` (detached HEAD)\n\n#### `simple`\n\nBranch/bookmark name with compact diff-type indicators. Shows `[~+-?]` when there are changes: `~` modified, `+` added, `-` deleted, `?` untracked. For jj, shows the bookmark name, description, or change ID depending on context, with immutable commits highlighted in red.\n\n#### `minimal`\n\nJust the branch or bookmark name, color-coded by state. Green = clean, yellow = changes, red = unstaged (git), magenta = untracked (git). For jj, shows the bookmark name, description, or change ID depending on context.\n\n### User-defined templates\n\nYou can define your own named templates in the config and select them with `template.name`:\n\n```toml\n[template]\nname = \"minimal\"\n\n[templates]\nminimal = \"{{ commit_id }} {{ description }}\"\n```\n\nUser templates take priority over built-in ones — you can override `ascii` or `nerdfont` with your own version.\n\nUse `vcs-status-daemon template print \u003cname\u003e` to view the raw source of any template (includes are inlined automatically). This is a good starting point for writing your own.\n\nUse `vcs-status-daemon template debug` to see the current template with each variable's value annotated inline (e.g. `{{ change_id_prefix=su | magenta }}`), plus a list of available variables not used by the template.\n\nThe built-in `ascii`, `nerdfont`, and `unicode` templates all share the same body (`detail.tera`) and differ only in their icon constants. You can use the same pattern in your own templates — set icon variables with `{% set %}` and then `{% include \"detail.tera\" %}`:\n\n```toml\n[template]\nname = \"my_icons\"\n\n[templates]\nmy_icons = '''\n{% set jj_icon = \"jj\" -%}\n{% set git_icon = \"git\" -%}\n{% set bookmark_prefix = \"\" -%}\n{% set rebasing_icon = \"REBASING\" -%}\n{% set conflict_icon = \"!!\" -%}\n{% set divergent_icon = \"DIVERGENT\" -%}\n{% set hidden_icon = \"HIDDEN\" -%}\n{% set immutable_icon = \"IMMUTABLE\" -%}\n{% set empty_icon = \"(empty)\" -%}\n{% set stale_icon = \"STALE\" -%}\n{% set workspace_open = \"(\" -%}\n{% set workspace_close = \")\" -%}\n{% include \"detail.tera\" %}'''\n```\n\n### Inline format override\n\nThe `format` field directly sets the template string, overriding `template.name`:\n\n```toml\n[template]\nformat = \"{{ change_id }} {{ branch }}\"\n```\n\nIn TOML, use multi-line literal strings (`'''`) for readability. Use Tera's `{%-` whitespace trimming to prevent newlines from appearing in the output:\n\n```toml\n[template]\nformat = '''\n{% if is_jj %}{{ change_id }}\n{%- for b in bookmarks %} {{ b.display | blue }}{% endfor %}\n{%- elif is_git %}{% if has_branch %}{{ branch | blue }}{% else %}{{ commit_id }}{% endif %}\n{%- endif %}'''\n```\n\n### Custom template examples\n\n**jj-only, minimal** -- just change ID and bookmarks, no color:\n\n```toml\ncolor = false\n\n[template]\nformat = '''\n{{ change_id }}\n{%- for b in bookmarks %} {{ b.display }}{% endfor %}'''\n```\n\n**git-only, minimal** -- branch name (or commit hash when detached):\n\n```toml\ncolor = false\n\n[template]\nformat = \"{% if has_branch %}{{ branch }}{% else %}{{ commit_id }}{% endif %}\"\n```\n\n**Verbose, both VCS** -- with description/state details:\n\n```toml\n[template]\nformat = '''\n{% if is_jj %}{{ change_id }} {{ commit_id | dim }}\n{%- for b in bookmarks %} {{ b.display | blue }}{% endfor %}\n{%- if description %} {{ description | dim }}{% endif %}\n{%- elif is_git %}{% if has_branch %}{{ branch | blue }}{% else %}{{ commit_id | dim }}{% endif %}\n{%- endif %}\n{%- if file_mad_count \u003e 0 %} {{ file_mad_count | bright_blue }}f {{ \"+\" ~ lines_added_total | bright_green }} {{ \"-\" ~ lines_removed_total | bright_red }}{% endif %}\n{%- if empty %} {{ \"empty\" | yellow }}{% endif %}\n{%- if conflict %} {{ \"conflict!\" | bright_red }}{% endif %}'''\n```\n\n**Custom bookmark formatting** -- show distance differently (jj only):\n\n```toml\n[template]\nformat = '''\n{{ change_id }}\n{%- for b in bookmarks %} {{ b.name | cyan }}{% if b.distance \u003e 0 %}~{{ b.distance }}{% endif %}{% endfor %}\n{%- if empty %} {{ \"empty\" | dim }}{% endif %}'''\n```\n\n## How it works\n\n### Architecture\n\n```\nShell prompt calls:   vcs-status-daemon         (client mode, the default)\n                          |\n                          | connects to Unix domain socket\n                          v\n                      vcs-status-daemon daemon   (background server)\n                          |\n                          +-- detects VCS type (jj wins if both .jj/ and .git/ exist)\n                          +-- watches repo via filesystem notifications (notify)\n                          +-- on change: shells out to jj or git, caches formatted status\n                          +-- serves cached text to clients instantly\n```\n\n- **Single binary, two modes**: `daemon` (background server) and default (client/query)\n- **Auto-start**: the client spawns the daemon automatically if it's not running\n- **Multi-repo**: the daemon tracks multiple repositories, each with its own filesystem watcher\n- **Dual VCS**: supports both jj and git repositories, with jj taking priority when both are present\n\n### Step by step\n\n1. **Client** connects to the daemon's Unix domain socket. If the daemon isn't running, the client spawns it as a detached background process and retries.\n\n2. **Daemon** receives a query with a directory path and walks up to find the repo root. It detects the VCS type (`.jj/` takes priority over `.git/`). On first query for a repo, it:\n   - Sets up a filesystem watcher appropriate for the VCS type:\n     - **jj**: watches `.jj/repo/op_heads/heads/` (operations) and the working directory\n     - **git**: watches `.git/` and `.git/refs/` (ref changes) and the working directory\n   - Shells out to `jj` or `git` to gather status info (commit, branch/bookmarks, diff stats)\n   - Renders the format template and caches the result\n\n3. **On filesystem changes**, the daemon immediately re-runs the appropriate VCS command and updates the cache (at most one refresh per repo at a time; events arriving during a refresh trigger a re-refresh on completion). For jj repos, it uses `--ignore-working-copy` when only `.jj/` internal files changed (faster, avoids unnecessary snapshots), and omits it when working copy files changed (so `jj` snapshots first, giving accurate diff stats).\n\n4. **Subsequent queries** return the cached string instantly.\n\n## Development\n\n```sh\n# Run tests (requires jj and git to be installed)\ncargo nextest run\n\n# Or with plain cargo\ncargo test\n\n# Build\ncargo build --release\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fquodlibetor%2Fvcs-status-daemon","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fquodlibetor%2Fvcs-status-daemon","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fquodlibetor%2Fvcs-status-daemon/lists"}