Experiments with Zed AI


Experiments in Zed

Baseline: Shy

As a baseline I asked a tiny, command-line-only assistant to help my format my slides for a Python User Group talk based on some of these results. I’m using the python package revealmd

Shy is designed to help you compose the correct command line options, mostly for a Linux OS and apps. I use it whenever I get stumped and a metager.org search doesn’t immediately show the correct answer in the docs.

I eventually found what I wanted using metaGer, despite Bing’s recent rug-pull. At first, my keyword search “reveal.js markdown syntax speaker notes” turned up mostly distracting answers for javascript programmers, and I had to try a couple queries and a couple rabbitholes before I found the correct answer.

So, with the truth in hand, and a reasonably challenging query, I gave shy a try.

Shy + ollama Llama 3.2 7B

Shy my go-to assistant for quick questions because it doesn’t require an internet connection and takes only a few seconds to return an answer directly in the command line. I’m sandbagging here, so “Don’t do this at home.” Skip to the bottom if you are more interested in my recommendations for cutting edge models and the best way to use generative coding assistants.

I like to use dumb, general models for my work, rather than specialized, overfit models. This gives me the most generic answers that I could expect from a search engine if I were online and my assistant was asked to retrieve a couple lines of code.And I want to be able to see when it is wrong. I’m not going to ask it to demonstrate difficult things where it would take me more time to test and debug the results.

Shy is both a CLI app and an interactive shell. I chose to run it in one-off app mode, so that you can reproduce these exact results yourself, if you like.

$ shy what is the markdown syntax for speaker notes in a reveal.js presentation slide deck
🛠️  markdown -s | grep -oP '(?<=^>).*?(?=</p>)'

Unfortunately, shy is trained to recognize the first shell command it sees in your question and key of this to help you run that command. What I wanted was something like “You should use a blank line and \nnote:\nThis slide is about...\n\n”. Fortunately, most assistants still ask you for confirmation before automating your computer into lalaland. Shy does this by default, and I’ll wait for the singularity before I turn this feature off.

So shy asked me what I wanted to do:

Do you need more details? [**C**opy/**n**o/**e**xplain/**a**lternatives]: a

It’s interesting that in the age of AI, I still can’t just say what I want, and instead have to navigate a phone tree.

 Pick the command to copy to the clipboard  
 ► Cancel
   markdown -s | grep -oP '(?<=^>).*?(?=</p>)' # Original command
   pandoc -s | sed 's/<[^>]*>//g; s/^[[:space:]]*//; s/[[:space:]]*$//' # Convert markdown to HTML and extract paragraph text
   grep -oP '(?<=^>).*?(?=</p>)' markdown.md # Extract paragraph text from markdown using grep
   markdown2html -s markdown.md | grep -oP '(?<=<p>).*?(?=</p>)' # Use markdown to HTML conversion tool and extract paragraph

✨: exit
🤖: 👋 Bye!

No joy. Shy is a wrapper around the ollama models I have running locally. Shy just rewords my prompt to focus ONLY on command line app options and arguments. So, taking a step back, I used my local copy of ollama and llama 3.2 7B directly.

Llama 3.2 7B

So to see if that prompt rewording was the problem, I gave my question directly to a bare bones llama3.2 that I’m serving up all the time on my laptop, using ollama:

$ ollama run llama3.2 "what is the markdown syntax for speaker notes in a reveal.js presentation slide deck?"

Ollama responded in less than a second (much faster than shy) with:

In Reveal.js, you can use Markdown syntax to create speaker notes on a slide. To do this, add the following attribute 
to your HTML element:

\`\`\`
<!-- notes -->
\`\`\`

This will create a speaker note area that appears when the user clicks on it.

Perfect. That looks like the most general and portable and robust answer, since it should work in HTML as well as markdown.

I tried it out for one of my slides

and not sure it actually creates a link or button that is clickable in the generated HTML slide deck, at least not in revealmd slides.

Fortunately Llama 3.2 rambles on:

Alternatively, you can also use the `notes` block attribute in your slides, like this:

\`\`\`
<div class="notes">
  <!-- Your speaker notes here -->
</div>
\`\`\`

This will render the speaker notes below the main slide content.

That’s not it either. I explicitly asked for Markdown syntax, not HTML syntax. Markdown is a superset of HTML, so I tested it out and it worked, but not the way that Llama described.

Zed + Claude Sonnet 3.7

show me how to add speakernotes to this reveal.js presentation
I'll help you add speaker notes to your reveal.js presentation. Let me first explore the project structure to find the relevant reveal.js presentation files.

🔍 50 matches · **/*.html

Let me look for reveal.js presentation files and related templates in the project:

🔍 11 matches · **/*.js

Let me continue searching ...

...

Best Practices for Speaker Notes

1. Keep notes concise and focused on key points
2. Use bullet points for easier scanning during presentation
3. Include timing cues if your presentation has time constraints
4. Add reminders for transitions or interactive segments
5. Consider including backup information for potential questions

Would you like me to show you how to add speaker notes to a specific slide or presentation in your project?

Follow-up

yes, to [@2025-05-22-python-automation-with-pexpect.md](@file:slides.nlpia.org/slides/2025-05-22-python-automation-with-pexpect.md)
I'll show you how to add speaker notes to your "Python Automation with Pexpect" presentation. Based on the file you provided, your presentation is written in Markdown format and uses reveal.js for presenting.

## How to Add Speaker Notes to Your Pexpect Presentation

In reveal.js, you can add speaker notes to your Markdown slides using the `note:` syntax. Let me show you how to add notes to several slides in your presentation:

### 1. First slide (Title slide)

...

note:
Welcome everyone to today's presentation on Python Automation with Pexpect.
I'm Hobson Lane, and I'll be showing you how to automate interactive command-line programs using Python.
This is particularly useful for testing, automating repetitive tasks, and interacting with programs that weren't designed for automation.

...

Serializer preprocessor

Before

def is_builtin_type(obj):
    return obj.__class__.__module__ == '__builtin__'
def dictify(obj, ignore_class_names=('Session',), ignore_startswith='_', ignore_endswith='_'):
    """ Recursively convert lists and dicts to built-in types serializable by json.dumps() """
    if isinstance(obj, (list, tuple, PaginatedList)):
        return [dictify(x) for x in obj]
    if callable(getattr(obj, 'isoformat', None)):
        return obj.isoformat()
    if (not isinstance(obj, dict) and is_builtin_type(obj)) or not hasattr(obj, '__dict__'):
        return obj
    d = dict()
    for k, v in vars(obj).items():
        if k.startswith(ignore_startswith) or k.endswith(ignore_endswith) or v.__class__.__name__ in ignore_class_names:
            continue
        elif isinstance(v, Mapping):
            d[k] = dictify(dict(v))
        else:
            if not is_builtin_type(v):
                d[k] = dictify(v)
    return d

Zed + Claude Sonnet 3.7:

I opened the AI panel open on the lower right and the course.py file in the main middle editor panel by selecting it in theproject outline panel on the left. After several failed attempts at asking it to simplify and modularize the course.py file, I found a prompt that I was sure it could handle: “Simplify the function dictify() in @course.py”

def is_builtin_type(obj):
    """Check if an object is a Python built-in type"""
    return isinstance(obj, (str, int, float, bool, type(None), dict, list, tuple))
def dictify(obj, ignore_class_names=('Session',), ignore_startswith='_', ignore_endswith='_'):
    """ Recursively convert objects to built-in types serializable by json.dumps() """
    # Handle collections
    if isinstance(obj, (list, tuple, PaginatedList)):
        return [dictify(x, ignore_class_names, ignore_startswith, ignore_endswith) for x in obj]
    
    # Handle datetime objects
    if callable(getattr(obj, 'isoformat', None)):
        return obj.isoformat()
    
    # Return built-in types as is
    if is_builtin_type(obj) or not hasattr(obj, '__dict__'):
        return obj
    
    # Convert object attributes to dictionary
    result = {}
    for k, v in vars(obj).items():
        # Skip ignored attributes
        if (k.startswith(ignore_startswith) or 
            k.endswith(ignore_endswith) or 
            (v is not None and v.__class__.__name__ in ignore_class_names)):
            continue
            
        # Handle mappings (dict-like objects)
        if isinstance(v, Mapping):
            result[k] = dictify(dict(v), ignore_class_names, ignore_startswith, ignore_endswith)
        # Handle non-builtin types
        elif v is not None and not is_builtin_type(v):
            result[k] = dictify(v, ignore_class_names, ignore_startswith, ignore_endswith)
        # Handle builtin types
        else:
            result[k] = v
            
    return result

Claude Haiku 3:

def dictify(obj):
    """Recursively convert an object to a dictionary"""
    if isinstance(obj, (list, tuple)):
        return [dictify(item) for item in obj]
    if hasattr(obj, 'isoformat'):
        return obj.isoformat()
    if is_builtin_type(obj) or not hasattr(obj, '__dict__'):
        return obj
    return {
        k: dictify(v)
        for k, v in vars(obj).items()
        if not k.startswith('_') and not k.endswith('_')
    }