replies - WireCatLabs/tg-cli GitHub Wiki

Auto-replies

This page is about answering Telegram messages automatically when you cannot answer yourself — for example, a short "I will answer in the morning" to people who write after working hours. By the end you have a working auto-reply: a rule with your reply text, a choice of who may get it, a way to check what it would answer before it sends anything, and ready-made texts from Drafts and reply templates.

A few words used below:

  • A rule says which incoming messages to answer and what to do: reply, open a task, or both.
  • A template is the reply text. It can include the sender's name and the time.
  • The audience is the list of people and chats that may get a reply at all, whatever a rule says.
  • tg personal serve is the background process that receives new messages and applies the rules.

Who gets a reply, and when anything is sent:

  • Replies go to everyone your rules match, unless you limit the audience. Answer only selected people with tg personal replies audience --reply listed --allow-people …, or leave some out with --deny-people and --deny-chats.
  • Nothing is sent until you turn sending on. permissions.replies.send must be allow. ask counts as no, because a background server has nobody to ask. A new rule is also off until you turn it on.

The full option lists are in the auto-reply commands.

Create and enable a rule

tg personal replies add away
tg personal replies edit away --template 'Thanks, {{ sender.firstName | default: "there" }}! I will answer in the morning.'
tg personal replies edit away --outside 09:00-19:00 --days mon-fri --timezone Europe/Madrid
tg personal replies edit away --per-chat 1/12h --per-person 1/1d

add creates a rule that is off, with every setting written out. The rules live in <profile>.replies.json, in the same folder as the configFile that tg config show --json names. By default the rules answer everyone they match. To answer only selected people, list their Telegram ids, comma-separated; tg personal contacts show <name> --json prints a person's id as id:

tg personal replies audience --reply listed --allow-people 1000001

To answer everyone except some people or chats, keep --reply all and deny them:

tg personal replies audience --deny-people 1000002 --deny-chats -1002000002

After the first command the file holds:

{
  "audience": {
    "reply": "listed",
    "allow": { "people": ["1000001"], "chats": [] },
    "deny": { "people": [], "chats": [] }
  },
  "rules": [ … ]
}

Rule ids are lower-case letters, digits and -, and each is unique. A rule that replies cannot be turned on with an empty template.

Then look at what it would have answered, turn it on, and start the server:

tg personal replies test --since-time 7d
tg personal replies on away
tg config set permissions.replies.send allow
tg personal serve

replies test reads only messages already in your local store. It sends nothing, changes nothing and never connects. tg personal replies off away turns one rule off.

Conditions and audience

replies edit changes only the fields you name. A comma-separated list replaces the whole list; an empty string clears it.

What Options
Action --do reply,task — a reply, a task, or both
Chats --kinds dialog,group, --allow-chats, --deny-chats
Conditions --words, --question / --no-question, --mentions-me / --no-mentions-me
Senders --allow-people, --deny-people, --contacts-only / --no-contacts-only
Reply --template, --as-reply / --no-as-reply
Limits --per-chat, --per-person, such as 1/12h
Working hours --outside, --days, --timezone, --no-hours

The first time you set working hours, give the window, the days and the time zone together; after that you can change one. A wrong edit does not overwrite the file, and the other rules, the audience and the record of what was answered stay as they were.

tg personal replies audience shows who the whole file may answer. A new file is --reply all: it answers anyone a rule matches. --reply listed answers only the allowed people and chats. --allow-people, --allow-chats, --deny-people and --deny-chats replace those lists, and a denial wins over an allowance. A task action opens a task on this computer and is not limited by the audience.

Templates and a model

Examples of reply texts for common cases, and when to keep a draft instead, are on Drafts and reply templates.

A template can use sender.firstName, sender.name, chat.title, chat.kind and now (in the rule's time zone, or UTC without working hours), with filters such as {{ now | date: "%H:%M" }}. The incoming message's text is not a template variable. Unknown variables and filters are refused.

A model may write only the ai block; everything outside it is your text:

Thanks, {{ sender.firstName | default: "there" }}!
{% ai %}Briefly confirm you got the message; I will answer tomorrow.{% else %}I will answer tomorrow.{% endai %}

The block's body is an instruction to the model. The incoming text goes to the model separately, as data. When no model is set up, there is no consent, or the call fails, the else text is sent; without an else, the message gets no reply and the reason is recorded.

Choose the model with models.replies.provider (openai or anthropic), models.replies.model and, for your own server, models.replies.base_url; models.default fills what is not set. Keep the key with tg personal models text key set.

Using a model needs its own consent, separate from the right to send:

tg personal replies consents show
tg personal replies consents grant
tg personal replies consents revoke
tg personal replies consents deny -1002000002
tg personal replies consents allow -1002000002

grant lets incoming message data go to the chosen provider for the whole profile. deny keeps one chat's messages away from the model; allow removes that, without granting consent. A new provider or endpoint needs consent again. tg personal replies test --ai sends stored messages to the model so you can see its text; it still sends nothing to Telegram.

What a rule never answers

  • Anyone the audience does not allow.
  • Your own messages, channels, bots, and messages sent on behalf of a chat.
  • An edited message, a message already handled, and anything that arrived before serve started.
  • In a group, a message that neither mentions you nor replies to you, unless the rule names that group in chats.

perChat and perPerson limits are required on every rule, so two auto-repliers that answer each other stop at the first limit.

Stop and look

tg personal replies pause
tg personal replies resume
tg personal replies status
tg personal sends list

pause stops every rule at once, a running serve included, without a restart; resume undoes it. status says whether sending is allowed, which rules are on and who they may answer. sends list shows each reply with the rule that sent it.

⚠️ **GitHub.com Fallback** ⚠️