Commands
Every slash command, message menu item, picker, prompt and DM the bot has, with options, defaults, limits and replies. Entries follow registration order, with the message menu and the tag flow next to /follow, then the ticket prompt and the meeting action items. Commands for asking, summaries, Linear and voice notes exist only while their feature is on; see When commands exist.
Terms used below:
- Message menu: the Apps entry you get by right-clicking (or long-pressing) a message.
- Picker: a private message with a drop-down of times and a Pick a time button.
- Tag: mentioning the bot in a message.
- Prompt: a direct message the bot starts on its own, such as the ticket prompt.
- Private: only the person who used the command can see the reply.
- Linear: the issue tracker the bot files tickets in.
- Gemini: the AI model the bot calls.
GEMINI_API_KEYis the key it needs. - Settings in capitals, such as
REMINDER_ALLOWLIST, are bot settings listed in Configuration.
Rules that apply everywhere
Section titled “Rules that apply everywhere”- The bot works in one server only. Anything from another server is ignored without a reply.
- Replies to commands, menus and buttons are private. The exceptions are the reply to a tag (a follow-up confirmation or an answer), a public
/ask, replies to an upload in the meetings channel, and the voice-note posts: a notice and a result line in the voice channel’s text chat, and the summary in the meetings channel or in that chat. The ticket prompt and the meeting action items are DMs. - The bot saves your server display name when you use
/whoami,/hours,/reminders, the message menu, the follow-up picker,/ask, or tag it with a follow-up request or a question. /followsaves it once the message link is accepted,/summary nowonce its checks pass, and every/interestssubcommand once its input checks pass./linear-admin linksaves it for the member you pick, if the bot has no record of them yet./reminder-rules,/summary-admin,/notesand/notes-admindo not save it.- An unexpected error shows as
Something went wrong.After a button, drop-down or form on a message, the apology is a new private message and the original stays as it was. - An unknown command or button shows
Unknown command.orUnknown action.
| Command | Who can use it | Where |
|---|---|---|
/whoami, /hours, /follow, /reminders | Anyone in the server | Server |
| Message menu “Remind me to follow up” | Anyone in the server | Server |
| Tag the bot in a reply | Anyone in the server | Server channels |
/ask and the answer to a tag | Anyone in the server. The feedback buttons only for the asker | Server, and a public answer in a server channel |
| Ticket prompt (buttons and form) | Only the author of the message that triggered it | Direct message |
| Meeting action items (drop-down and buttons) | Only the owner of the items. Items with no owner belong to whoever uploaded the transcript | Direct message |
/reminder-rules | Members with Manage Server | Server only, not in DMs |
/notes | Anyone in the server | Server only, not in DMs |
/notes-admin | Members with Manage Server | Server only, not in DMs |
/summary now | Recipients of that summary, and members with Manage Server | Server |
/interests | Anyone in the server | Server |
/summary-admin | Members with Manage Server | Server only, not in DMs |
/linear-admin | Members with Manage Server | Server only, not in DMs |
When commands exist
Section titled “When commands exist”A command whose switch is off is removed from the server at the next start. Each switch is a setting; see Configuration.
| Commands | Exist while |
|---|---|
/summary, /interests, /summary-admin | SUMMARIES_ENABLED is true |
/notes | VOICE_NOTES_ENABLED and MEETING_TRANSCRIPTS_ENABLED are true and GEMINI_API_KEY is set |
/notes-admin | MEETING_TRANSCRIPTS_ENABLED is true and GEMINI_API_KEY is set, so an upload-only install can still name the summary channel |
/linear-admin | LINEAR_API_KEY is set, whatever TICKET_PROMPTS_ENABLED says, because prompts already sent still use the member mapping |
/ask | ASK_ENABLED is true and GEMINI_API_KEY is set. With either missing, a tag about a question gets no answer |
Message search and embeddings have no command of their own. Summaries and /ask use them behind the scenes.
Accepted time formats
Section titled “Accepted time formats”/hours, /reminders time, /interests digest, the time option of /summary-admin create and the clock-time forms of follow-up times all read the same clock formats. Input is trimmed and case does not matter.
| Form | Rule | Parses | Does not parse |
|---|---|---|---|
| 12-hour | 1 or 2 digits, optional : and 2 minute digits, optional space, then am or pm. Hour 1 to 12. | 9am, 9 am, 9AM, 5:30 pm, 12am (00:00), 12pm (12:00), 12:30am | 13pm, 0am, 13am |
| 24-hour with colon | 1 or 2 hour digits, :, exactly 2 minute digits. Hour up to 23, minute up to 59. | 09:00, 9:00, 23:59, 17:30 | 24:00, 25:00, 9:5, 9:75, 9:00:00 |
| Compact digits | 1 or 2 hour digits, then exactly 2 minute digits | 0900, 900, 1730 | 99999 |
A bare 9 does not parse. noon, abc, an empty value and seconds do not parse either. A bare four digit number such as 2026 reads as the time 20:26.
/whoami
Section titled “/whoami”Shows your saved profile. No options. Private reply.
You type
/whoami
Doge Bot replies
Name: Sam
Discord ID: 123456789012345678
Timezone: America/New_York
Working hours: 09:00 to 17:00
Only you can see this
Unset values show not set. Working hours show only when both start and end are saved.
/hours
Section titled “/hours”Saves your working hours and your timezone. Two subcommands. Both replies are private.
/hours set
Section titled “/hours set”Autocomplete on start and end offers up to 25 half-hour slots from 00:00 to 23:30, so 09 offers 09:00 and 09:30. 5pm shows no suggestion but is still accepted. Autocomplete on zone trims what you type, lower-cases it, turns spaces into underscores and offers up to 25 zone names that contain it, so new york finds America/New_York. It only suggests; an unknown zone gets the error below.
Start and end must differ after parsing, so 9am and 09:00 count as equal. If both are bad, only the start is named. Times are checked before the zone. When the end is earlier than the start, the reply adds (ends the next day). Hours are stored as HH:MM:00 and shown as HH:MM. To change only your timezone, run the command again with your current start and end and the new zone.
You type
/hours set start: 9am end: 5pm zone: America/New_York
Doge Bot replies
Working hours saved: 09:00 to 17:00 (America/New_York)
Only you can see this
You type
/hours set start: 22:00 end: 06:00 zone: UTC
Doge Bot replies
Working hours saved: 22:00 to 06:00 (ends the next day) (UTC)
Only you can see this
After saving, the bot checks your start-of-day channel reminders at once. If it sends you one, the reply gains a second line listing each channel as a mention:
You type
/hours set start: 9am end: 5pm zone: America/New_York
Doge Bot replies
Working hours saved: 09:00 to 17:00 (America/New_York)
You have not posted in <#123456789012345678> yet today, so I sent you a reminder.
Only you can see this
With two channels the channels are joined by , . With no reminder sent, the reply is the first line only, and a failed check never changes the reply. The check ignores the rule’s grace (its wait after the start of your day) and the late limit (REMINDER_LATE_LIMIT_MINUTES). It skips end-of-day rules, rules whose time for you (see /reminders time) is later than now, rules you turned off, disabled rules, members not on REMINDER_ALLOWLIST and reminders switched off (REMINDERS_ENABLED). It counts as that work day’s reminder, so repeating /hours set sends nothing more. See The reminder engine.
Errors:
| Cause | Reply |
|---|---|
zone sent blank (Discord normally blocks this) | I also need your timezone. Run /hours set again and fill in `zone`. Nothing was saved. |
zone is not a known timezone | "Mars/Olympus" is not a valid timezone. Pick one from the suggestions. (the value you typed is quoted) |
| A value does not parse | "noon" is not a time I understand. Try 9am, 9:30 or 17:00. (the offending value is quoted) |
| Start and end are the same time | Start and end must be different times. |
/hours clear
Section titled “/hours clear”Removes your working hours and keeps your timezone. No options. Works whether or not hours were set. It does not trigger the reminder check.
You type
/hours clear
Doge Bot replies
Working hours cleared.
Only you can see this
/follow
Section titled “/follow”Reminds you about a message at a time you choose. Private reply. The bot does not open the message, so it does not check that the message exists or that you can see it.
You type
/follow message: https://discord.com/channels/123456789012345678/200000000000000001/300000000000000002 when: in 2h note: Check the build
Doge Bot replies
Sure, I'll help you follow up on <https://discord.com/channels/123456789012345678/200000000000000001/300000000000000002> in 2 hours.
Only you can see this
The confirmation is fixed words, with no countdown. A relative when such as in 2h is repeated as in 2 hours. A clock time such as tomorrow 9am ends with at <t:1790000000:f>, which Discord shows as a date and time in your own timezone. The link has no preview.
Time formats for when
Section titled “Time formats for when”Input is trimmed and case does not matter.
| Form | Meaning | Example |
|---|---|---|
in <number> <unit> | That long from now. Units: s, sec, secs, second, seconds; m, min, mins, minute, minutes; h, hr, hrs, hour, hours; d, day, days. A day is 24 hours. Needs no timezone. | in 45s, in 30m, in 2 hours, in 3d |
| Clock time | The next time the clock reads that value in your timezone. If today’s time has passed, it means tomorrow. Needs a timezone. | 9am, 17:00, 1730 |
tomorrow <clock time> | That clock time on tomorrow’s date in your timezone. Needs a timezone. | tomorrow 9:30am |
Limits: at least 10 seconds ahead, at most 365 days ahead. A bare clock time does not skip weekends. in 1.5h, in 1 week, today 5pm, next monday and tomorrow on its own do not parse.
Time errors, shared by /follow, the picker form and the tag flow:
| Cause | Reply |
|---|---|
| Text not understood | I did not understand that time. Try "in 2h", "tomorrow 9am" or "9am". |
| Clock time but no timezone saved | Set your timezone with /hours set first, or use a relative time like "in 2h". |
| Less than 10 seconds ahead or in the past | That time is in the past. Pick a time at least 10 seconds from now. |
| More than 365 days ahead | That is more than a year away. Pick something sooner. |
Other errors:
| Cause | Reply |
|---|---|
| Link is not a message link from this server | That is not a message link from this server. Use "Copy Message Link" on a message here. |
| The follow-up rule is disabled | Follow-ups are switched off. |
The same follow-up twice (same message, same instant) keeps one reminder and shows the same confirmation. Different messages at the same instant are both kept.
Message menu: Remind me to follow up
Section titled “Message menu: Remind me to follow up”Right-click or long-press a message, choose Apps, then Remind me to follow up. Private reply with a picker.
You right-click a message and choose Apps >
Remind me to follow up
Doge Bot replies
When should I remind you to follow up on this message?
Only you can see this
The picker also holds a drop-down titled “When should I remind you?” with the presets below. The menu takes no note.
Presets
Section titled “Presets”| Preset | Shown when | Time |
|---|---|---|
| In 1 hour | Always | Now plus 1 hour |
| In 3 hours | Always | Now plus 3 hours |
Tomorrow HH:MM | A timezone is saved | Tomorrow’s date at your work start |
Next working day HH:MM | A timezone is saved | Tomorrow, moved forward past Saturday and Sunday, at your work start |
HH:MM is your saved work start, or 09:00 when no hours are saved. The last preset reads, for example, Next working day 09:00.
- On a Friday, Tomorrow is Saturday and Next working day is Monday.
In 1 hourandIn 3 hoursare counted from the moment you click.TomorrowandNext working dayuse the time fixed when the picker was posted. If that time has passed when you click, you get the time errorThat time is in the past. Pick a time at least 10 seconds from now.and the picker is removed.
Picker behaviour
Section titled “Picker behaviour”- Choosing a preset replaces the picker with the
/followconfirmation:in 3 hoursfor In 3 hours,at <t:...:f>for Tomorrow and Next working day. - Pick a time opens a form titled “Remind me to follow up” with one required field, “When”, hinting
in 30s, in 2h, tomorrow 9am, 9am. It takes the/followformats and replies with the confirmation or a time error. - Only the person the picker was made for can use it.
| Cause | Reply |
|---|---|
| Someone else clicks | This picker is not for you. |
| The picker’s message reference cannot be read | That reminder picker is no longer valid. |
| The chosen option cannot be read | That option is no longer available. |
| You have left the server (picker click or form) | You are no longer in the server, so I cannot set a reminder for you. |
| The fixed time of the chosen preset has passed | That time is in the past. Pick a time at least 10 seconds from now. |
| The follow-up rule is disabled | Follow-ups are switched off. |
| Unknown button or menu action | Unknown action. |
Tag the bot
Section titled “Tag the bot”Type the bot’s mention in a message. Gemini reads the message to decide whether it is a follow-up request, a question or neither, and for a follow-up whether you gave a time. A tag on a reply follows up on the message you replied to; a tag on a plain message follows up on that message. The reply to a follow-up request is public in the channel, pings nobody, and never repeats your message.
| Your message | The bot answers in the channel | And by direct message |
|---|---|---|
| A follow-up with a time the bot understands | Sure, I'll help you follow up on this in 2 hours. for a length of time, or Sure, I'll help you follow up on this at <t:1790000000:f>. for a clock time. The follow-up is saved at once. | Nothing |
| A follow-up with no time, or a time the bot could not read | Sure, I'll help you follow up on this. Check your DMs to pick a time. | The picker below |
| A follow-up with no usable time, and your DMs are closed | I could not DM you. Use /follow to pick a time. | Nothing |
| A follow-up with a clock time and no timezone saved | The matching time error below. Nothing is saved. | Nothing |
| A follow-up with a time in the past or over a year away | The matching time error below. Nothing is saved. | Nothing |
| A follow-up while the follow-up rule is disabled | Follow-ups are switched off. | Nothing |
| A question, while asking is switched on | A public reply to your message with the answer and the feedback buttons, see /ask. No follow-up is saved. | Nothing |
| A question over 500 characters, while asking is switched on | Keep questions under 500 characters, or use /ask. Once per member per hour; after that the bot only reacts with ⏳. | Nothing |
| A question while your last question is still being answered | A ⏳ reaction on your message. | Nothing |
| Anything else | Nothing | Nothing |
For a length of time the reply repeats the number and unit the model returned: in 1 second, in 30 seconds, in 1 hour. The unit is singular only for 1. For a clock time, Discord turns <t:...:f> into a date and time in your own timezone, such as “3 October 2026 at 09:00”. The picker is the one the message menu sends, and its link points to the message you replied to, or to your own message when it is not a reply.
You reply and tag the bot
@Doge Bot
Doge Bot sends you a DM
When should I remind you to follow up on <https://discord.com/channels/123456789012345678/200000000000000001/300000000000000002>?
The model returns the time as in N seconds, in N minutes, in N hours, in N days, tomorrow HH:MM or HH:MM, and the bot reads it with the /follow rules.
Fallbacks. The bot does not read the message when the AI is not set up, you have used 20 readings in the last hour, the server has used MENTION_MAX_CHECKS_PER_DAY readings in the last 24 hours, the call fails, or nothing is left of your message once the mention is removed. A tag on a reply then counts as a follow-up with no time, and any other tag is ignored. These fallbacks never produce a question answer.
The bot ignores your message when:
- it is in another server or a DM to the bot, or the author is a bot;
- it mentions
@everyoneor@here, or does not contain the literal mention text (the bot’s own role counts as a tag, because Discord offers it under the same name as the bot; any other role does not); - neither feature applies: a follow-up needs reminders switched on (
REMINDERS_ENABLED) and, whenREMINDER_ALLOWLISTis set, you on it; a question needs asking switched on (ASK_ENABLED) and ignores the allowlist.
If the bot cannot send messages in the channel, the follow-up is still saved and no confirmation appears. A question is answered only when the bot can view the channel, send messages there (in threads, send messages in threads), embed links and read the message history; otherwise it stays silent. The text of your message, without the mention, goes to Gemini. See What the bot stores.
Ticket prompt
Section titled “Ticket prompt”Not a slash command. When a post looks like a new feature idea and Linear has no matching ticket, the bot DMs the author a draft ticket. Only a submitted form creates a ticket. How the bot decides, and how it picks the team, assignee and labels: Ticket prompts. How members use it: Ticket prompts.
The prompt is sent only while TICKET_PROMPTS_ENABLED is true and both GEMINI_API_KEY and LINEAR_API_KEY are set. The buttons and the form keep working for prompts already sent while LINEAR_API_KEY is set. See Configuration.
The message
Section titled “The message”Doge Bot sends you a DM
Hi Sam, this sounds like a feature idea: https://discord.com/channels/123456789012345678/200000000000000001/300000000000000002
> Draft ticket: Add dark mode
Want a Linear ticket for it? You can edit it before anything is created.
Only you got this. I ask when a post looks like a new feature and Linear has no matching ticket, at most 3 times a day.
- The greeting is
Hiand your first name from your server display name. A blank name givesHi. - The link points to your message. The draft title is bold. The number in the last line is
TICKET_PROMPT_DAILY_CAP. - When Linear has related tickets,
These existing tickets look similar, check them first:and one line per ticket,- [IDENTIFIER](<url>) <title>, appear before theWant a Linear ticketline. Titles are cut to 80 characters and at most 3 are listed. If the message would pass 2000 characters, whole ticket lines are dropped from the end. - Mentions are off and link previews are suppressed.
- When the AI judges the idea a clear duplicate and names the existing ticket, no message is sent. If it says duplicate but names no ticket the search found, the prompt is sent with the first 3 tickets found listed as similar.
| Control | Kind | What it does |
|---|---|---|
Create ticket | Primary button | Opens the form |
No thanks | Secondary button | Closes the prompt |
Only the author can use the controls. Anyone else gets This prompt is not for you. There is no time limit on the buttons or the form.
Create ticket
Section titled “Create ticket”Opens a form. Discord allows 3 seconds for this. The bot gives Linear 2.5 seconds, minus the time already used, to return the team list, and waits at most 0.7 seconds for the cycle dates, which are only decoration.
| Cause | Reply |
|---|---|
| The prompt is open | The form opens |
| Linear has no team list in time | Linear is slow right now. Press Create ticket again in a moment. |
| Linear shows no public team | No Linear team is available. |
| A form was sent less than 2 minutes ago and is still being filed | Still creating that ticket. Give it a few seconds. The buttons stay. |
| The draft is gone: the message or its channel was deleted, or the bot started more than 30 days after the prompt | The prompt becomes Your original message was deleted, so I closed this prompt. with no buttons. The same text is shown in all three cases |
| The prompt is not open any more | The buttons are removed, then the status text below |
| A form was sent more than 2 minutes ago and never finished | The form opens again |
Status texts:
| Prompt state | Text |
|---|---|
| Ticket created | Already created: [IDENTIFIER](<url>). |
Dismissed with No thanks | You dismissed this one. |
| Closed without a ticket | This prompt is closed. Nothing was created. |
| Still open | This prompt is still open. Press Create ticket to try again. |
| Being filed | Still creating that ticket. Give it a few seconds. |
The form
Section titled “The form”The form is titled New Linear ticket. Fields in order: Team, Title, Description, Cycle.
Checks on submit, in order. The first one that fails ends it.
| Cause | Reply |
|---|---|
| The draft is gone: the message or its channel was deleted, or the bot started more than 30 days after the prompt | The prompt becomes Your original message was deleted, so I closed this prompt. |
| The title is blank | The ticket needs a title. Press Create ticket and add one. |
| Linear cannot return the team list | Linear is slow right now. Press Create ticket again in a moment. |
| The chosen team is not one of the teams offered to you now | That team is not available. Press Create ticket and choose another. |
| You have left the server | You are no longer in the server, so I cannot create this ticket. |
| A form is already being filed | Still creating that ticket. Give it a few seconds. |
| The prompt is already created, dismissed or closed | The matching status text above |
| The message was deleted while the form was being sent | The claim is released, nothing is filed, and the prompt becomes Your original message was deleted, so I closed this prompt. |
The prompt is marked as being filed (claimed) only after the first five checks pass, so a second press cannot start a second ticket.
What the bot creates in Linear:
- Team: the one you chose, or the only one offered. Title: your title.
- Assignee: your linked Linear user. When an admin never linked or unlinked you, the bot first tries to match your name exactly. Otherwise none.
- Labels: up to 3 that the model picks from the labels the team can already use, only when the AI is configured. The bot never creates a label. If the model fails, the ticket is created with no labels.
- Cycle: the current or next cycle of the team, when you chose one and the team has it. Otherwise the ticket is filed with no cycle and a line under it says why, for example
Engineering has no current cycle, so the ticket was filed without one. - Nothing else is set: no project, priority or state. Linear gives the team’s default state.
- If Linear refuses the assignee, labels or cycle as invalid, the bot tries once more without them. The ticket then reads
Filed inand gains a line such asLinear rejected some details, so it was filed without its assignee or labels.that names what had been sent. - Description: your description, a blank line,
---andProposed by <your display name> (Discord id <your id>) in Discord: <link to your message>. - The creator shown in Linear is the owner of
LINEAR_API_KEY, not you. - Linear gets 20 seconds per step. The ticket id is fixed before filing, so pressing
Create ticketagain after a failure never makes a second ticket.
On success the prompt is edited to show a link button and no other buttons. While filing, the prompt gains the line *Creating the ticket…* at its end and returns to its old text if filing fails.
Doge Bot sends you a DM
Ticket created: [ABC-9](<https://tracker.example/issue/ABC-9>) Add dark mode
From your message: https://discord.com/channels/123456789012345678/200000000000000001/300000000000000002
Assigned to you in Engineering · Cycle 5 (Oct 5–18).
The small-text line under the link is -# Assigned to you in <team name>. when the ticket was assigned to you, and -# Filed in <team name>. when it was not. When a cycle was set, · <cycle name> (<dates>) follows the team name. Team and cycle names are cut to 64 characters. Each note is added below as its own small-text line. When Linear did not confirm the details of a ticket that already existed from an earlier try, the line reads Linear did not confirm this ticket's details, so check them in Linear. and no notes follow.
The cycle notes are <team> does not use cycles, so the ticket was filed without one., <team> has no current cycle, so the ticket was filed without one., <team> has no next cycle, so the ticket was filed without one. and Could not read <team>'s cycles, so the ticket was filed without one.
On a failure, the bot answers privately and keeps your edited text.
| Cause | Reply |
|---|---|
| Linear did not answer in time | Linear did not answer in time, so I cannot tell yet whether the ticket was filed. Press Create ticket to check: it will not create a second one. |
| Linear rejected the ticket (key, permission or input) | Linear rejected the ticket, so nothing was filed. Tell an admin: the bot may lack permission for that team. |
| Any other failure, including a rate limit | Could not create the ticket in Linear, so nothing was filed. Your text is saved: press Create ticket to try again. |
No thanks
Section titled “No thanks”Closes the prompt and clears the draft. The prompt is edited and loses its buttons.
Doge Bot sends you a DM
No ticket created for Add dark mode
Your message: https://discord.com/channels/123456789012345678/200000000000000001/300000000000000002
I will not ask about that message again.
With no draft left the first line is No ticket created. A dismissed prompt still counts toward your daily limit. On a prompt that is no longer open, No thanks answers Still creating that ticket. Give it a few seconds. while a ticket is being filed, and otherwise removes the buttons and shows the matching status text above.
Other replies
Section titled “Other replies”| Cause | Reply |
|---|---|
LINEAR_API_KEY is not set (every control, including No thanks) | Ticket prompts are turned off. |
| No prompt matches the button, for example an old or edited button | This prompt has expired. Nothing was created. |
| Someone other than the author | This prompt is not for you. |
| Unknown action | Unknown action. |
When a prompt is sent
Section titled “When a prompt is sent”A prompt starts only from a new message in a channel the bot stores: text and announcement channels, public threads and forum posts. An edit, backfilled history, a DM, a private thread and the chat of a voice channel never start one.
| Rule | Value |
|---|---|
| Authors | Not bots. Everyone when REMINDER_ALLOWLIST is empty, otherwise only listed ids |
| Message types | Normal messages and replies |
| Length | At least 8 words. Code, links, emoji, mentions and tokens without a letter do not count |
| Per author, per rolling hour | 20 checks. Fixed (not a setting) |
| Checks waiting or running | At most 10 per author and 200 in total, 4 running at once. Fixed. A message over a limit is dropped and does not use up the author’s hourly allowance |
| Per author, per rolling 24 hours | TICKET_PROMPT_DAILY_CAP prompts, default 3, 1 to 50. Duplicates do not count |
| All members, per rolling 24 hours | TICKET_PROMPT_MAX_CHECKS_PER_DAY checks that reach the AI, default 2000, 1 to 100000 |
| AI unavailable | New checks pause for 60 seconds. Messages in that time are dropped |
| No public Linear team | No prompt is sent |
| Team suggestion | Only for a message judged a proposal: one more model call that sees the teams offered to the author (two or more, looked up within 1.5 seconds, skipped when slow) with their one-line descriptions. It answers with a team name, and only a name that matches exactly one listed team (accents and letter case ignored) counts. The suggestion only preselects the Team field and never files anything. A failure means no suggestion |
| One prompt per message | Yes. A message is never prompted twice, even after No thanks or a failed DM |
| Deleted message or channel | The draft is cleared and nothing is filed |
| Draft kept | Until the ticket is created, the prompt is dismissed or fails, the message or channel is deleted, or the bot next starts more than 30 days after the prompt |
If the bot cannot DM you, for example because your DMs are closed, you see nothing, and the prompt still counts toward your daily limit.
Meeting action items
Section titled “Meeting action items”Not a slash command. When a transcript upload or a voice meeting produces an action item that names you as owner, the bot DMs you your items. Only a press of Create selected (or Apply selected) creates or changes anything in Linear. How the bot decides: Meeting transcripts. How members use it: Meeting transcripts.
The message is sent only while MEETING_TRANSCRIPTS_ENABLED is true and GEMINI_API_KEY is set. The controls keep working for messages already sent; Create selected and the team drop-down need LINEAR_API_KEY. See Configuration.
When an owner’s DMs are closed, the upload reply or the /notes stop result says <names> could not get a DM (their DMs are closed), so their action items are only listed above.
The message
Section titled “The message”Doge Bot sends you a DM
Hi Alex, here are your action items from Weekly sync (see the summary).
- Draft the build checklist - this might already be ENG-12: Host menu mute. Check it before creating.
- Book the QA session
- Move ENG-9: Add blue crossbow to In Progress
Choose items, then press Create selected. Nothing is filed until you do.
- The greeting is
Hiand your first name from your server display name.see the summarylinks to the bot’s summary in the channel. - When an item had no clear owner,
Some of these had no clear owner, so they came to you.follows the first line. - Every item starts selected, so
Create selected (N)is enabled at once. - An item line is its number and title, cut to 100 characters.
- this might already be <ticket>. Check it before creating.follows when a ticket may cover it, and- already tracked as <ticket>when one surely does; that item cannot be selected. After you act, an item reads- created: <ticket>,- creating...,- dismissedor, for an item left unticked in a press that filed the rest,- not filed. - While a press works, the controls are disabled, the primary button reads
⏳ Creating…(⏳ Applying…for updates only) and the footer readsWorking on it, this takes a few seconds.Afterwards the buttons are removed and the last line isIt is created.,It is updated.orIt is created and updated. - An update item reads
Move <ticket> to <Status>orAdd a note to <ticket>, and after you act- applied: <ticket>,- noted: <ticket>,- applying...or- dismissed. An update with no matching ticket readsNote: <title> (no matching issue found, nothing to update)and is not selectable. - A ticket link reads
ID: title, with the whole link text cut to 70 characters. - When every open item is an update, the buttons are
Apply updateorApply selected (N), the drop-down placeholder isChoose the items to applyand the footer saysNothing is changed until you press .... - A
Cycledrop-down sits under the item drop-down while a new item is open. It is not in the example. - Mentions are off and link previews are suppressed. If the message would pass 2000 characters, whole item lines are dropped from the end and
-# N more not shownis added.
| Control | Kind | What it does |
|---|---|---|
Choose the items to create (Choose the items to apply for updates only) | Drop-down, up to 25 open items, all chosen at first. Update items are prefixed Update: | Selects which items to act on. Saves and refreshes the message |
Cycle | Drop-down with No cycle, Current cycle and Next cycle, one choice, No cycle at first | Sets the cycle for every open new item in the message, not for updates. Saved at once. Shown while a new item is open or being created |
Create selected (N) or Apply selected (N), Create ticket or Apply update for one item | Primary button | Files each selected new item as a Linear ticket and applies each selected update |
Dismiss all or Dismiss | Secondary button | Marks every open item dismissed |
The item drop-down shows only while two or more items are open. The buttons show while an item is open or being created. Only the owner can use the controls; anyone else gets These action items are not for you. There is no time limit.
Create selected
Section titled “Create selected”The bot first acknowledges the press, because Discord allows 3 seconds for that, then works.
| Cause | Reply |
|---|---|
There is no LINEAR_API_KEY (Create selected and the team drop-down; the other controls keep working) | Meeting tickets are turned off. |
| The meeting is not posted, has no row, or the button holds a broken id | This meeting is no longer available. Nothing was created. |
| The items are not yours | These action items are not for you. |
| Nothing is selected | Select at least one action item first. |
| You have left the server | You are no longer in the server, so I cannot create these tickets. |
| Linear cannot return the team list | Linear is slow right now. Try again in a moment. |
| Linear shows no team | No Linear team is available. |
| An item is already being filed | Still creating that ticket. Give it a few seconds. |
| The team needs a choice | A private message Which Linear team should these tickets go in? with a drop-down Choose a team. A team the bot suggested from the meeting is listed first with the description Suggested from the meeting |
| The team you chose is not offered to you | That team is not available. Pick another team. |
Linear rejected the ticket (auth or invalid) | Linear rejected the ticket, so nothing was filed. Tell an admin: the bot may lack permission for that team. |
| Linear did not answer in time | Linear did not answer in time, so I cannot tell yet whether the ticket was filed. Try again in a moment: it will not create a second one. |
| Another Linear error | Could not create the ticket in Linear, so nothing was filed. Try again in a moment. |
| A failure left items unfiled | 1 more item is still selected. or N more items are still selected. |
| An update and you have no admin-made Linear link | I could not update <ticket> because your Discord account is not linked to Linear yet. Ask an admin to run /linear-admin link for you. |
| An update and you are not on the ticket’s team | I could not update <ticket> because you are not on its Linear team. |
| The ticket for an update cannot be found or is in a private team | Could not find <ticket> in Linear, so nothing was changed. |
| The access check failed | Could not check your access in Linear, so nothing was changed. Try again in a moment. |
| Linear did not answer an update in time | Linear did not answer in time, so the update may or may not have been applied. Check the issue in Linear before trying again. |
Linear rejected an update (auth or invalid) | Linear rejected the update, so nothing was changed. Tell an admin: the bot may lack permission for that team. |
| Another Linear error on an update | Could not update the issue in Linear, so nothing was changed. Try again in a moment. |
Updates are applied first, before the team is looked at. Then the team is chosen in this order: the team the meeting named, when you are offered it; the only team offered to you; the team you pick in the drop-down, which is remembered for the meeting when it named none. The offered teams are your Linear teams when your Discord account is linked to a Linear user, and all public teams otherwise. When an admin never linked or unlinked you, your account is first matched to a Linear user by exact name.
What the bot creates in Linear, for each selected item:
- Team: as above. Title: the item title.
- Assignee: your linked Linear user, only for an item assigned to you. An item with no owner is unassigned.
- Labels: up to 3 that the model picks from the labels the team can already use. The bot never creates a label. If the model fails, the ticket is created with no labels.
- Project: the project the meeting named, only while it is still one of the chosen team’s projects.
- Cycle: the current or next cycle of the team, as set in the
Cycledrop-down. The choice stored on the item when the bot claims it wins, so a pick made while a press is working cannot be lost. - Nothing else is set: no priority or state.
- If Linear refuses the assignee, labels, project or cycle as invalid, the bot tries once more without them.
- Up to three tickets are filed at once. Any error stops new ones from starting.
- Description: the item description, a blank line,
---and a footer:From the meeting "<title>" in [Discord](<link to the summary>),Approved by [<your display name>](<link to your profile>)and, for an item with no assignee whose owner the meeting named,Owner in the meeting: <name>. The summary link has no angle brackets. - The creator shown in Linear is the owner of
LINEAR_API_KEY, not you. - The ticket id is fixed before filing, so pressing
Create selectedagain after a failure never makes a second ticket.
Updates
Section titled “Updates”An update item is applied before any new ticket in the same press. The person pressing needs an admin-made link (/linear-admin link; a name-matched link does not count) to a Linear user who is a member of the ticket’s team. Membership is read fresh each time. Refused or unverifiable updates take no claim and change nothing.
A successful update needs no message of its own: the item line reads - applied: <ticket> when the state was set or already there, and - noted: <ticket> when a comment was added. When the team has no matching state, the bot adds a comment instead and sends a private message: <ticket> noted (no "<Status>" state, so I added a note instead), with the ticket as a link.
The status is one of Backlog, Todo, In Progress or In Review, picked from the team’s own states. The bot never sets Done or Canceled. A comment reads Meeting note: <title>. <description>, or for a missing state The meeting suggested the status "<Status>", which this team has no matching state for., followed by the same --- footer as a ticket.
When the team is known, pressing Create selected edits the message to show - created: <ticket>. When you answered the team drop-down, that private message becomes Created <ticket> lines instead, and the original message is refreshed too when the bot can still find it.
Notes under the closed message
Section titled “Notes under the closed message”After a press that filed something, the message ends with small-text lines for what happened. Each cycle line covers every ticket that press filed with that choice.
| Line | When |
|---|---|
Filed in <team> · <cycle name> (<dates>). | Tickets went into the cycle. Ends , except <tickets>. when some were filed without details Linear rejected, or Linear did not confirm them |
<team> does not use cycles, so the ticket was filed without one. | The team has cycles switched off. With several tickets: the 3 tickets were filed without one. |
<team> has no current cycle, so the ticket was filed without one. | The choice was Current cycle and there is none |
<team> has no next cycle, so the ticket was filed without one. | The choice was Next cycle and there is none |
Could not read <team>'s cycles, so the ticket was filed without one. | Linear did not return the cycles |
Linear rejected some details, so it was filed without its assignee or labels. | The retry without those details ran. With several tickets it names them, or counts them, such as so 2 of 3 tickets were filed without their labels. |
Linear did not confirm the details of <tickets>, so check it in Linear. | A ticket was recovered by its id after an unknown outcome. check them for several |
/reminders
Section titled “/reminders”See and control your own reminders. A reminder here is a rule: a channel reminder that checks whether you posted, or the built-in follow-up rule behind /follow. Admins manage rules with /reminder-rules. Three subcommands. Everyone can use them and all replies are private.
The rule option autocompletes with enabled channel reminders only, sorted by name, up to 25. The follow-up rule is never offered.
For toggle and time, a rule that does not exist, is disabled or is the follow-up rule gets this reply:
You type
/reminders toggle rule: nope state: off
Doge Bot replies
There is no reminder called “nope”. Pick one from the suggestions.
Only you can see this
/reminders list
Section titled “/reminders list”Shows the enabled reminders that can message you. No options. Disabled rules are hidden. Sorted by name, cut at 2000 characters.
A channel line reads **name** (status): channel, timing, wait, attachment, where:
- status is
onoroff, with, HH:MMadded when you set your own time - channel is a channel link, or
not set - timing is
at the start of your work day,at the end of your work dayoron request - the rule’s grace (minutes to wait after that time) shows as
N min afteronly when it is more than 0 needs an attachmentappears only when the rule requires one
The follow-up rule shows as **follow-up**: on request with /follow.
You type
/reminders list
Doge Bot replies
follow-up: on request with /follow
standup (on): <#123456789012345678>, at the start of your work day, 120 min after
Only you can see this
With no enabled rules the reply is There are no reminders set up.
/reminders toggle
Section titled “/reminders toggle”Turns a reminder on or off for you only.
You type
/reminders toggle rule: standup state: off
Doge Bot replies
Reminder standup is now off for you.
Only you can see this
/reminders time
Section titled “/reminders time”Sets your own time for a reminder, or clears it.
You type
/reminders time rule: standup time: 9:30
Doge Bot replies
Reminder standup will now fire at 09:30 (your timezone).
Only you can see this
You type
/reminders time rule: standup time: clear
Doge Bot replies
Custom time for standup cleared. It follows your work hours again.
Only you can see this
A value that does not parse gets "noon" is not a time I understand. Try 9am, 9:30 or 17:00.
/reminder-rules
Section titled “/reminder-rules”Manage reminder rules: the channel watches that DM members who have not posted, and the built-in follow-up rule. Needs Manage Server and works only in a server. Discord hides it from members without the permission, and the bot checks again; without it the reply is You need Manage Server.
Five subcommands, all with private replies. The name option of edit, enable and disable autocompletes with all rules, enabled and disabled, including follow-up, sorted by name, up to 25. create has no autocomplete. There is no delete: rules are only disabled.
/reminder-rules list
Section titled “/reminder-rules list”Shows every rule, including disabled ones. No options. Sorted by name, cut at 2000 characters.
- A channel watch rule checks a channel for the member’s post. Channel watch line:
**name** (enabled|disabled) - channel watch - channel - anchor, with- +Nmadded when the wait is more than 0. - Follow-up line:
**name** (enabled|disabled) - follow-up. - Anchor is the point in the member’s work day the check counts from. It reads
start of work day,end of work dayoron request. A missing channel showsnot set.
You type
/reminder-rules list
Doge Bot replies
art-eod (disabled) - channel watch - not set - end of work day
follow-up (enabled) - follow-up
standup (enabled) - channel watch - <#123456789012345678> - start of work day - +120m
Only you can see this
With no rules the reply is There are no reminder rules.
/reminder-rules create
Section titled “/reminder-rules create”Creates a channel reminder rule. New rules are enabled.
You type
/reminder-rules create name: art-end-of-day channel: #art-updates anchor: End of work day grace: 30 attachment: True message: Time to post in {channel}. {previous}
Doge Bot replies
Rule created.
art-end-of-day (enabled)
Kind: channel watch
Channel: <#123456789012345678>
When: end of work day
Grace: 30 minutes
Needs an attachment: yes
Message: Time to post in {channel}. {previous}
Only you can see this
Errors:
| Cause | Reply |
|---|---|
Name is not 1 to 50 of a-z, 0-9, - | Rule names use lowercase letters, digits and dashes only, up to 50 characters. |
| A rule with that name exists | A rule named "art-end-of-day" already exists. |
/reminder-rules edit
Section titled “/reminder-rules edit”Changes a rule. Only the options you pass change. 0 for grace and false for attachment are real values and are applied.
The success reply is Rule updated., a blank line, then the same seven-line summary shown under create. The message line is cut at 300 characters.
Errors:
| Cause | Reply |
|---|---|
Only name passed | Nothing to change. Pass at least one option to edit. (checked before the rule is looked up) |
| No rule with that name | There is no rule named "nope". |
Anything but message on the follow-up rule | Follow-up rules only support editing the message. |
Follow-up message without {link} | The follow-up message must include {link}, or the reminder has nothing to open. |
/reminder-rules enable and disable
Section titled “/reminder-rules enable and disable”One option each.
You type
/reminder-rules disable name: art-eod
Doge Bot replies
Rule art-eod is now disabled.
Only you can see this
Enabling an enabled rule, or disabling a disabled one, repeats the success reply. An unknown name gets There is no rule named "nope". The follow-up rule cannot be enabled or disabled here and answers Follow-up rules only support editing the message.
Ask a question about what was said in the server. The reply is private unless you set public. The answer comes from messages and meetings you can see, with links to each source; Linear is not a source. How it works: Asking the bot questions. The member’s view: Asking the bot questions.
The reply is an embed (a boxed message) with the answer and linked sources, plus two buttons, 👍 Helpful and 👎 Not helpful, which only the asker can press. A tag question is answered like a public /ask: a reply to the tagging message, with typing shown meanwhile, nothing to press first and no expiry. With public: true, a text that is not an answer is removed from the channel and sent to you privately. In a tag it is a plain reply in the channel, once per member per hour; later refusals only get a ⏳ reaction. A tag is skipped, with no reply, when the bot cannot view the channel, send messages there, embed links or read the message history. The first four checks run before the bot starts on the answer, so their replies are private even for a public /ask. Checks run in this order:
| Cause | Reply |
|---|---|
GEMINI_API_KEY is not set | Asking is not set up yet. Ask an admin. |
| The question is only spaces | Ask a question. |
| You already have a question running | I am still answering your last question. |
| 4 questions already running | Busy right now, try again shortly. |
| You asked your limit in the last 24 hours | You have asked 50 questions in the last 24 hours. Try again later. The number is ASK_MAX_PER_MEMBER_PER_DAY |
| The server reached its limit | The daily question limit is reached. Try again later. |
| Used outside the server | This only works in the server. |
| Discord could not say which channels you (or, for a public answer, everyone) can view | I could not check which channels you can see right now. Try again in a minute. |
| You can search no channel or meeting, or a public answer has none open to its readers | I could not find anything you have access to search. |
| The model found nothing | The answer reads I could not find that in what I can search., or the model’s own short words saying what it could not find. An answer with no valid source counts as no answer |
| The search ran too long | That took too long to search. Try a shorter period or a more specific question. |
| The model failed | I could not answer that right now. Try again in a minute. |
From a tag, the texts for a failed answer, a search that ran too long, a channel list that could not be read and use outside the server end with Use /ask to try again.
The buttons
Section titled “The buttons”Feedback button ids are ask:fb:<id>:<userId>:up or :down, and the bot checks who presses. Buttons with the old ask:answer: id are retired.
| Cause | Reply |
|---|---|
| Someone other than the asker presses | This button is not for you. |
| The id cannot be read | That button is no longer valid. |
| An old Answer privately button | This button is no longer used. Ask with /ask or tag me. |
| Feedback saved | The answer’s buttons are removed and you get a private Thanks for the feedback. The answer text is not changed. |
| Feedback could not be saved | I could not record that. |
| Unknown action | Unknown action. |
The vote is stored with the question for as long as the record lasts.
/notes
Section titled “/notes”Takes notes of a voice call. How a meeting is written up: How voice notes work. How members use it: Voice notes.
Three subcommands, none with options. Every reply is private.
| Subcommand | What it does |
|---|---|
start | The bot joins the voice channel you are in, muted, and starts taking notes |
stop | Stops, and writes and posts the notes |
status | Shows whether notes are being taken |
/notes start
Section titled “/notes start”You type
/notes start
Doge Bot replies
I joined #team-sync and started taking notes. Run /notes stop when you are done and the summary will be posted.
Only you can see this
The channel is shown as a link. The bot also posts the consent notice in that voice channel’s text chat. The refusals are checked in this order:
| Cause | Reply |
|---|---|
| The bot’s voice part is not running (the reply is the same for any reason) | Voice notes are not enabled on this server. |
| You are not in a voice channel | Join a voice channel first, then run /notes start. |
| Notes are being taken, starting or wrapping up | I am already taking notes in #team-sync. Only one meeting at a time. The channel is another channel when you cannot see it |
| The bot lacks Connect, View Channel or Send Messages in that channel | Ask an admin to give me Connect, View Channel and Send Messages in that channel. |
| The bot could not look up the blocked channels (see /notes-admin) | I could not check this channel right now. Try again in a moment. |
| The channel is blocked and you do not have Manage Server | An admin has turned off notes in this channel. |
| The bot could not connect | I could not join that voice channel. Try again in a moment. |
| The notice could not be posted | I could not post the notice in the voice channel chat, so I did not start taking notes. Check my Send Messages permission there. |
| The connection dropped while joining | I lost the voice connection while joining. Try again in a moment. |
The consent notice is posted in the voice channel’s text chat before anything is transcribed. Its first line is **Taking notes**, started by <name>. The summary goes to <where>, visible to <who>. where <where> is the summary channel and <who> is everyone who can read that channel, or, when the voice channel is not open to everyone, this channel's chat and the people who can access this voice channel. It adds I created <channel> for the summaries. when the bot just created the summary channel, or I could not find or create the summary channel, so this meeting's summary stays in this chat. when it could not. The second line is small text: Everyone who speaks here is transcribed. Audio is not kept; the text is kept for N days and processed by the PlaySafe transcription service and AI. Leave the call to opt out; anyone in it can run /notes stop. N is MEETING_TRANSCRIPT_RETENTION_DAYS.
Start from an invite
Section titled “Start from an invite”Discord’s “Invite to voice” sends the bot a direct message with an invite link, and that also starts notes. The bot reacts with 👀, then ✅ or ❌, and replies to the message. Only a member who is in that voice channel and may use bot commands there can start notes this way, at most 5 times a minute per member. The refusals of /notes start apply, with these extra replies:
| Cause | Reply |
|---|---|
| The invite is not for a voice or stage channel of this server | That invite is not for a voice channel in this server. |
| You are not in that channel | Join that voice channel first, then send the invite again. |
| You may not use bot commands in that channel | You do not have permission to use bot commands in that channel. |
| It worked | I joined #team-sync and started taking notes. Run /notes stop in the server when you are done. |
Messages that carry no invite, or that are not direct messages, are ignored.
/notes stop
Section titled “/notes stop”Anyone in the call, the person who started the notes, or a member with Manage Server from anywhere. The reply is the result line, which is also posted in the voice chat.
| Cause | Reply |
|---|---|
| No notes are running | I am not taking notes right now. |
| The bot is still joining | Notes are still starting. Try again in a moment. |
| It is already finishing | The notes are already being wrapped up. |
| You are not in the call, did not start it and lack Manage Server | Only people in the call, the person who started the notes or someone with Manage Server can stop them. |
| It worked | Meeting notes posted in #ai-meeting-transcripts., with Some speech could not be transcribed. when part was missed, and the closed-DM line from the action items when an owner could not get a DM |
| Under 200 characters of text | There was too little speech (the transcript was too short), so no notes were posted. |
| Nothing could be transcribed | The transcription service was unavailable, so no notes were written. |
| The same meeting was already written | These notes were already posted. |
| The AI is unavailable | The AI service was unavailable, so the notes are not written yet. I kept what was said and will write them up automatically in a few minutes. |
| The server’s daily total is used up | The daily limit for meeting notes has been reached. Try again tomorrow. |
| The starter’s own daily limit is used up | You have reached your daily limit for meeting notes. Try again tomorrow. |
| The summary channel is not available | The meeting notes channel is not available. |
| Meeting notes are off | Meeting notes are turned off. |
| The write-up was interrupted | The notes were interrupted. or, at shutdown, What was said is saved and the notes will be finished when the bot is back. |
| Anything else | Something went wrong while writing the notes. |
Notes also stop on their own. The bot then posts the result line in the voice chat with a lead-in and DMs the same text to the person who started the notes, because nobody may be left to read the chat.
| Cause | Lead-in |
|---|---|
| Every person left the call | Everyone left, so I stopped taking notes. |
The call reached VOICE_NOTES_MAX_MINUTES | The maximum meeting length was reached, so I stopped taking notes. |
| The bot lost its voice connection or was moved out | I was disconnected from the voice channel, so I stopped taking notes. |
| The bot is shutting down | The bot is restarting, so I stopped taking notes. |
Once per session, when the transcription service keeps failing, the bot posts The transcription service is having trouble, so parts of this meeting may be missing from the notes. in the voice chat.
/notes status
Section titled “/notes status”| State | Reply |
|---|---|
| Nothing running | I am not taking notes right now. |
| Running in a channel you can see | Taking notes in #team-sync, started by @Sam since 12 minutes ago., with (joining) or (wrapping up) after the channel while it is starting or finishing |
| Running in a channel you cannot see | I am taking notes in a channel you cannot see. |
The mention shows the person’s name, and the time is Discord’s relative time. The mention does not ping.
/notes-admin
Section titled “/notes-admin”Manage where voice notes are allowed and where summaries go. Needs Manage Server and works only in a server. Discord hides it from members without the permission, and the bot checks again; without it the reply is You need Manage Server. Every reply is private. How it is used: Voice notes for admins.
| Subcommand | What it does |
|---|---|
exclude | Blocks notes in a voice or stage channel |
include | Allows notes there again |
list | Shows the blocked channels |
summary-channel set | Sets the name of the channel summaries and uploads use |
summary-channel show | Shows that name |
/notes-admin exclude and include
Section titled “/notes-admin exclude and include”| Command | Reply |
|---|---|
exclude | Notes are now blocked in #hr-room. or #hr-room is already excluded. Followed by The notes running there were stopped: <result line> when notes were running in that channel |
include | Notes are allowed again in #hr-room. or #hr-room was not excluded. |
Blocking is only checked when notes start. Blocked channels refuse members, and a member with Manage Server may still start notes there.
/notes-admin list
Section titled “/notes-admin list”No options. The reply is Notes are blocked in: and one channel link per line, oldest first. Whole lines are kept up to about 1900 characters, then ...and N more. With none it is No channels are excluded.
/notes-admin summary-channel set
Section titled “/notes-admin summary-channel set”| Cause | Reply |
|---|---|
| The name is not valid after that clean-up | That is not a valid channel name. Use letters, numbers, hyphens and underscores, up to 100 characters. |
| It could not be saved | I could not save the summary channel name. Try again in a moment. |
| A text channel with that name exists | The summary channel is now #team-meetings. A channel with that name already exists and will be used. The old channel is not moved or deleted. |
| None exists | The summary channel is now #team-meetings. A channel with that name does not exist yet; it will be created the first time someone starts voice notes. Transcript uploads are only read once it exists. The old channel is not moved or deleted. |
/notes-admin summary-channel show
Section titled “/notes-admin summary-channel show”No options. The reply is The summary channel is #team-meetings (set by an admin). or (the default), followed by The channel exists. or A channel with that name does not exist yet; it is created the first time someone starts voice notes.
/summary
Section titled “/summary”Gets a project summary. A summary is a named setup (called a config in the options) that says which Linear team to cover, how often, and who receives it. Everyone can see the command, but a given summary works only for its recipients and for members with Manage Server. How summaries are built and sent: Summaries.
/summary now
Section titled “/summary now”Writes a summary right now, for you only. Private reply. The bot reads only channels you can see yourself, so Manage Server does not widen what it uses.
Checks run in this order. The first one that fails ends the command.
| Cause | Reply |
|---|---|
| No summary with that name, it is disabled (also for Manage Server), or it is a personal digest | There is no summary called "nope". Pick one from the list that appears as you type. |
| You are not a recipient and do not have Manage Server | You are not a recipient of this summary. Ask an admin to add you with /summary-admin recipients add. |
GEMINI_API_KEY is not set | Summaries are not available: AI is not configured. |
| Used outside the server | This command only works in the server. |
| You asked less than 60 seconds ago | Please wait 42 seconds before asking for another summary. /summary now and /interests now share this limit. (the seconds left, rounded up) |
| 3 summaries are already being written | Busy right now, try again shortly. |
| The daily limit is used up | Daily summary limit reached, try again later. |
| None of the channels mapped to the team is visible to you | No channel mapped to this team is visible to you. Ask an admin to check /summary-admin list. |
| The model or Discord failed and nothing was sent | I could not write that summary right now. Nothing was sent; try again in a minute. |
You type
/summary now config: weekly-launch period: 7d
Doge Bot replies
weekly-launch - <t:1789900000:d> to <t:1790504800:d>
Launch build is stable and one review is waiting
Progress
- Release build passed on all targets
Blockers & risks
- Trailer approval is waiting on legal
Only you can see this
The first line is the summary name and the period. The headline and the items are written by the model, so your text will differ. When the model returns nothing usable, the headline reads No summary this time. The layout is fixed:
- Sections appear in this order, and empty ones are left out:
Progress,Blockers & risks,Decisions,Next. - The model writes at most 8 items per section.
Blockers & riskscan be longer, because the in-review tickets below are added after the model’s items. An item can end with links the bot built itself, in brackets:discordfor a message, or the Linear id for a ticket, for example(discord, PLAY-12). - With nothing to report,
No activity in this period.replaces the sections. - When Linear is connected, tickets that have been in review for 7 days or more are added at the end of
Blockers & risks. Each reads likePLAY-7 Fix shader is in review for 9 days, followed by its Linear link. The bot checks at most 30 tickets in review. If there are more, it adds the lineMore issues in review than could be checked.If Linear is not connected or the lookup fails, none are added. - The text is cut into pieces of at most 2000 characters. The first piece is the reply and the rest are private follow-up messages. Mentions are switched off.
Rules:
- The 60 second wait is per person and resets on restart. If nothing was sent, it is cleared.
- A summary can take up to 180 seconds to write.
- The daily limit is
SUMMARY_MAX_GENERATIONS_PER_DAY, counted per recipient over the last 24 hours across scheduled and on-demand summaries. Sent and failed summaries count, and so does a personal digest that matched nothing./interests nowuses the same limit. REMINDER_ALLOWLISTdoes not apply to/summary now. For summaries it limits only the scheduled DMs.- A summary is never posted in a channel.
/interests
Section titled “/interests”Follow people, topics and channels and get a personal digest. Every reply is private, and it only ever works on your own interests. How digests are built: Summaries. The member’s view: Interests.
An interest needs at least one of person, topic or a channel. You can have 10.
/interests add
Section titled “/interests add”| Cause | Reply |
|---|---|
| Success | Saved: <@person>, "topic", <#channel> (note: ...). Your digest is on: every weekday at 09:00 (Europe/London). Change it with /interests digest, or try /interests now. The digest part reads is paused when you paused it, and weekly on Friday for a weekly digest |
| Success, no timezone saved | Saved: .... Your digest is on: every weekday at 09:00, once you set a timezone. Change it with /interests digest. and a second line I need your timezone first. Run /hours set and fill in `zone`. |
| Topic or note is only spaces | The topic cannot be empty. Nothing was saved. or The note cannot be empty. Nothing was saved. |
| Same person, topic (any letter case), channels and note already saved | You already follow that. |
| None of person, topic or channel given | Pick at least one person, topic or channel. Nothing was saved. |
| You already have 10 | You can follow at most 10 interests. Remove one first. |
/interests list
Section titled “/interests list”Shows your interests, numbered. With none: You are not following anything yet. Add one with /interests add.
/interests edit
Section titled “/interests edit”Takes interest (required, autocomplete over your own interests, labelled by number) and the same options as add. Only the options you give change, and giving channels replaces the channel list. A person, topic or note cannot be cleared this way, only replaced. Replies Updated: <description>. With none given: Nothing to change. Provide at least one option. An interest that is not yours gets That interest was not found. A change that makes it the same as another interest of yours gets You already follow that.
/interests remove
Section titled “/interests remove”Takes interest (required, autocomplete). Deletes it. Replies Removed. or That interest was not found.
/interests digest
Section titled “/interests digest”Needs a timezone. Without one: I need your timezone first. Run /hours set and fill in `zone`. Creates your digest on first use (every weekday, 09:00, on). An option you leave out keeps its current value.
Replies Your digest is on: every weekday at 09:00 (Europe/London). (weekly on Friday at 09:00 (Europe/London) for a weekly digest) or Your digest is paused. It was set for every weekday at 09:00 (Europe/London). The checks run in this order: timezone, then the time (I could not read that time. Try 9am or 09:00.), then a weekly cadence with no weekday. A schedule the bot refuses, such as a weekday given for an every-weekday digest, answers with the reason and Your digest schedule was not changed., for example Weekday only applies to weekly summaries. Your digest schedule was not changed.
/interests now
Section titled “/interests now”Writes a digest of the last 24 hours for you only. Needs a timezone. Checks run in this order:
| Cause | Reply |
|---|---|
| No timezone saved | I need your timezone first. Run /hours set and fill in `zone`. |
GEMINI_API_KEY is not set | Summaries are not available: AI is not configured. |
| Used outside the server | This command only works in the server. |
| Asked less than 60 seconds ago | Please wait 42 seconds before asking for another summary. /summary now and /interests now share this limit. |
| 3 summaries already being written | Busy right now, try again shortly. |
| You have no interests | Add an interest first with /interests add. |
You already ran /interests now 5 times in the last 24 hours (/summary now does not count) | You can ask for 5 on-demand digests per day. Try again later or wait for your digest. |
| The daily limit is used up | Daily summary limit reached, try again later. |
| You can see none of the channels the bot stores | I could not find any channels you can view right now. |
| Nothing matched | Nothing matched your interests in the last 24 hours. |
| The model failed and nothing was sent | I could not write that summary right now. Nothing was sent; try again in a minute. |
The reply is cut into pieces of at most 2000 characters, like /summary now. A request that matched nothing still counts toward the daily limit. Once a request passes the checks above, the 60 second wait stays even when the request fails. If the digest ends with nothing sent and no reason, the reply is Something went wrong, try again in a minute.
/summary-admin
Section titled “/summary-admin”Manage project summaries (the named setups called configs). Needs Manage Server and works only in a server. Discord hides it from members without the permission, and the bot checks again; without it the reply is You need Manage Server.
Nine subcommands. Every reply is private. Autocomplete answers with an empty list for anyone without Manage Server.
| Subcommand | What it does |
|---|---|
list | Shows every summary |
create | Creates a summary |
prompt | Sets what the summary should emphasise |
recipients add | Adds a person or role as a recipient |
recipients remove | Removes a person or role |
map-channel | Maps a channel to a Linear team |
unmap-channel | Removes a channel mapping |
enable, disable | Turns a summary on or off |
The config option of prompt, recipients and enable and disable autocompletes with all summaries, enabled and disabled, filtered by what you type, up to 25. The team option autocompletes with Linear teams as Name (KEY), up to 25, and the project option with the projects of the team already chosen in the same command. Both are empty when no Linear key is set.
There is no delete subcommand, and no way to change cadence, weekday, time, description, team or project after creating a summary. The review status (In Review) and the 7 day review flag have no command. To change one of the fixed settings, create a new summary and disable the old one.
Error shared by the subcommands that take a config (prompt, recipients add, recipients remove, enable, disable):
| Cause | Reply |
|---|---|
| No summary with that name | There is no summary called "nope". |
The name is a personal digest (interests- and an id) | Personal digests are managed with /interests. (for prompt, this arrives after the form is sent) |
/summary-admin list
Section titled “/summary-admin list”Shows every summary, including disabled ones. No options. Sorted by name. Whole lines are kept up to about 1950 characters, then ...and N more closes the list.
A line reads **name** (enabled|disabled) - cadence [Weekday] HH:MM in each recipient's timezone - team label - N recipients - N channels. The cadence is shown as stored: daily, weekly or on_demand. The weekday shows only when one is set. The team label is Name (KEY), or a Linear team when Linear cannot name it. 1 recipient and 1 channel are singular. The recipient count is the people and roles added, so a role counts once. The channel count includes the threads and forum posts under each mapped channel. A team with no mapped channel reads 0 channels (unmapped).
You type
/summary-admin list
Doge Bot replies
art-daily (disabled) - daily 09:00 in each recipient’s timezone - team Art (ART) - 1 recipient - 0 channels (unmapped)
weekly-launch (enabled) - weekly Friday 09:00 in each recipient’s timezone - team Launch (LCH) - 2 recipients - 3 channels
Only you can see this
With none the reply is There are no summaries.
/summary-admin create
Section titled “/summary-admin create”Creates a summary. New summaries are enabled, have no prompt, and look at tickets in the state In Review.
You type
/summary-admin create name: weekly-launch team: Launch (LCH) cadence: weekly weekday: Friday time: 9am
Doge Bot replies
Created summary weekly-launch (weekly Friday 09:00 in each recipient’s timezone, team Launch (LCH)). Set its prompt with /summary-admin prompt and add recipients with /summary-admin recipients add.
Only you can see this
Errors:
| Cause | Reply |
|---|---|
Name is not 1 to 50 of a-z, 0-9, - | Config names use lowercase letters, digits and dashes only, up to 50 characters. |
time does not parse | I could not read that time. Try 09:00, 9:30am or 1730. |
| The team is not one of the Linear teams | Pick a team from the list. |
| No Linear key is set | Linear is not connected, so I cannot validate the team. Ask an admin to set LINEAR_API_KEY. |
weekly without weekday | Pick a weekday for weekly summaries. |
weekday with daily or on_demand | Weekday only applies to weekly summaries. |
project is not a valid id | Linear project id is invalid. |
| Team id is not a valid id | Linear team id is invalid. |
The name starts with interests- | Config names starting with interests- are reserved for personal digests. |
| A summary with that name exists | There is already a summary called "weekly-launch". |
If Linear fails for any other reason, the team is not checked against Linear. The value must still be 1 to 64 letters, digits, dashes or underscores, or the reply is Linear team id is invalid. This is the only case where that reply appears.
/summary-admin prompt
Section titled “/summary-admin prompt”Opens a form to edit what the summary should emphasise.
The form is titled Prompt for <name> (cut to 45 characters). It has one paragraph field, Summary prompt, optional, up to 2000 characters, with the placeholder Optional: what to emphasise, e.g. launch blockers and release risk. The field starts with the current prompt. Only the person who opened the form can send it.
| Cause | Reply |
|---|---|
| Saved with text | Prompt updated for weekly-launch. |
| Saved empty | Prompt cleared for weekly-launch. |
| Someone else sends the form | This form is not for you. |
| The sender lost Manage Server | You need Manage Server. |
| No summary with that name (before the form opens) | There is no summary called "nope". |
/summary-admin recipients add and remove
Section titled “/summary-admin recipients add and remove”A recipient gets the scheduled DM and may run /summary now for that summary. A role covers everyone who holds it when the summary is sent.
You type
/summary-admin recipients add config: weekly-launch user: @Sam
Doge Bot replies
Added <@123456789012345678> to weekly-launch.
Only you can see this
| Cause | Reply |
|---|---|
add, person | Added <@123456789012345678> to weekly-launch. |
add, role | Added <@&123456789012345678> to weekly-launch. |
add, person with no saved timezone | The reply above, then They have no timezone set, so they will not get scheduled summaries until they set one with /hours set. |
add, already a recipient | <@123456789012345678> is already a recipient of weekly-launch. |
remove | Removed <@123456789012345678> from weekly-launch. |
remove, not a recipient | <@123456789012345678> was not a recipient of weekly-launch. |
Neither or both of user and role | Pick exactly one of user or role. |
A summary can have the same person or role only once.
/summary-admin map-channel
Section titled “/summary-admin map-channel”Maps a channel to a Linear team. Every summary on that team reads the channels mapped to it, plus the threads and forum posts under them. A channel maps to one team at most.
You type
/summary-admin map-channel channel: #launch team: Launch (LCH)
Doge Bot replies
Mapped <#123456789012345678> to Launch (LCH).
Only you can see this
| Cause | Reply |
|---|---|
| The bot has not stored the channel yet | That channel has not been indexed yet. Try again after the backfill has seen it. The backfill is the bot’s pass that reads and stores channel history. |
| Team problems | The same replies as create: Pick a team from the list., the Linear-not-connected text, or Linear team id is invalid. when Linear fails for another reason and the value is not a valid id |
/summary-admin unmap-channel
Section titled “/summary-admin unmap-channel”Removes a channel mapping.
Replies Unmapped <#123456789012345678>. or <#123456789012345678> was not mapped.
/summary-admin enable and disable
Section titled “/summary-admin enable and disable”One option each: config (required, autocompletes).
You type
/summary-admin disable config: art-daily
Doge Bot replies
art-daily is now disabled.
Only you can see this
The reply is <name> is now enabled. or <name> is now disabled. and repeats if nothing changed. A disabled summary is skipped by the scheduler, hidden from /summary now autocomplete and refused by /summary now, even for Manage Server.
/linear-admin
Section titled “/linear-admin”Link Discord members to Linear users, which decides the team and the assignee of their tickets. Needs Manage Server and works only in a server. Discord hides it from members without the permission, and the bot checks again; without it the reply is You need Manage Server.
Four subcommands. Every reply is private, and no reply pings anyone. If Linear does not answer, link, list and sync reply Could not reach Linear. Try again in a moment. unlink never calls Linear. The bot also links members by exact name on its own: see Linking members to Linear.
| Subcommand | What it does |
|---|---|
link | Links one member to one Linear user and stops name matching for that member |
unlink | Removes the link and stops name matching for that member |
list | Matches by name, then shows who is linked, unsure or not matched |
sync | The same as list, with a first line saying how many were matched |
/linear-admin link
Section titled “/linear-admin link”You type
/linear-admin link member: @Sam linear_user: Sam Rivera
Doge Bot replies
Linked <@123456789012345678> to Linear user Sam Rivera. Their tickets go to: Engineering, Tools.
Only you can see this
| Cause | Reply |
|---|---|
| The Linear user is on no team | Linked <@123456789012345678> to Linear user **Sam Rivera**. They are not on any Linear team, so they choose from all public teams. |
| The team lookup fails after the link was saved | Linked <@123456789012345678> to Linear user **Sam Rivera**. |
| The value is not one of the Linear users | Pick a Linear user from the list. |
| Another member already holds that Linear user | That Linear user is already linked to <@234567890123456789>. (That Linear user is already linked to another member. when that member is no longer listed) |
The link is saved as a manual decision, so name matching never changes it. Linking a member who is already linked replaces their link. If the bot has no record of the member yet, it saves one first.
/linear-admin unlink
Section titled “/linear-admin unlink”| Cause | Reply |
|---|---|
| The member was linked | Unlinked <@123456789012345678>. |
| The member had no link, or the bot has no record of them | <@123456789012345678> was not linked. |
When the bot has a record of the member, unlinking marks them as decided by an admin, even if they had no link, so name matching skips them from then on. Use link to give them a link again.
/linear-admin list
Section titled “/linear-admin list”No options. First the bot runs the name match, so the report is current. Then it shows four sections, in this order. A section with nothing in it still shows its heading with (0).
| Section | What it holds |
|---|---|
Linked (N) | One line per linked member: <@123456789012345678> - Sam Rivera, with (matched by name) added when the bot made the link. Reads a Linear user when the Linear user is no longer in the active list |
Unsure (N) | <@123456789012345678> - could be: Sam Rivera, Sam Rivers. Up to 3 names. These need link |
No match (N) | The members with no candidate, as mentions. Up to 20, then and K more |
Not matched on purpose (N) | Members an admin unlinked, as mentions |
You type
/linear-admin list
Doge Bot replies
Linked (2)
<@123456789012345678> - Sam Rivera (matched by name)
<@234567890123456789> - Alex Doe
Unsure (1)
<@345678901234567890> - could be: Jo Lee, Jo Leigh
No match (1)
<@456789012345678901>
Not matched on purpose (0)
Only you can see this
Whole lines are kept up to about 1950 characters, then ...and N more lines closes the report.
/linear-admin sync
Section titled “/linear-admin sync”No options. It runs the same name match and shows the same report as list, with one line first.
You type
/linear-admin sync
Doge Bot replies
Matched 2 members by name.
Linked (2)
…
Only you can see this
The line reads Matched N members by name. with the number of members linked by this run. list runs the match too but does not show the line.
- How rules behave over time: Reminder rules.
- How members use them: Channel reminders and Follow-ups.
- Summaries: Summary configs, Summaries and How summaries work.
- Linking members to Linear users: Linking members to Linear.