Miss any of our Open RFC calls?Watch the recordings here! »


1.2.4 • Public • Published

The new BF CLI replaces legacy standalone tools

The Bot Framework SDK team is happy to announce the General Availability of the consolidated bot framework CLI tool bf-cli. The new BF CLI tool will replace legacy standalone tools to manage Bot Framework bots and related services. The old tools will be ported over in phases and all new features, bug fixes, and further investments will focus on the new BF CLI. Old tools will still work for the time being, but they are going to be deprecated in future releases.

Upon the release of Bot Framework SDK version 4.6 the following legacy tools have been ported: Chatdown, QnAMaker, LuisGen, and LuDown.

To learn more about the BF CLI please visit the BF CLI github repository.

The following page is about a legacy tool.


npm version

Chatdown is a transcript generator which consumes a .chat file to generate mock transcripts. Generated mock transcript files are output to stdout.

A good bot, just like any successful application or a website, starts with clarity on supported scenarios. Creating mockups of conversations between bot and user is useful for:

  • Framing the scenarios supported by the bot.
  • Business decision makers to review, provide feedback.
  • Defining a "happy path" (as well as other paths) through conversational flows between a user and a bot

.chat file format helps you create mockups of conversations between a user and a bot. Chatdown CLI tool converts .chat files into conversation transcripts (.transcript files) that can be viewed in the Bot Framework Emulator.



npm i -g chatdown



chatdown <chat> --help
Argument Description
<chat> The path of the chat file to be parsed. If omitted, stdin will be used.
-v, --version show version
--help Output the help to the console
--static use static timestamps when generating timestamps on activities.

.chat File Format

Here's an example .chat file:

bot: Hi!
user: yo!
bot: [Typing][Delay=3000]
What would you like to do?
* update - You can update your account
* List - You can list your data
* help - you can get help
user: I need the bot framework logo.
Here you go.
user: thanks
Here's a form for you
[Attachment=card.json adaptivecard]

See the Examples folder for more samples.

Chat files are markdown files that contain 2 parts:

  • Header that defines who the participants are in the conversation
  • Back and forth conversation between a user and a bot


The header defines who the participants are in the conversation and defines other options.

Option Description
user=<user> This option tells chatdown that a user message will begin with <user> followed by a colon. For example, user=Joe instructs chatdown that lines beginning with Joe: or user: are the start of a message from the user Joe.
users=<user1>,<user2>,<user3> This option tells chatdown that there are multiple users in the conversation.
bot=<bot> This options tells chatdown that a bot message will begin with <bot> followed by a colon. For example, bot=LulaBot instructs chadown that lines beginning with LulaBot: or bot: are the start of a message from the bot Lulabot.
channelId=<channelID> This option tells chatdown to use the specified channelID for each activity.

Once the configuration options for users and bot are defined, the rest of the conversation can use the alias prefixes user: and bot: or the names directly. Chatdown will correctly make the associations to the specified names for you.

The Bot will default to sending to the first user in the users list or the last user it received a message from, unless you directly specify a target user by using the bot->user: syntax.

For example:

bot: This will go to Joe, because he's first in the list
Fred: What about me?
bot: This will go to Fred, because he's the latest user to talk to the bot
bot->Joe: This will always go to Joe
bot->Fred: This will always go to Fred


The conversation between the user and the bot with markdown support for bot's responses. Every time a user: or bot: is found at the beginning of the line, a new activity will be inserted into the transcript. Inside the markdown, you can insert commands to generate richer transcripts:

Activity commands

Command Description
[Typing] Inserts a typing activity into the transcript to signify that a user or a bot is typing.
[Delay=<milliseconds>] Delays the transcript by <milliseconds>.
[ConversationUpdate=] Sends a conversationUpdate, with membersAdded= and membersRemoved= values

Example ConversationUpdate message

bot->Joe: Hi Joe!
bot->Susan: Hi Susan!

Message commands

When sending a message there are a number of commands for controlling layout.

Command Description
[Suggestions=<Option 1>|<Option 2>|<Option 3>] Add suggested action buttons, delimited by |
[AttachmentLayout=LayoutType] Specify how multiple attachments would be displayed. Layout types are carousel or list

Message Cards

You can add cards using simple commands as well. Currently we support a number of cards:

description card name
HeroCard A simple card with single large image, title, subtitle, text and buttons
ThumbnailCard Same as herocard, but image is much smaller
AudioCard send audio card for playing back an audio url
VideoCard send an video player card for playing back a video file
AnimationCard send a animated gif card
MediaCard send arbitrary media with transport control
SigninCard send a signin card
OauthCard send an oauth card which uses azure bot service oauth flow
    title=Cheese gromit!
    subtitle=Hero Card
    text=This is some text describing the card, it's cool because it's cool
    buttons=Option 1| Option 2| Option 3]
    title=Cheese gromit!
    subtitle=Thumbnail Card
    text=This is some text describing the card, it's cool because it's cool
    buttons=Option 1| Option 2| Option 3]

The properties that are supported are

property description
title The title of the card
subtitle a subtitle for the card with less emphasis
text a generic text property which can contain longer text describing the card
image image url to use for the card
buttons a set of button labels separated by |

Message Attachments

To add an attachment, you use [Attachment=path contentPath]. The path can be a URL or a local path (either absolute or relative to .chat file). The content type is optional and if not passed, will be inferred from the file extension. You can also pass it using a shortcut or full mime type.

[Attachment=path contentType]

The following examples illustrates sending a carousel of photos:

Enjoy these pictures!

This example sends a local adaptive card using a content type shortcut:

[Attachment=folder/sample.json "adaptivecard"]

Attachment content type shortcuts

Some of the content types have shortcuts:

ContentType Shortcuts Description
animation application/vnd.microsoft.card.animation
audio application/vnd.microsoft.card.audio
hero application/vnd.microsoft.card.hero
receipt application/vnd.microsoft.card.receipt
thumbnail application/vnd.microsoft.card.thumbnail
signin application/vnd.microsoft.card.signin
video application/vnd.microsoft.card.video
adaptivecard application/vnd.microsoft.card.adaptive
application/custom application/custom

CLI Examples

Basic usage

In the simplest form, a chatdown command looks like the following:

chatdown sample.chat > sample.transcript

This will consume sample.chat and output sample.transcript.

Using stdin

stdin can be used as an alternative to specifying an input file.

(echo user=Joe && echo bot=LulaBot && echo Joe: 'Hi!' && echo LulaBot: 'Hi there!') | chatdown > sample.transcript

Using stdout

stdout can be used as an alternative to specifying the output file.

chatdown sample.chat


chatdown sample.chat > joe.transcript

The transcript will be piped to stdout.

As a library

Chatdown can be used within a Node.js application as an imported library. Install locally:

npm i -s chatdown

In your node project:

const chatdown = require('chatdown');
const conversation = `
    user: Hello!
    bot: Hello, can I help you?
    user: I need an image
    bot: here you go! [Attachments:bot-framework.png]
chatdown(conversation, config)
    .then(activities => {
        // do stuff with the resulting activities.
    .catch(e =>{
         // oops! Something went wrong

Processing multiple Chatdown files

If you are dealing strictly with files, and not standard input/output, you can process all Chatdown files at once:

chatdown -f **/*.chat -o ./transcripts

The above command will process all *.chat files in the current directory and all subdirectories, and put the output in the "transcripts" folder of the current directory. If an output directory is not present, it will default to the current working directory.

Setting up a watcher to automatically transcribe chat files

Chokidar-cli is a great utility to do this.

To install:

npm install -g chokidar-cli

To run as a watcher:

chokidar "**/*.chat" -c "chatdown {path} > {path}.transcript"

Now, any time a .chat file is created or saved, chatdown will automatically create the transcript file beside it.

Nightly builds

Nightly builds are based on the latest development code which means they may or may not be stable and probably won't be documented. These builds are better suited for more experienced users and developers although everyone is welcome to give them a shot and provide feedback.

You can get the latest nightly build of Chatdown from the BotBuilder MyGet feed. To install the nightly -

npm config set registry https://botbuilder.myget.org/F/botbuilder-tools-daily/npm/

Install using npm:

npm i -g chatdown

To reset registry:

npm config set registry https://registry.npmjs.org/




npm i chatdown

DownloadsWeekly Downloads






Unpacked Size

141 kB

Total Files


Last publish


  • avatar