Erbot is an emacs-lisp irc bot. Main instances are fsbot on #emacs and other software channels on freenode; and donald-bot on #latex.

Most of the erbot-docs below are a bit dated (by about two decades). The ErbotParsing section is freshly revamped in 2019. For current help, PM fsbot on freenode and type ,help. -deego, 2019

Other sections available:


Bots reacts to an initial comma. Here is a usage example. As you can see, the same easy syntax is used for querying as well as to define terms:

    <lurwas> , clog
    <fsbot> BEEEEEP...Try search or search-wide on clog
    <lurwas> , clog is a channel logger
    <fsbot> Done (create clog )
    <kensanata> , clog
    <fsbot> clog is, like, a channel logger
    <deego> , clog is also temporary-string
    <fsbot> Added entry to term "clog"
    <deego> , clog
    <fsbot> I think clog is [0] a channel logger
    <fsbot> [1] temporary-string
    <deego> , forget clog 1
    <fsbot> Removed entry 1 of clog
    <deego> , clog
    <fsbot> I think clog is a channel logger

The above fuzzy “english” syntax is just a front-end to an accurate lisp syntax which can also be used instead.

The bots can do elisp, as well:

    <deego> fsbot: (+ 2 3 (expt 4 5))
    <fsbot> 1029
    <deego> , (let ((i 0) (b 0)) (while (< i 1000) (setq i (+ i 1) b (+ b
                   (fs-random-choose '(0 2))))) b)
     <fsbot> 984
    <deego> (progn (let ((j 0)) (dotimes (i 10) (setq j (+ j i))) j))
    <singbot> 45

Start your private investigation:

    /query fsbot

When talking privately, you can skip the initial comma, as above.


Each TERM can have one or more ENTRIES. That TERM is internally stored as a bbdb-name, and the ENTRIES are formatted as a list and stored in the corresponding bbdb-notes. As of December 2002, fsbot has 1600 terms, a full 1200 of which contain references to

Deego feeds fsbot with the index of all new pages on Community wikiand EmacsWiki. All pagenames are terms in the fsbot database.

Searching: search and search-wide

Searching for regular expressions amongst the terms:


    <deego> fsbot: search foo.*bar
    <fsbot> ...

Searching for regular expressions amongst the terms and their entries:

    <deego> fsbot: search-wide foo$
    <fsbot> ...

If a search yields exactly one match, fsbot goes ahead and shows it.


Here are some equivalent ways to ask for description of a term:

    <deego> , describe emacschannel
    <fsbot> deego: EmacsChannel may be at
    <deego> , (describe "emacschannel")
    <fsbot> deego: hmm, EmacsChannel is at

In fact, all the rest are converted to the last form. (See lispify). The most common way to ask for a description, however, is to simply type the term:

    <deego> , emacschannel
    <fsbot> I think EmacsChannel is at

Asking the bot to describe a term this way calls a function ‘describe-internal’ which tries a lot of other “smartly structured” fallback operations and searches to return you some info if the exact term is not found … Boring details: The bot searches for the term in its database in several exceedingly more permissive ways. If it doesn’t find anything, it goes to google for help (but often attaches a channel-specific extra term when googling). If that fails too, it just tries to answer your query by looking for common English terms in your statement like “thank you”. If that also fails, the bot resorts (weighted) randomly to one of several things on your query: doctor (psychoanalysis), fortune, yow, a small flame, spook, etc.

You can also search for multiple words:

    <deego> fsbot: foo bar baz
    <fsbot> ...

This amounts to searching for foo.*bar.*baz – ie. the order of the terms is important.


    <kensanata> , ff ignore
    <fsbot> (defun ignore (&rest ignore)
    <fsbot>   (interactive)
    <fsbot>   nil)
    <kensanata> , a bbdb-ignore
    <fsbot> 6 matches.  (bbdb-ignore-most-messages-alist

Parsing/Lispification and Lisp interpreter

See ErbotParsing

Fsbot has interfaces to many other Emacs help facilities, see section ErbotEmacs Help above.

Merging, moving, copying and forgetting terms

Use commands like cp, mv, merge, forget (= rm) for manipulating terms. Merge merges the entries of first term it is given, into the second term.

    <deego> , foo
    <fsbot> From memory, foo is bar
    <deego> , cp foo fool
    <fsbot> Copied entries of foo to fool
    <deego> , fool
    <fsbot> From memory, fool is bar

Using no instead of forget

    <deego> , foo is bar
    <fsbot> created.
    <deego> , no foo is baz
    <fsbot> created.
    <fsbot> , foo
    <fsbot> Perhaps foo is baz

Moving entries around within terms

    <deego> , tmpfoo
    <fsbot> Perhaps tmpfoo is [0] a
    <fsbot> [1] b
    <deego> , 1->0 in tmpfoo
    <fsbot> Moved entry 1 to 0 in "tmpfoo"
    <deego> , tmpfoo
    <fsbot> tmpfoo - [0] b
    <fsbot> [1] a

String-replace and regexp-replace in terms

With foo being baz as before, let’s string-replace:

    <deego> , s/baz/newstring/ in foo                                        
    <fsbot> Replaced string "baz" with "newstring".
    <deego> , foo                                                           
    <fsbot> Perhaps foo is newstring

Now, a regexp-replace

    <deego> , r/^new/old/ in foo                                            
    <fsbot> Replaced regexp "^new" with "old"

The last / can optionally be skipped. For a literal /, either try using //, or try using real lisp instead of English for really complicated entries. (To find lisp renditions of English stuff, see lispify).

Entries Starting With Special Keywords

If the first entry of a single-entry term starts with one of ‘(“lisp” “redirect” “unecho” “function” “directonly”), that term has a special meaning. Using describe-literally (dl) instead of describe can turn off these special interpretations.


In this case, fsbot evals the expression that follows “lisp”.

    <deego> , tmprandom is lisp (random 3)
    <fsbot> created.
    <deego> , tmprandom
    <fsbot> 2

Yes, fsbot has an eval:

    <deego> , (eval '(+ pi (string-to-number emacs-version)))
    <fsbot> 24.141592653589793

If the lisp form finally results in the symbol ‘noreply, then the bot doesnt’ reply to the channel at all. The lisp expression understands arguments, labeled by lispa, lispb, lispc, lispd, lispe and lispargs for all its arguments.

For example,

 <deego> ,tmpfoo is lisp (+ lispa lispb (apply  '+ lispargs))
 <fsbot> created.
 <deego> ,tmpfoo 1 2 3 4
 <fsbot> 13

Of course, if you want to use lisp expressions with arguments, the better way remains using a defun rather than creating entries like those above.

 <deego> ,(defun tmpfoo (&rest args) (apply '+  args))
 <fsbot> fs-tmpfoo
 <deego> ,tmpfoo 1 2 3 4
 <fsbot> 10

Or, a more interesting example:

<kensanata> forget channel-wisdom
<fsbot> Forgot "channel-wisdom" which had one note:  ["redirect shit#emacssays"]
<kensanata> (defun channel-wisdom (&rest args) (concat "Shut up, " nick "!"))
<fsbot> fs-channel-wisdom  ..(symbol)
<kensanata> channel-wisdom
<fsbot> Shut up, kensanata!

More code:

<kensanata> which\\sis\\sbetter:\\S is lisp (let ((it nil) (in
    (mapcar 'symbol-name (nthcdr 2 lispargs)))) (while in (unless (string=
    (car in) "or") (setq it (cons (car in) it))) (setq in (cdr in))) (if it
    (random-choice it) "Or what?"))
<fsbot> Created new note for "which\\\\sis\\\\sbetter:\\\\S"
<kensanata> which is better: toast, bread, croissant or jam
<fsbot> jam

Or fancy output, and showing how to describe such terms:

<kensanata> dl how\\scool\\sis\\s\\S
<fsbot> From memory, how\scool\sis\s\S is lisp (let ((i (random 10)))
    (format "|%s%s| %d%%" (substring "**********" 0 i) (substring
    "----------" i) (* 10 i)))
<kensanata> how cool is emacs
<fsbot> |*****-----| 50%


    <deego> , shae
    <fsbot> [->] ShaeErisson is [0] at
    <fsbot> [1] Nick: shapr
    <deego> , dl shae
    <fsbot> shae may be redirect shaeerisson


This will allow users to create their own functions. This is not yet functional. Entries here can be either set using the usual , foo is function (lambda ()...) , or using the soon-to-come fsbot command defun. fsbot also has funcall and apply, but they are broken as of this writing.

This feature will probably never be implemented, nor is it needed any more, since the bots can now parse (defun…)… See ErbotEmacs.


You can have entries that fsbot does not prefix with his usual mumbling. Just use ‘noecho’ or ‘unecho’ as the first word.


    <kensanata> , ni! is noecho NI! NI! NI! NI!
    <fsbot> created.
    <kensanata> fsbot: ni!
    <fsbot> NI! NI! NI! NI!

You can, of course, see the full stuff by asking it to describe-literally:

    <deego> fsbot: dl ni!
    <fsbot> deego, From memory, ni! is noecho NI! NI! NI! NI!


Yeah, this is a boring subsection. Feel free to skip it 😊

Background:In many channels (channels that match a regexp), fsbot responds not just to questions asked of it, but also responds briefly to any single word queries, if the query hits an exact match in its database. This is generally very useful, people often (accidentally) get their questions answered that way.

 <deego> iirc?								
 <fsbot> IIRC is like, an acronym for "If I recall correctly"
 <deego> gnus?
 <hbot> hmm, gnus is Gnus is the Emacs newsreader--- http:/ It also reads mail, Slashdot, and your mind. .. + more entries

However, sometimes that is not the intention. Say, you want to teach it what WTF means yet you do not want it to barge in with explanation of WTF whenever someone says WTF to another person. Here’s an example:

 <deego> ... (Something very silly) ...
 <bpt> WTF?
 <fsbot> bpt: WTF is What the fuck.
 <bpt> I know that you silly bot!

In that case, you teach the bot something different:

 <deego> fsbot: WTF is directonly What the Fuck.

When the first letter is directonly, fsbot will not reply to single question-mark queries. This directonly can be followed by the other usual entries.

 <deego> fsbot: foo is directonly lisp (+ 1 2)
 <deego> , foo
 <fsbot> 3


Syntax: , g[oogle] [number] WORD [MORE-WORDS]

    <deego> , google pcomplete
    <fsbot> [google]

Yes, googling has a timeout built into it. The bot has timeout built into it at various places in various functions and in the overall parsing.

Multiple google results:

 <deego> , g 2 emacs						
 <fsbot> [google]

You can also Google for words restricted to the EmacsWiki site:

    <deego> , ge dumpkeys
    <fsbot> [google]

Similar functions exist for a few other sites: ge – google-emacswiki gt --google-twiki gg – google-gnufans-net ggo – google-gnufans-org gu – google-usemod gw – gogole-wikipedia

The form below also happens to work, even though we didn’t prefix it with g or ge:

    <deego> , pcomplete
    <fsbot> [google]

Here’s what happened, if i remember the chronology correctly: fsbot tried to look for the term, then it tried searching for the regexp*pcomplete, then it tried to search-wide for the regexp*pcomplete, then it tried to parse your message as an english message looking for words like “thank you” etc. Finally, it gave up and went to google. If this googling would not have returned anything within the allotted time, or gives 0 results, fsbot first tries to parse your message as an english message (looking for words like “thank you”), and if that fails, does some funny default thing: which includes things like:

Talking to people as well as the bot

If a sentence is not addressed to the bot, but has ,, in the middle of it, the bot responds to the part of the sentence starting with ,,

    <resolve> probably best off with ,, categoryoutline
    <fsbot> I heard CategoryOutline is at\CategoryOutline

A second pair of ,, can terminate the input to the bot.

Embedding Question marks (?)

You cannot include a (single) question mark at the end of the answer, because the last question mark is stripped away (that behavior is useful for many many other cases).


    <deego> , foo is why do you say foo?
    <fsbot> created
    <deego> foo
    <fsbot> why do you say foo

You can use the internal set-term function, however, if you know what you are doing.


    <kensanata> , (set-term "why" "Why not?")
    <fsbot> created.
    <kensanata> why?
    <fsbot> why -- Why not?
    <Johbe> wohoo!

Or you could just end the sentence with 2 question marks.


Karma is currently unavailable.

Here’s older info:

Karma started out just for fun, but following another of DamienElmes’ awesome suggestions, it is now also used by the bot to automatically track a TERM’s popularity..

Karma is used both for terms as well as nicks or any other entries people care to assign karma to. For each direct reference to a Term the bot increases the term’s karma slightly (by 0.1). Subsequently, when a certain input by the user would result in multiple term matches, the Term with the highest karma gets displayed (the user also gets a list of the other possible terms..). You can also change karma of anything:

As you can see, users have much more influence over karma than the automatic increments. Thus, if you think a particular Term is more relevant than another similarly named term, just increase its karma.

Karma is case-insensitive and everything gets downcased.

Most of this karma stuff is not functional right now… This was just the new design for the overhauled karma, whenever that becomes functional. 😊


 <deego> , country .jp
 *fsbot* Japan

#dunnet and dunnet-mode

NOTE: the bots’ DUNNET is broken ATM.

You can enable dunnet-mode in any channel, but we recommend doing that only on #dunnet. Here is how to enable it:

    *** Topic for #dunnet: you are in a twisty little maze of passages all alike
    *** #dunnet: topic set by smoke, 07:31:48 11/29/02
    <deego> , (dunnet-mode)
    <fsbot> Dunnet mode set to t.  To toggle, type , (dunnet-mode)
    <deego> , look
    <fsbot> Dead end
    <fsbot> You are at a dead end of a dirt road.  The road goes to the east.
    <fsbot> In the distance you can see that it will eventually fork off.  The
    <fsbot> trees here are very tall royal palms, and they are spaced equidistant
    <fsbot> from each other.
    <fsbot> There is a shovel here.
    <deego> , take shovel
    <fsbot> Taken.  

You can also play dunnet without enabling dunnet-mode:

    <deego> , dunnet go east
    <fsbot> E/W Dirt road
    <fsbot> You are on the continuation of a dirt road.  There are more trees on
    <fsbot> both sides of you.  The road continues to the east and west.
    <fsbot> There is a large boulder here.

Fsbot is also a doctor, fortune-teller, pinhead, elisp-interpretor… Later: whoops, fsbot currently hangs in dunnet when it reaches the computer… – DeepakGoel

Perhaps this triggers some password stuff? – AlexSchroeder

Wiki Training

See the bottom of the ErbotInstallation page

JavaDoc Training

If you have required erbjavadoc (see the ErbotInstallation page), users on a channel can add links to all Java classes and package names by “scraping” links from a javadoc generated page. For example, to load the entire Java 1.5 standard library:

     <deego> , learn-javadocs
     <erbot> I'm downloading the javadocs now ...
     <erbot> Processing 213 entries from 
               will take at least 0.3 minutes.
     <erbot> Processing 3467 entries from 
               will take at least 7.2 minutes.
      [Time passes as this is an asynchronous operation]
     <erbot> Added 213 entries from
    <erbot> Added 3467 entries from

To see the list of javadocs that have been learned:

    <deego> , learned-javadocs
    <erbot> I know about the following set of javadocs: 

Please keep in mind, learning a set of javadocs as large as the jdk1.5 pages will take a long time (especially if you have not compiled erbot elisp files). While learning the pages, erbot is still able to respond to user requests on channels. Furthermore, a set of javadocs cannot be learned more than once until it has been forgotten which the bot operator must do, usually with the following in the erbot emacs session:

     ;; The following will take a long time to run and is not 
     ;; asynchronous and thus erbot will be disconnected 
     ;; from IRC if performed on a live session.
     (erburl-forget-terms "")
     (setq erbjavadoc-scraped-urls 
               (remove ""

If that seems complicated, its because erbjavadoc-forget-javadocs, the function that does all of the above, has been commented out until I can figure out how to make it asynchronous as well otherwise users on a channel can cause the bot to be disconnected.

Viewing Web Pages and Web Server Info

Web pages can be viewed by users on a channel. Of course this assumes that the web page in question can be rendered by a text browser (in this case w3m). The output will be paginated appropriately so as not to flood the channel. For example:

     <pete> !web
     <erbot> 2000
     <erbot>                                  The BileBlog
     <erbot>                              All | General | Java
     <erbot> 20041230 Thursday December 30, 2004
     <erbot> The real interview with Klaus Wuestefeld Not one to be
               outdone by any old fake ..[Type !more]

In addition to web pages, one can also view the HTTP headers for a request. For example:

     <pete> !wserver 
     <erbot> HTTP/1.1 200 OK
     <erbot> Server: Resin/3.0.9
     <erbot> Cache-Control: private
     <erbot> Set-Cookie: JSESSIONID=a-_xBElt4Mi8; path=/
     <erbot> Content-Type: text/html; charset=utf-8
     <erbot> Content-Length: 74851
     <erbot> Date: Sat, 08 Jan 2005 04:11:44 GMT


Info stored in fsbot is licensed under the FDL, according to fsbot.

    *fsbot* [1] All information known to fsbot is freely distributable under GNU FDL.

Note that since the “invariant sections” of fsbot’s FDL are “none”, the license is DFSG-free.

TODO: Topics to document

We still need to write more here about these topics: help, website, paginator, dictionary, Erbot’s customization, elisp, codewalking, wserver, web, h4x0r, stud, bash-quotes, say, geek-code, readonly functions,

Authors etc.

The people responsible for Erbot’s code are DeepakGoel, SebastianFreundt, DavidEdmondson, MichaelOlson, Pete Kazmier, YannHodique (erbot->lispy extention), JorgenSchaefer (RSS feed), Dheeraj Buduru (erbkarma.el),Alejandro Benitez (natural language translation), J. Michael Dupont at #fsedu (perl scripts), authors of packages used by Erbot: google.el (hober AKA EdwardOConnor), dictionary-el (Torsten Hilbrich), w3, url, bbdb, h4x0r.el (Charles Sebold), bash-quotes.el (TerryPatcher), many of Noah Friedman’s libraries (like flame.el), and of course, the entire ERC and emacs. It is a result of collaborative design 😊, with many people’s thoughts going into it: resolve (DamienElmes), bpt (BtTempleton), forcer (JorgenSchaefer), kensanata (AlexSchroeder), LawrenceMitchell, Grant Bowman, MarioLang, TerryPatcher, LuisFernandes, tintin and many other #emacsers.

This list may be outdated. Please consult the AUTHORS file that comes with erbot, and please feel free to update this list.

Done reading already?

Erbot has a bunch of other newer features (like natural language translation) which may not be documented here at all, or which may be documented on other pages. So, scroll down (== page-up) and go on to other pages like ErbotEmacs 😊


Here can erbot be downloaded from? I mirror this package on the Emacsmirror so people can get a copy from their but the place where I used to get this package ( seams to be dead. – JonasBernoulli

AFAICT the official sources are still on savannah: I just imported the CVS with history into if that can be of any help. – YannHodique

The current sources reside at Disclaimer/forewarning: Source is far from polished; nor is installation straightforward. -deego, 2019

EmacsChannel ErcRobot