{% extends "base.html" %} {% import "macros.html" as m %} {% block title %}Settings{% endblock %} {% macro status(done) %}{{ 'done' if done else 'pending' }}{% endmacro %} {% macro step_errors(step) %}{% set errs = form_errors.get(step, {}) %}{% if errs %}
You · BCC capture · Calendar · Backup · Appearance · Fields · Drafts · AI · Task types · Outcomes · Schedule · Access · Support Hermit · About · Help
{% if os_store %}Secrets are stored in .secrets.toml (mode 600) or {{ os_store_label }}, never in config.toml.{% if os_store == 'secret-service' %} A keyring is locked while you are logged out, so a daily import that runs then cannot read the password; keep it in .secrets.toml if the machine imports without you logged in.{% endif %}{% elif is_windows %}Secrets are stored in .secrets.toml, never in config.toml. They are plain text, readable only by your user account and never committed to git.{% else %}Secrets are stored in .secrets.toml, never in config.toml. No system keyring was found (install libsecret-tools and run a Secret Service such as GNOME Keyring or KWallet to use one), so they are plain text, readable only by your user account (mode 600) and never committed to git.{% endif %} Everything else is written to config.toml, comments kept.{% if setup_pending %} Skip for now{% endif %}
How it works: when you write to a prospect, put a tracking address in BCC (or forward the thread to it later). Hermit CRM reads that mailbox over IMAP, matches each message to a company by the other person's address or domain, and logs it as an interaction. Mail you send or forward to someone at a domain no company has creates that company, named after the domain. Personal addresses and domains that fit more than one company wait on Home, under To file. With Gmail, you+crm@gmail.com reaches your own inbox, so no second account is needed; a filter can file those messages out of the way.
Gmail filter (Settings → Filters → Create new filter): {{ gmail_filter }}
Mail it cannot place waits on Home, under To file.
{% if last_run %} {% if last_run.ok %}Last import {{ last_run.at | replace('T', ' ') }}: {{ last_run.summary }}
{% else %}Last import {{ last_run.at | replace('T', ' ') }} failed: {{ last_run.error }}
{% endif %} {% else %}No import has run yet.
{% endif %} {% if inbox_alert and last_run and last_run.ok %}{{ inbox_alert }}
{% endif %}Optional. The secret ICS address of your calendar (Google: Settings → your calendar → Integrate calendar → Secret address in iCal format). Treat it like a password.
{{ step_errors('calendar') }}Last meeting import {{ calendar_last_run.at | replace('T', ' ') }}: {{ calendar_last_run.summary }}
{% else %}Last meeting import {{ calendar_last_run.at | replace('T', ' ') }} failed: {{ calendar_last_run.error }}
{% endif %} {% else %}No meeting import has run yet. Past meetings whose attendees match no company wait on Home, under To file.
{% endif %}Every few minutes, to a repository outside this folder that can only grow: a reset, a deleted .git or a force-push loses nothing, and any version can be put back. How it works and how to roll back.
{%- if lb.level == 'ok' and lb.age_minutes is not none -%} Last backup {{ 'just now' if lb.age_minutes < 1 else lb.age_minutes ~ ' min ago' }} ({{ lb.size }}). {%- elif not lb.last_ok -%} No backup yet. {%- else -%} {{ lb.summary }} {%- endif -%} {% if lb.last_ok and not schedule.backup_installed %} It does not repeat on its own yet.{% endif %}
{% if schedule.backup_elsewhere %}This computer's backup job is set up for another folder, {{ schedule.backup_elsewhere }}; there is one per computer. To back up this folder instead, run hermitcrm --data {{ about.data_dir }} schedule install; that folder is then no longer backed up.
In {{ lb.dest }}, outside your CRM folder, so deleting the folder does not delete the backup. To keep it somewhere else, such as another disk or a synced folder, set backup_dir in config.toml.
{{ line }}The backup above lives on the same disk as your data. For a copy that survives a lost laptop, push the folder to a git remote after every change.
The repository must be PRIVATE on GitHub, GitLab or Bitbucket: it holds your contacts and mail.
{% if remote_warning %}{{ remote_warning }}
{% endif %}In use: {{ theme_file.path }}. It changes colours and fonts on top of the default. Delete the file to go back to the default look.
Not in use. To change colours or fonts, ask your AI tool to write {{ theme_file.path }}, for example "make my Hermit CRM blue". It is one block like the one below; Help > Settings lists what you can change.
{{ theme_example }}
{% endif %}
Fields of your own, on top of the ones Hermit CRM has. Their values live in the front matter of the record they belong to, like every other field, so nothing is hidden in a database. They are described in fields.toml next to your data.
| key | label | type | on | shown in |
|---|---|---|---|---|
{{ f.key }} | {{ f.label }} | {{ f.type }} | {{ f.applies_to }} | {{ f.show_in | join(', ') }} |
No fields of your own yet.
{% endif %}Every field of your own is a slot the outreach templates can use by name, written {{ '{' }}key{{ '}' }}; an empty one renders as its label in square brackets, the mark the templates already use for "only you can fill this in". Two of them can also play the roles the shipped wording knows about. See Messages.
Enrich and Ask the Hermit use an AI CLI you already have. The Enrich button asks it for a company's or contact's empty fields; Ask the Hermit answers questions about the page you are on, then about the whole CRM. Provider auto takes the first of claude, codex, gemini, grok it finds; custom runs the command line below. "Fetch from URL" needs none of this.
In use: {{ enrich_status.provider }}
{% else %}Unavailable: {{ enrich_status.reason }}
When Hermit CRM runs under launchd or systemd (hermitcrm schedule install --serve) it starts with a bare PATH: the CLI must be in /usr/local/bin, /opt/homebrew/bin or ~/.local/bin, or give its full path as the command.
Your own labels for tasks and next steps, e.g. pipeline follow-up, prospecting, lost deals. A type is a label and a filter; it changes no dates. Renaming a type renames it on every task that has it. Deleting one leaves it on its tasks, in grey.
{{ step_errors('task-types') }}The outcome choices for an interaction, one per line, in order. The first is what a detected reply counts as; the last is what silence past the message window counts as. A sent message with no outcome and no reply is unknown until the window passes.
{{ step_errors('outcomes') }}The daily job runs hermitcrm sync --apply (BCC, then calendar import). Read-only here; install or remove it from a terminal.
{{ line }}Install (daily at 07:00; --at HH:MM changes the time, drop --serve to leave the web app to you):
{{ schedule.install_command }}
Two more ways into the same folder. Both start from a terminal, so this section is read-only.
The app is bound to {{ access.host }}{% if not access.on_network %}, which only this machine can reach{% endif %}. Bind it to every interface and open the app on your phone over the same Wi-Fi:
{{ access.serve_command }}
Then open {{ access.lan_url }} on the phone. To make it permanent, set host = "0.0.0.0" in config.toml.
Hermit CRM has no password. Anyone who can reach that port can read and write your CRM, so use it on a network you trust, or a private one (Tailscale, WireGuard) rather than public Wi-Fi.
Lets a desktop AI client on this machine — Claude Desktop, ChatGPT desktop, Cursor — read and write this CRM with no terminal: ask for your pipeline, what you owe a reply to, a brief before a meeting, and log the call afterwards. Seven read tools and three writes; the writes commit exactly as the web form does.
{{ access.mcp_command }}
It speaks on stdin and stdout, so you do not run it yourself: paste this into your client's MCP config and it starts it for you. That also means the client must run on this machine — a phone app cannot reach it. For the phone, use the section above.
{{ access.mcp_config }}
Details and the full tool list: AI agents.
Hermit CRM is free and open source, and stays that way. If it earns its place in your week, you can support its development with a tip on Ko-fi.
Opens {{ support_url | replace('https://', '') }} in your browser. Nothing in the app depends on it, and Hermit CRM sends nothing to Ko-fi.
| Version | Hermit CRM v{{ about.version }}{% if update_notice and update_notice.available %} — v{{ update_notice.available }} available: {{ update_notice.hint }}{% elif about.update_note %} ({{ about.update_note }}){% endif %} |
|---|---|
| Data folder | {{ about.data_dir }} |
| Data format | {% if about.data_format is none %}unknown{% else %}{{ about.data_format }}{% if about.data_format != about.latest_format %} (this Hermit CRM writes {{ about.latest_format }}; run hermitcrm migrate){% endif %}{% endif %} |
| Check the installation | hermitcrm --data {{ about.data_dir }} doctor (add --online to try the IMAP login) |
| Help | All help topics, or hermitcrm help |