         obj.outputs = ipynb_outputs(output, exec_count, opts.more_output?[id], opts.blob_store)
     else if not obj.outputs? and obj.cell_type == 'code'
         obj.outputs = [] # annoying requirement of ipynb file format.
+    for n, x of obj.outputs
+        if x.cocalc?
+            # alternative version of cell that official Jupyter doesn' support can only
+            # stored in the **cell-level** metadata, not output.
+            metadata.cocalc ?= {outputs:{}}
+            metadata.cocalc.outputs[n] = x.cocalc
+            delete x.cocalc
     return obj
 
 ipynb_outputs = (output, exec_count, more_output, blob_store) ->

# Return ipynb version of the given cell as Python object
cell_to_ipynb = (id, opts) ->
    cell = opts.cells.get(id)
    obj =
        cell_type : cell.get('cell_type') ? 'code'
        source    : cell.get('input')
        metadata  : {}
    if cell.get('collapsed')
        obj.metadata.collapsed = true
    if cell.get('scrolled')
        obj.metadata.scrolled = true

    exec_count = cell.get('exec_count') ? 0
    if obj.cell_type == 'code'

        output_n.execution_count = exec_count
    else if output_n.name?
        output_n.output_type = 'stream'
        if output_n.name == 'input'
            process_stdin_output(output_n)
    else if output_n.ename?
        output_n.output_type = 'error'
    return

process_stdin_output = (output) ->
    output.cocalc = misc.deep_copy(output)
    output.name = 'stdout'
    output.text = output.opts.prompt + ' ' + (output.value ? '')
    delete output.opts
    delete output.value
