mscgen_js tutorial

turns text into sequence charts


This is a short (but complete) tutorial on creating sequence charts in plain text. It covers


Msc Cheat sheet

# MsGenny: a cheat sheet

a -> b   : a -> b  (signal),
b <-> c  : b <-> c,
c -- d   : c -- d,
d -> d   : d -> d;

a => b   : a => b  (method),
b <=> c  : b <=> c,
d => d   : d => d;

b >> a   : b >> a (return value),
b <<>> c : b <<>> c,
c .. d   : c .. d (dotted),
d >> d   : d >> d;

a =>> b   : a =>> b (callback),
b <<=>> c : b <<=>> c,
d =>> d   : d =>> d;

a -x b   : a -x b  (lost),
d -x d   : d -x d;

a :> b   : a :> b  (emphasis),
b <:> c  : b <:> c,
d :> d   : d :> d;

b note b : b note b \n(note),
c box c  : c box c\n(action);

b rbox b : b rbox b\n(reference),
c abox c : c abox c\n(state/ condition);

|||      : ||| (empty row);
...      : ... (omitted row);
 ---      : --- (comment);
a -> b   : a -> b  (signal);
a => b   : a => b  (method);
b >> a   : b >> a  (return value);
a =>> b  : a =>> b (callback);
a -x b   : a -x b  (lost);
a :> b   : a :> b  (emphasis);
a .. b   : a .. b  (dotted);
a note a : a note a\n(note),
b box b  : b box b\n(action);
a rbox a : a rbox a\n(reference),
b abox b : b abox b\n(state/ condition);
|||      : ||| (empty row);
...      : ... (omitted row);
---      : --- (comment);

MsGenny language tutorial

MsGenny was designed to make writing sequence charts in text even simpler than it already is in MscGen.


a sends a signal to b

The most simple sequence chart is the one where an entity a sends a signal to an entity b

a -> b;

As you can see this creates two entities (a and b), both with a lifeline, and an arrow from the first to the second lifeline.

Entity names can consist of almost any unicode character, so you can write things like 差出人 -> 受信機;

Adding labels

To add a label to your signal, put it behind a colon, like so:

a -> b: "ping";

Note: when your description doesn't contain a , or a ; it is possible to leave the quotes out of the label, so in this case a -> b: ping; would have achieved exactly the same effect.

b replies to a

Adding extra parts to the conversation works along the same lines

a -> b: ping;
b >> a: heard ya!;


To add a note to a chart use the special note arc type. Notes are similar to arcs in that they start on a lifeline and end on one.

a -> b: ping;
b >> a: heard ya!;
a note a: we're not done yet ...;

Multiline text

The mscgen_js render engine automatically breaks long lines into multiple lines.

However, you can break a long label in pieces manually by putting the (c-style) escape code \n on the spots you want to split the label. This works for all labels.

a note b: This is a note consisting of\ntwo lines of text;
b => c  : Breaking text in two\nalso works for arcs;

Everything in boxes wraps automatically. Regular arcs also do that when the wordwraparcs option is on. We're thinking of having this as the default somewhere in the future, but haven't yet because of backwards compatibility.

Empty rows, omitted rows, comments

Sometimes your chart needs some more space between arcs, e.g. to emphasise grouping.

a =>> b: do something for me;
b >>  a: done;
a => c : "b is done doing something;\ngo bother him";
c -> b : bother;

To indicate you deliberately left out stuff of your chart, you can use ellipses, like this:

a =>> b: Do the voodoo;
b => c : Iberian dance task;
c -x b : Whaaat?;
...    : magic happens here;
b >> a : Magic answer;

To demarcate more strongly and/ or to comment on a part, use comment (---), like so:

a =>> b: readOutLoud\n(message);
---    : for each line in the message:;
b => "text to\nspeach": getAudio (line);
"text to\nspeach" >> b: lAudioStream;
b -> speaker: play(lAudioStream);

Ignore this

In your program lines starting with # or // are ignored, as is everything between /* c-style block comments */

# This line is ignored
a =>> b: what's happening here?; /* don't know */
// ignored line

Caveat: on translating to MscGen most comments (except those at the top of the source) get lost.

Advanced stuff

Options: arcgradient, hscale, width, wordwraparcs

With arcgradient all lines get skewed a little.

Options go on top


client => server : SYN;
server => client : SYN + ACK;
client => server : ACK;

hscale horizontally scales the chart a bit. Numbers bigger than 1 enlarge it; smaller than 1 shrink it.

arcgradient="10", hscale="0.6";

client => server : SYN;
server => client : SYN + ACK;
client => server : ACK;

... and width scales the whole chart so it fits in exactly the amount of pixels width.

arcgradient="10", width="240";

client => server : SYN;
server => client : SYN + ACK;
client => server : ACK;

The default behaviour for regular (= not note, box, abox or rbox) arcs is that text does not get wrapped. To override this you can use the boolean wordwraparcs option. Just like the other options, this one was copied from MscGen. MscGen not only accepts true and false, but also on and off and 1 and 0 all with or without quotes.

wordwraparcs=false; # default behaviour
a =>   b : This will get wrapped when wordwraparcs=true;
a note b : "Text in notes, boxes (box, abox, rbox)
            and entities always gets wrapped.
            Wordwraparcs does not influence that
wordwraparcs=true; # override default behaviour
a =>   b : This will get wrapped when wordwraparcs=true;
a note b : "Text in notes, boxes (box, abox, rbox)
            and entities always gets wrapped.
            Wordwraparcs does not influence that

For boxes and entitiesthe default behaviour is exactly the other way 'round; if you need to override that, use the wordwrapboxes and wordwrapentities options respectively. An example for wordwrapboxes:

wordwrapboxes=true; # the default behaviour
a =>   b : "By default this won't wrap";
a note b : "This will wrap automatically, 
            unless wordwrapboxes equals false.";
wordwrapboxes=false; # override default behaviour
a =>   b : "By default this won't wrap";
a note b : "This will wrap automatically, 
            unless wordwrapboxes equals false.";

Explicit entity declarations: labeling entities, use your own order

To prevent you from having to enter long entity names in each line, you can explicitly declare entity names at the start of your script and give them labels.

A: Actor, fe:Front end, be: Back end;

A =>> fe: "log me in\n(id, secret)";
fe => be: "getToken\n(id, secret)";
fe << be: [OK] token;
A << fe: Whoop!;

The msgenny parser puts the entities in the order they occur in your script, e.g.

1 =>> 4;
3 >> 2;

If that's not what you want, declare them in the order you want them to appear:


1 =>> 4;
3 >> 2;

broadcasts, parallel calls

When an entity has to send a message to all entities at once (broadcast) use * as entity name. When you use this it is practical to use the arcgradient option to prevent lines from overlapping.

a, b, c, d;
b =>> *;

In situations where you want to express two calls being executed in parallel (or for some other reason want to see two arcs on one row), seperate them with a , in stead of with a ;

a, b, c, n;
a => b: parallel\nwith c => b,
c => b: parallel\nwith a => b,
n note n: a note on the same line;

Both ways, no way

For almost every arc type (->, =>, =>>, >>, :>) a two way variant exists, as well as a variant without arrows:

a <-> b, b <=> c;
a <<=>> b, b <<>> c;
a -- b, b .. c;
a :: b, b <:> c ;

box, rbox, abox

Boxes expressing action (box), states or conditions (abox) and MSC references (rbox) are part of the original MscGen standard, and hence they're supported in MsGenny as well.

a  box b :  box (action);
b abox c : abox (state/ condition);
c rbox d : rbox (MSC reference);


We've thrown the most important ones in a cheat sheet (see below). A smaller version of the sheet is available as (svg, png) and directly from the "learn" menu in the interpreter.

Extended stuff

The features described in extended stuff are only supported in Xù and MsGenny, not in MscGen. If you rely on MscGen to do your rendering in (e.g.) doxygen you might want to steer clear of these, or rewrite them in a fashion that kind of mimics the behavior in vanilla MscGen (tips below).

alt, loop, par & family

If you're a sequence diagram regular, you probably feel the need to express alternatives and loops 'n stuff once in a while, like this:

In sequence chart land these things are called inline expressions (SDL) or combined fragments (UML). There is no support for it in MscGen, which is why we created Xù and included them in MsGenny at the same time.

All inline expression keywords (alt, opt, loop, par and the more excotic exc, break, seq, strict, neg, ignore, consider and assert) work in both languages.

To get the sample above you'd use:

a =>> b;
b loop d: 3 times {
   b =>> c: knock;
   c alt d: some condition {
      c =>> d: do stuff;
      ---: not true;
      c =>> d: do other stuff;

Mimicing this in MscGen A way to do nesting in MscGen is to use arrowless arcs for the top and the bottom of the inline expression.

The command line interface script will help you do that: (mscgen_js yourscript.msgenny -o yourscript.mscgen).

In beta feature mode the interpreter can do this as well. Use the ... button and pick Vanilla MscGen from the menu.


To put a watermark text through your chart, add a watermark option, like so:

hscale="0.7", watermark="Watermark";

Alice => Bob : do something funny;
Bob => pocket : "fetch (nose flute)";
Bob >> Alice : PHEEE!;
Alice => Alice: hihihi;

Mimicing this in MscGen There are several ways to get a similar message accross in MscGen. The simplest one is to put the text in an empty row somewhere (||| [label="Watermark", textcolor="gray"];). For now the command line interface ignores the watermark option when translating back to MscGen


To make the generated svg match the space it is put in,

width=auto, arcgradient=25;


d =>> *: "A wide chart, but no wories - it'll autoscale";
width=auto, arcgradient=25; a,b,c,d,e,f,g; d =>> *: "A wide chart, but no wories - it'll autoscale";

Mimicing this in MscGen You can manually enter the required width (e.g. width=800), or you can open up the generated svg and modify the width and height to relative ones.

The MscGen language

Michael McTernan created the MscGen sequence chart language in 2006. It's a bit more elaborate than MsGenny. There are three good reasons to use MscGen in stead of (or beside) the simpler MsGenny:

For the original MscGen reference visit Michaels site.


MscGen scripts are surrounded by an opening and closing statements:

msc {


In between go, in this order:

Putting these together (larded with some # comments):

/* By the way: c-style single line (//)
 * and multi-line comments are
 * supported, as are shell-style
 * single line comments (starting with #)
msc {
    # options

    # entities
    mike [label="Michael McTernan"],
    kbd [label="keyboard"],
    pc [label="computing unit"],
    scr [label="screen"];

    # arcs
    mike =>> kbd [label="push button"];
    kbd =>> pc [label="electrical current"];
    pc => pc [label="do stuff"];
    pc => scr [label="electrical current"];
    scr >> mike [label="photons"];

Non ascii entity names

If you'd want use different things from numbers and letters in entity names you have two options:


MscGen has three basic attributes to influence the color of both entities and attributes: textcolor, textbgcolor and linecolor, which work as advertised. As an example:

msc {

a [label="linecolor=\n\"orange\"",
b [label="textbgcolor=\n\"yellow\"",

a =>> b  [label="linecolor=\"blue\"",
b >> a   [label="textcolor=\"green\"",
a => b   [label="textbgcolor=\"lime\"",
a note a [label="color bonanza",
b note b  [label="color\nbonanza",

Coloring everyting departing from a lifeline

If you want to color lifelines and every arc departing it, you don't have to manually color each and every one, instead use the arc* variants of coloring attributes described in the previous paragraph on the entity:

msc {

  cust [label="customer"],
  ui [label="UI"],
  c [label="Glue module",
     linecolor="red", textbgcolor="yellow",
     arclinecolor="red", arctextcolor="red",
  a [label="Customer store"],
  m [label="Model"],
  e [label="Event logger"];

  cust =>> ui [label="Account\n(id, secret)?"];
  ui =>> c [label="Get account\ninfo"];
  c -> e [label="log(id, 'getAccount', 'start')"];
  c => a [label="identify\n(id, secret)"];
  a >> c [label="token"];
  c => m [label="getAccount(id)"];
  m >> c [label="Account data"];
  c =>> c [label="mangle(Account Data)"];
  c -> e [label="log(id, 'getAccount', 'OK')"];

  ui << c [label="Account data"];
  ui =>> ui [label="render"];


To express that one specific call takes time you can make it "skip" some lines:

msc {
    a, b;

    a =>> b [label="with arcskip", arcskip="1"];
    a =>> b [label="without arcskip"];

Links'n stuff: url, id, idurl

It is possible to define actual links. The original MscGen command line version processed them by generating an image map. mscgen_js instead embeds the links directly within the vector graphics it creates. The attribute name for this magic is url.

Besides, MscGen enables you to attach an id to entities and arcs. And actually define links on these as well.

Putting this together:

msc {
    a [id="this is the id of entity a"],
    b [label="link to\ngithub page",

    a => b [label="link to mscgen\nissues on github",

    a note b [label="works in entities, arcs, notes and boxes",
              id="id links to about:blank",

Xù - a superset of MscGen

Xù is a little language that combines the features of MscGen and MsGenny:

Using Xù

In the mscgen_js on line interpreter

The on line interpreter recognizes when you use a feature from Xù. It shows by displaying a little xù marker on the language switch.

In the atom package

The mscgen-preview package for the atom editor shows a live preview of the chart inside the editor.

It shoots into 'Xù-mode' when presented with a file that ends in .xu.

On the command line

The mscgen_js command line interface also recognizes the .xu extension:

# .xu is automatically recognized as Xù
mscgenjs supercoolchart.xu

# other extensions aren't. in that case specify xu
mscgenjs --input-type xu anothercoolchart.seq

An example

The source for this:

# facebook authentication
# adopted from
msc {
  watermark="序 sample: FaceBook auth";

  act [label="Actor", linecolor="darkgreen", textcolor="white", textbgcolor="darkgreen", arclinecolor="darkgreen", arctextcolor="darkgreen"],
  browser [label=":WebBrowser", linecolor="darkgreen", textcolor="white", textbgcolor="darkgreen", arclinecolor="darkgreen", arctextcolor="darkgreen"],
  app [label="Application", linecolor="maroon", textcolor="white", textbgcolor="maroon", arclinecolor="maroon", arctextcolor="maroon"],
  fbauth [label="Facebook Authorization Server", linecolor="#3a5795", textcolor="white", textbgcolor="#3a5795", arclinecolor="#3a5795", arctextcolor="#3a5795"],
  fbcont [label="Facebook Content Server", linecolor="#3a5795", textcolor="white", textbgcolor="#3a5795", arclinecolor="#3a5795", arctextcolor="#3a5795"];

  act => browser [label="get FB resource"];
  browser => app [label="request FB access"];
  app >> browser [label="<>"];
  browser => fbauth [label="authorize"];
  fbauth >> browser [label="permission form"];
  browser >> act [label="permission form"];

  act => browser [label="user permission"];
  browser => fbauth [label="process permission"];
  fbauth >> browser [label="<>"];

  act alt fbcont [label="permission granted", linecolor="grey", textcolor="black"] {
    browser => app [label="FB authorization code"];
    app => fbauth [label="FB authorization code"];
    fbauth >> app [label="access token"];
    app => fbcont [label="access FB user protected resource"];
    fbcont >> app [label="protected resource"];
    app >> browser [label="protected resource"];
    browser >> act [label="protected resource"];
    --- [label="no permission", linecolor="grey", textbgcolor="white", textcolor="black"];
    browser => app [label="no authorization"];
    app >> browser [label="FB resource not available"];
    browser >> act [label="FB resource not available"];

Using the on line interpreter

With the on line interpreter you can write MsGenny and MscGen scripts and see the resulting chart grow in real time.

If you like the on line interpreter, you might also like the (open source) mscgen-preview package for the atom editor. It uses the same render engine, renders charts in real-time, and has out-of-this-world syntax higlighting.


The typing area on the right uses codemirror. This means it (a.o.) supports undo history, automatic bracket matching and syntax highlighting, just like you would expect of an off line code editor. You can even drop files directly from your desktop.

a screenshot of the mscgen_js interpreter

Auto render

By default the interpreter renders the chart as you type. However, if you're on a very slow machine, you can switch off this behavior. The interpreter will offer you a Render button that renders the chart only when you click it.


With the language radiobox you can switch between the languages supported by mscgen_js (MscGen, Xù and MsGenny). When the interpreter is in debug mode, you can also see (and edit) the abstract syntax tree, which is in JSON format.

When you switch between the languages, you'll see the program in the editor is translated to the new language.

When switching between languages the interpreter preserves comments preceding the program. Comments within and after the program get lost, though.

When your program uses features not available in a target language, these will get lost in the translation.


When you hit the color button you can either:

For example, here is what the what applying the 'Automatic' color scheme will get you:


Not for MsGenny

As MsGenny does not support colors, auto color is disabled for that language.

Respect existing colors vs forced

Each color scheme has two variants:


The online interpreter supports several output formats behind the save button.

Vector graphics: svg

Clicking the svg button pushes the svg to you - depending on your browser configuration the browser will either ask you what to do with it, save it or open it in your default program that handles svg's.

Raster graphics: png and jpeg

Works the same as the svg, albeit you are presented with the "rasterized" version of the chart in the lossless png or the lossy jpeg formats respectively.

This works for most charts. If your chart is really big, though (>32k pixels wide or high) the browser won't be able to export it to png or jpeg. The interpreter will hide the png and jpeg buttons and explain. For the background of these limitations check mscgen_js github issue #248.

The little film camera icon

Animates the current sequence chart. When you click it, a light box opens:

a simple sequence chart - animated

The multi-media buttons should be pretty self explanatory. To close the lightbox, click the X or hit the ESC key.

Why is this in?

The animation feature is an attempt to capture the feeling of seeing a sequence chart grow on a whiteboard. We noticed that when we draw sequence charts, even people who have never seen one immediately grasp what is going on.

Bookmarkable url

This generates a URL (in your address bar) which would (re-)load the program currently in the editor e.g.

Beta feature mode

When you start the interpreter in "beta feature" (/ "debug") mode (like so:, you'll notice the interpreter grows some extra features:



mscgen_js is the engine for an interpreter for MscGen, MsGenny and . It makes embedding sequence charts in html easy as falling off a log.


Sander Verweij

LinkedIn GitHub



open source (GPL-3.0), with a relaxation.

Source Licenses

To improve based on data we save some behavior information (like button clicks) for future analysis. By using this site you imply you're ok with that (it's the only thing we ask for).