<?xml version="1.0" encoding="utf-8"?>
<feed xml:lang="en-us" xmlns="http://www.w3.org/2005/Atom"><title>Simon Willison's Weblog: deno</title><link href="http://simonwillison.net/" rel="alternate"/><link href="http://simonwillison.net/tags/deno.atom" rel="self"/><id>http://simonwillison.net/</id><updated>2026-02-03T22:44:50+00:00</updated><author><name>Simon Willison</name></author><entry><title>Introducing Deno Sandbox</title><link href="https://simonwillison.net/2026/Feb/3/introducing-deno-sandbox/#atom-tag" rel="alternate"/><published>2026-02-03T22:44:50+00:00</published><updated>2026-02-03T22:44:50+00:00</updated><id>https://simonwillison.net/2026/Feb/3/introducing-deno-sandbox/#atom-tag</id><summary type="html">
    
&lt;p&gt;&lt;strong&gt;&lt;a href="https://deno.com/blog/introducing-deno-sandbox"&gt;Introducing Deno Sandbox&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
Here's a new hosted sandbox product from the Deno team. It's actually unrelated to Deno itself - this is part of their Deno Deploy SaaS platform. As such, you don't even need to use JavaScript to access it - you can create and execute code in a hosted sandbox using their &lt;a href="https://pypi.org/project/deno-sandbox/"&gt;deno-sandbox&lt;/a&gt; Python library like this:&lt;/p&gt;
&lt;div class="highlight highlight-source-shell"&gt;&lt;pre&gt;&lt;span class="pl-k"&gt;export&lt;/span&gt; DENO_DEPLOY_TOKEN=&lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;"&lt;/span&gt;... API token ...&lt;span class="pl-pds"&gt;"&lt;/span&gt;&lt;/span&gt;
uv run --with deno-sandbox python&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Then:&lt;/p&gt;
&lt;pre&gt;&lt;span class="pl-k"&gt;from&lt;/span&gt; &lt;span class="pl-s1"&gt;deno_sandbox&lt;/span&gt; &lt;span class="pl-k"&gt;import&lt;/span&gt; &lt;span class="pl-v"&gt;DenoDeploy&lt;/span&gt;

&lt;span class="pl-s1"&gt;sdk&lt;/span&gt; &lt;span class="pl-c1"&gt;=&lt;/span&gt; &lt;span class="pl-en"&gt;DenoDeploy&lt;/span&gt;()

&lt;span class="pl-k"&gt;with&lt;/span&gt; &lt;span class="pl-s1"&gt;sdk&lt;/span&gt;.&lt;span class="pl-c1"&gt;sandbox&lt;/span&gt;.&lt;span class="pl-c1"&gt;create&lt;/span&gt;() &lt;span class="pl-k"&gt;as&lt;/span&gt; &lt;span class="pl-s1"&gt;sb&lt;/span&gt;:
    &lt;span class="pl-c"&gt;# Run a shell command&lt;/span&gt;
    &lt;span class="pl-s1"&gt;process&lt;/span&gt; &lt;span class="pl-c1"&gt;=&lt;/span&gt; &lt;span class="pl-s1"&gt;sb&lt;/span&gt;.&lt;span class="pl-c1"&gt;spawn&lt;/span&gt;(
        &lt;span class="pl-s"&gt;"echo"&lt;/span&gt;, &lt;span class="pl-s1"&gt;args&lt;/span&gt;&lt;span class="pl-c1"&gt;=&lt;/span&gt;[&lt;span class="pl-s"&gt;"Hello from the sandbox!"&lt;/span&gt;]
    )
    &lt;span class="pl-s1"&gt;process&lt;/span&gt;.&lt;span class="pl-c1"&gt;wait&lt;/span&gt;()
    &lt;span class="pl-c"&gt;# Write and read files&lt;/span&gt;
    &lt;span class="pl-s1"&gt;sb&lt;/span&gt;.&lt;span class="pl-c1"&gt;fs&lt;/span&gt;.&lt;span class="pl-c1"&gt;write_text_file&lt;/span&gt;(
        &lt;span class="pl-s"&gt;"/tmp/example.txt"&lt;/span&gt;, &lt;span class="pl-s"&gt;"Hello, World!"&lt;/span&gt;
    )
    &lt;span class="pl-en"&gt;print&lt;/span&gt;(&lt;span class="pl-s1"&gt;sb&lt;/span&gt;.&lt;span class="pl-c1"&gt;fs&lt;/span&gt;.&lt;span class="pl-c1"&gt;read_text_file&lt;/span&gt;(
        &lt;span class="pl-s"&gt;"/tmp/example.txt"&lt;/span&gt;
    ))&lt;/pre&gt;
&lt;p&gt;There’s a JavaScript client library as well. The underlying API isn’t documented yet but appears &lt;a href="https://tools.simonwillison.net/zip-wheel-explorer?package=deno-sandbox#deno_sandbox/sandbox.py--L187"&gt;to use WebSockets&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;There’s a lot to like about this system. Sandboxe instances can have up to 4GB of RAM, get 2 vCPUs, 10GB of ephemeral storage, can mount persistent volumes and can use snapshots to boot pre-configured custom images quickly. Sessions can last up to 30 minutes and are billed by CPU time, GB-h of memory and volume storage usage.&lt;/p&gt;
&lt;p&gt;When you create a sandbox you can configure network domains it’s allowed to access.&lt;/p&gt;
&lt;p&gt;My favorite feature is the way it handles API secrets.&lt;/p&gt;
&lt;pre&gt;&lt;span class="pl-k"&gt;with&lt;/span&gt; &lt;span class="pl-s1"&gt;sdk&lt;/span&gt;.&lt;span class="pl-c1"&gt;sandboxes&lt;/span&gt;.&lt;span class="pl-c1"&gt;create&lt;/span&gt;(
    &lt;span class="pl-s1"&gt;allowNet&lt;/span&gt;&lt;span class="pl-c1"&gt;=&lt;/span&gt;[&lt;span class="pl-s"&gt;"api.openai.com"&lt;/span&gt;],
    &lt;span class="pl-s1"&gt;secrets&lt;/span&gt;&lt;span class="pl-c1"&gt;=&lt;/span&gt;{
        &lt;span class="pl-s"&gt;"OPENAI_API_KEY"&lt;/span&gt;: {
            &lt;span class="pl-s"&gt;"hosts"&lt;/span&gt;: [&lt;span class="pl-s"&gt;"api.openai.com"&lt;/span&gt;],
            &lt;span class="pl-s"&gt;"value"&lt;/span&gt;: &lt;span class="pl-s1"&gt;os&lt;/span&gt;.&lt;span class="pl-c1"&gt;environ&lt;/span&gt;.&lt;span class="pl-c1"&gt;get&lt;/span&gt;(&lt;span class="pl-s"&gt;"OPENAI_API_KEY"&lt;/span&gt;),
        }
    },
) &lt;span class="pl-k"&gt;as&lt;/span&gt; &lt;span class="pl-s1"&gt;sandbox&lt;/span&gt;:
    &lt;span class="pl-c"&gt;# ... $OPENAI_API_KEY is available&lt;/span&gt;&lt;/pre&gt;
&lt;p&gt;Within the container that &lt;code&gt;$OPENAI_API_KEY&lt;/code&gt; value is set to something like this:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;DENO_SECRET_PLACEHOLDER_b14043a2f578cba...
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Outbound API calls to &lt;code&gt;api.openai.com&lt;/code&gt; run through a proxy which is aware of those placeholders and replaces them with the original secret.&lt;/p&gt;
&lt;p&gt;In this way the secret itself is not available to code within the sandbox, which limits the ability for malicious code (e.g. from a prompt injection) to exfiltrate those secrets.&lt;/p&gt;
&lt;p&gt;From &lt;a href="https://news.ycombinator.com/item?id=46874097#46874959"&gt;a comment on Hacker News&lt;/a&gt; I learned that Fly have a project called &lt;a href="https://github.com/superfly/tokenizer"&gt;tokenizer&lt;/a&gt; that implements the same pattern. Adding this to my list of tricks to use with sandoxed environments!

    &lt;p&gt;&lt;small&gt;&lt;/small&gt;Via &lt;a href="https://news.ycombinator.com/item?id=46874097"&gt;Hacker News&lt;/a&gt;&lt;/small&gt;&lt;/p&gt;


    &lt;p&gt;Tags: &lt;a href="https://simonwillison.net/tags/python"&gt;python&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/sandboxing"&gt;sandboxing&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/security"&gt;security&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/deno"&gt;deno&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/fly"&gt;fly&lt;/a&gt;&lt;/p&gt;



</summary><category term="python"/><category term="sandboxing"/><category term="security"/><category term="deno"/><category term="fly"/></entry><entry><title>MicroQuickJS</title><link href="https://simonwillison.net/2025/Dec/23/microquickjs/#atom-tag" rel="alternate"/><published>2025-12-23T20:53:40+00:00</published><updated>2025-12-23T20:53:40+00:00</updated><id>https://simonwillison.net/2025/Dec/23/microquickjs/#atom-tag</id><summary type="html">
    
&lt;p&gt;&lt;strong&gt;&lt;a href="https://github.com/bellard/mquickjs"&gt;MicroQuickJS&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
New project from programming legend Fabrice Bellard, of ffmpeg and QEMU and QuickJS and &lt;a href="https://bellard.org"&gt;so much more&lt;/a&gt; fame:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;MicroQuickJS (aka. MQuickJS) is a Javascript engine targetted at embedded systems. It compiles and runs Javascript programs with as low as 10 kB of RAM. The whole engine requires about 100 kB of ROM (ARM Thumb-2 code) including the C library. The speed is comparable to QuickJS.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;It supports &lt;a href="https://github.com/bellard/mquickjs/blob/17ce6fe54c1ea4f500f26636bd22058fce2ce61a/README.md#javascript-subset-reference"&gt;a subset of full JavaScript&lt;/a&gt;, though it looks like a rich and full-featured subset to me.&lt;/p&gt;
&lt;p&gt;One of my ongoing interests is sandboxing: mechanisms for executing untrusted code - from end users or generated by LLMs - in an environment that restricts memory usage and applies a strict time limit and restricts file or network access. Could MicroQuickJS be useful in that context?&lt;/p&gt;
&lt;p&gt;I fired up Claude Code for web (on my iPhone) and kicked off &lt;a href="https://simonwillison.net/2025/Nov/6/async-code-research/"&gt;an asynchronous research project&lt;/a&gt; to see explore that question:&lt;/p&gt;
&lt;p&gt;My full prompt &lt;a href="https://github.com/simonw/research/pull/50#issue-3757781692"&gt;is here&lt;/a&gt;. It started like this:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;Clone https://github.com/bellard/mquickjs to /tmp&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Investigate this code as the basis for a safe sandboxing environment for running untrusted code such that it cannot exhaust memory or CPU or access files or the network&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;First try building python bindings for this using FFI - write a script that builds these by checking out the code to /tmp and building against that, to avoid copying the C code in this repo permanently. Write and execute tests with pytest to exercise it as a sandbox&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Then build a "real" Python extension not using FFI and experiment with that&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Then try compiling the C to WebAssembly and exercising it via both node.js and Deno, with a similar suite of tests [...]&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;I later added to the interactive session:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;Does it have a regex engine that might allow a resource exhaustion attack from an expensive regex?&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;(The answer was no - the regex engine calls the interrupt handler even during pathological expression backtracking, meaning that any configured time limit should still hold.)&lt;/p&gt;
&lt;p&gt;Here's &lt;a href="https://gistpreview.github.io/?6e07c54db7bb8ed8aa0eccfe4a384679"&gt;the full transcript&lt;/a&gt; and the &lt;a href="https://github.com/simonw/research/blob/main/mquickjs-sandbox/README.md"&gt;final report&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Some key observations:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;MicroQuickJS is &lt;em&gt;very&lt;/em&gt; well suited to the sandbox problem. It has robust near and time limits baked in, it doesn't expose any dangerous primitive like filesystem of network access and even has a regular expression engine that protects against exhaustion attacks (provided you configure a time limit).&lt;/li&gt;
&lt;li&gt;Claude span up and tested a Python library that calls a MicroQuickJS shared library (involving a little bit of extra C), a compiled a Python binding and a library that uses the original MicroQuickJS CLI tool. All of those approaches work well.&lt;/li&gt;
&lt;li&gt;Compiling to WebAssembly was a little harder. It got a version working in Node.js and Deno and Pyodide, but the Python libraries wasmer and wasmtime proved harder, apparently because "mquickjs uses setjmp/longjmp for error handling". It managed to get to a working wasmtime version with &lt;a href="https://github.com/simonw/research/blob/main/mquickjs-sandbox/README.md#working-solution"&gt;a gross hack&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I'm really excited about this. MicroQuickJS is tiny, full featured, looks robust and comes from excellent pedigree. I think this makes for a very solid new entrant in the quest for a robust sandbox.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Update&lt;/strong&gt;: I had Claude Code build &lt;a href="https://tools.simonwillison.net/microquickjs"&gt;tools.simonwillison.net/microquickjs&lt;/a&gt;, an interactive web playground for trying out the WebAssembly build of MicroQuickJS, adapted from my previous &lt;a href="https://tools.simonwillison.net/quickjs"&gt;QuickJS plaground&lt;/a&gt;. My QuickJS page loads 2.28 MB (675 KB transferred). The MicroQuickJS one loads 303 KB (120 KB transferred).&lt;/p&gt;
&lt;p&gt;Here are &lt;a href="https://github.com/simonw/tools/pull/180#issue-3758595291"&gt;the prompts I used&lt;/a&gt; for that.


    &lt;p&gt;Tags: &lt;a href="https://simonwillison.net/tags/c"&gt;c&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/javascript"&gt;javascript&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/nodejs"&gt;nodejs&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/python"&gt;python&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/sandboxing"&gt;sandboxing&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/ai"&gt;ai&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/webassembly"&gt;webassembly&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/deno"&gt;deno&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/pyodide"&gt;pyodide&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/generative-ai"&gt;generative-ai&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/llms"&gt;llms&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/claude-code"&gt;claude-code&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/fabrice-bellard"&gt;fabrice-bellard&lt;/a&gt;&lt;/p&gt;



</summary><category term="c"/><category term="javascript"/><category term="nodejs"/><category term="python"/><category term="sandboxing"/><category term="ai"/><category term="webassembly"/><category term="deno"/><category term="pyodide"/><category term="generative-ai"/><category term="llms"/><category term="claude-code"/><category term="fabrice-bellard"/></entry><entry><title>The many, many, many JavaScript runtimes of the last decade</title><link href="https://simonwillison.net/2025/Jul/27/javascript-runtimes-of-the-last-decade/#atom-tag" rel="alternate"/><published>2025-07-27T23:56:57+00:00</published><updated>2025-07-27T23:56:57+00:00</updated><id>https://simonwillison.net/2025/Jul/27/javascript-runtimes-of-the-last-decade/#atom-tag</id><summary type="html">
    
&lt;p&gt;&lt;strong&gt;&lt;a href="https://buttondown.com/whatever_jamie/archive/the-many-many-many-javascript-runtimes-of-the-last-decade/"&gt;The many, many, many JavaScript runtimes of the last decade&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
Extraordinary piece of writing by Jamie Birch who spent over a year putting together this comprehensive reference to JavaScript runtimes. It covers everything from Node.js, Deno, Electron, AWS Lambda, Cloudflare Workers and Bun all the way to much smaller projects idea like dukluv and txiki.js.

    &lt;p&gt;&lt;small&gt;&lt;/small&gt;Via &lt;a href="https://news.ycombinator.com/item?id=44701574"&gt;Hacker News&lt;/a&gt;&lt;/small&gt;&lt;/p&gt;


    &lt;p&gt;Tags: &lt;a href="https://simonwillison.net/tags/javascript"&gt;javascript&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/nodejs"&gt;nodejs&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/deno"&gt;deno&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/bun"&gt;bun&lt;/a&gt;&lt;/p&gt;



</summary><category term="javascript"/><category term="nodejs"/><category term="deno"/><category term="bun"/></entry><entry><title>MCP Run Python</title><link href="https://simonwillison.net/2025/Apr/18/mcp-run-python/#atom-tag" rel="alternate"/><published>2025-04-18T04:51:20+00:00</published><updated>2025-04-18T04:51:20+00:00</updated><id>https://simonwillison.net/2025/Apr/18/mcp-run-python/#atom-tag</id><summary type="html">
    
&lt;p&gt;&lt;strong&gt;&lt;a href="https://github.com/pydantic/pydantic-ai/tree/main/mcp-run-python"&gt;MCP Run Python&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
Pydantic AI's MCP server for running LLM-generated Python code in a sandbox. They ended up using a trick I explored &lt;a href="https://til.simonwillison.net/deno/pyodide-sandbox"&gt;two years ago&lt;/a&gt;: using a &lt;a href="https://deno.com/"&gt;Deno&lt;/a&gt; process to run &lt;a href="https://pyodide.org/"&gt;Pyodide&lt;/a&gt; in a WebAssembly sandbox.&lt;/p&gt;
&lt;p&gt;Here's a bit of a wild trick: since Deno loads code on-demand from &lt;a href="https://jsr.io/"&gt;JSR&lt;/a&gt;, and &lt;a href="https://docs.astral.sh/uv/guides/scripts/"&gt;uv run&lt;/a&gt; can install Python dependencies on demand via the &lt;code&gt;--with&lt;/code&gt; option... here's a one-liner you can paste into a macOS shell (provided you have Deno and &lt;code&gt;uv&lt;/code&gt; installed already) which will run the example from &lt;a href="https://github.com/pydantic/pydantic-ai/blob/v0.1.2/mcp-run-python/README.md"&gt;their README&lt;/a&gt; - calculating the number of days between two dates in the most complex way imaginable:&lt;/p&gt;
&lt;pre&gt;ANTHROPIC_API_KEY=&lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;"&lt;/span&gt;sk-ant-...&lt;span class="pl-pds"&gt;"&lt;/span&gt;&lt;/span&gt; \
uv run --with pydantic-ai python -c &lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;'&lt;/span&gt;&lt;/span&gt;
&lt;span class="pl-s"&gt;import asyncio&lt;/span&gt;
&lt;span class="pl-s"&gt;from pydantic_ai import Agent&lt;/span&gt;
&lt;span class="pl-s"&gt;from pydantic_ai.mcp import MCPServerStdio&lt;/span&gt;
&lt;span class="pl-s"&gt;&lt;/span&gt;
&lt;span class="pl-s"&gt;server = MCPServerStdio(&lt;/span&gt;
&lt;span class="pl-s"&gt;    "deno",&lt;/span&gt;
&lt;span class="pl-s"&gt;    args=[&lt;/span&gt;
&lt;span class="pl-s"&gt;        "run",&lt;/span&gt;
&lt;span class="pl-s"&gt;        "-N",&lt;/span&gt;
&lt;span class="pl-s"&gt;        "-R=node_modules",&lt;/span&gt;
&lt;span class="pl-s"&gt;        "-W=node_modules",&lt;/span&gt;
&lt;span class="pl-s"&gt;        "--node-modules-dir=auto",&lt;/span&gt;
&lt;span class="pl-s"&gt;        "jsr:@pydantic/mcp-run-python",&lt;/span&gt;
&lt;span class="pl-s"&gt;        "stdio",&lt;/span&gt;
&lt;span class="pl-s"&gt;    ],&lt;/span&gt;
&lt;span class="pl-s"&gt;)&lt;/span&gt;
&lt;span class="pl-s"&gt;agent = Agent("claude-3-5-haiku-latest", mcp_servers=[server])&lt;/span&gt;
&lt;span class="pl-s"&gt;&lt;/span&gt;
&lt;span class="pl-s"&gt;async def main():&lt;/span&gt;
&lt;span class="pl-s"&gt;    async with agent.run_mcp_servers():&lt;/span&gt;
&lt;span class="pl-s"&gt;        result = await agent.run("How many days between 2000-01-01 and 2025-03-18?")&lt;/span&gt;
&lt;span class="pl-s"&gt;    print(result.output)&lt;/span&gt;
&lt;span class="pl-s"&gt;&lt;/span&gt;
&lt;span class="pl-s"&gt;asyncio.run(main())&lt;span class="pl-pds"&gt;'&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;

&lt;p&gt;I ran that just now and got:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The number of days between January 1st, 2000 and March 18th, 2025 is 9,208 days.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;I thoroughly enjoy how tools like &lt;code&gt;uv&lt;/code&gt; and Deno enable throwing together shell one-liner demos like this one.&lt;/p&gt;
&lt;p&gt;Here's &lt;a href="https://gist.github.com/simonw/54fc42ef9a7fb8f777162bbbfbba4f23"&gt;an extended version&lt;/a&gt; of this example which adds pretty-printed logging of the messages exchanged with the LLM to illustrate exactly what happened. The most important piece is this tool call where Claude 3.5 Haiku asks for Python code to be executed my the MCP server:&lt;/p&gt;
&lt;pre&gt;&lt;span class="pl-en"&gt;ToolCallPart&lt;/span&gt;(
    &lt;span class="pl-s1"&gt;tool_name&lt;/span&gt;&lt;span class="pl-c1"&gt;=&lt;/span&gt;&lt;span class="pl-s"&gt;'run_python_code'&lt;/span&gt;,
    &lt;span class="pl-s1"&gt;args&lt;/span&gt;&lt;span class="pl-c1"&gt;=&lt;/span&gt;{
        &lt;span class="pl-s"&gt;'python_code'&lt;/span&gt;: (
            &lt;span class="pl-s"&gt;'from datetime import date&lt;span class="pl-cce"&gt;\n&lt;/span&gt;'&lt;/span&gt;
            &lt;span class="pl-s"&gt;'&lt;span class="pl-cce"&gt;\n&lt;/span&gt;'&lt;/span&gt;
            &lt;span class="pl-s"&gt;'date1 = date(2000, 1, 1)&lt;span class="pl-cce"&gt;\n&lt;/span&gt;'&lt;/span&gt;
            &lt;span class="pl-s"&gt;'date2 = date(2025, 3, 18)&lt;span class="pl-cce"&gt;\n&lt;/span&gt;'&lt;/span&gt;
            &lt;span class="pl-s"&gt;'&lt;span class="pl-cce"&gt;\n&lt;/span&gt;'&lt;/span&gt;
            &lt;span class="pl-s"&gt;'days_between = (date2 - date1).days&lt;span class="pl-cce"&gt;\n&lt;/span&gt;'&lt;/span&gt;
            &lt;span class="pl-s"&gt;'print(f"Number of days between {date1} and {date2}: {days_between}")'&lt;/span&gt;
        ),
    },
    &lt;span class="pl-s1"&gt;tool_call_id&lt;/span&gt;&lt;span class="pl-c1"&gt;=&lt;/span&gt;&lt;span class="pl-s"&gt;'toolu_01TXXnQ5mC4ry42DrM1jPaza'&lt;/span&gt;,
    &lt;span class="pl-s1"&gt;part_kind&lt;/span&gt;&lt;span class="pl-c1"&gt;=&lt;/span&gt;&lt;span class="pl-s"&gt;'tool-call'&lt;/span&gt;,
)&lt;/pre&gt;

&lt;p&gt;I also managed to run it against &lt;a href="https://ollama.com/library/mistral-small3.1"&gt;Mistral Small 3.1&lt;/a&gt; (15GB) running locally using &lt;a href="https://ollama.com/"&gt;Ollama&lt;/a&gt; (I had to add "Use your python tool" to the prompt to get it to work):&lt;/p&gt;
&lt;pre&gt;ollama pull mistral-small3.1:24b

uv run --with devtools --with pydantic-ai python -c &lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;'&lt;/span&gt;&lt;/span&gt;
&lt;span class="pl-s"&gt;import asyncio&lt;/span&gt;
&lt;span class="pl-s"&gt;from devtools import pprint&lt;/span&gt;
&lt;span class="pl-s"&gt;from pydantic_ai import Agent, capture_run_messages&lt;/span&gt;
&lt;span class="pl-s"&gt;from pydantic_ai.models.openai import OpenAIModel&lt;/span&gt;
&lt;span class="pl-s"&gt;from pydantic_ai.providers.openai import OpenAIProvider&lt;/span&gt;
&lt;span class="pl-s"&gt;from pydantic_ai.mcp import MCPServerStdio&lt;/span&gt;
&lt;span class="pl-s"&gt;&lt;/span&gt;
&lt;span class="pl-s"&gt;server = MCPServerStdio(&lt;/span&gt;
&lt;span class="pl-s"&gt;    "deno",&lt;/span&gt;
&lt;span class="pl-s"&gt;    args=[&lt;/span&gt;
&lt;span class="pl-s"&gt;        "run",&lt;/span&gt;
&lt;span class="pl-s"&gt;        "-N",&lt;/span&gt;
&lt;span class="pl-s"&gt;        "-R=node_modules",&lt;/span&gt;
&lt;span class="pl-s"&gt;        "-W=node_modules",&lt;/span&gt;
&lt;span class="pl-s"&gt;        "--node-modules-dir=auto",&lt;/span&gt;
&lt;span class="pl-s"&gt;        "jsr:@pydantic/mcp-run-python",&lt;/span&gt;
&lt;span class="pl-s"&gt;        "stdio",&lt;/span&gt;
&lt;span class="pl-s"&gt;    ],&lt;/span&gt;
&lt;span class="pl-s"&gt;)&lt;/span&gt;
&lt;span class="pl-s"&gt;&lt;/span&gt;
&lt;span class="pl-s"&gt;agent = Agent( &lt;/span&gt;
&lt;span class="pl-s"&gt;    OpenAIModel(                          &lt;/span&gt;
&lt;span class="pl-s"&gt;        model_name="mistral-small3.1:latest",&lt;/span&gt;
&lt;span class="pl-s"&gt;        provider=OpenAIProvider(base_url="http://localhost:11434/v1"),                &lt;/span&gt;
&lt;span class="pl-s"&gt;    ),            &lt;/span&gt;
&lt;span class="pl-s"&gt;    mcp_servers=[server],&lt;/span&gt;
&lt;span class="pl-s"&gt;)&lt;/span&gt;
&lt;span class="pl-s"&gt;&lt;/span&gt;
&lt;span class="pl-s"&gt;async def main():&lt;/span&gt;
&lt;span class="pl-s"&gt;    with capture_run_messages() as messages:&lt;/span&gt;
&lt;span class="pl-s"&gt;        async with agent.run_mcp_servers():&lt;/span&gt;
&lt;span class="pl-s"&gt;            result = await agent.run("How many days between 2000-01-01 and 2025-03-18? Use your python tool.")&lt;/span&gt;
&lt;span class="pl-s"&gt;    pprint(messages)&lt;/span&gt;
&lt;span class="pl-s"&gt;    print(result.output)&lt;/span&gt;
&lt;span class="pl-s"&gt;&lt;/span&gt;
&lt;span class="pl-s"&gt;asyncio.run(main())&lt;span class="pl-pds"&gt;'&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;

&lt;p&gt;Here's &lt;a href="https://gist.github.com/simonw/e444a81440bda2f37b0fef205780074a"&gt;the full output&lt;/a&gt; including the debug logs.

    &lt;p&gt;&lt;small&gt;&lt;/small&gt;Via &lt;a href="https://news.ycombinator.com/item?id=43691230"&gt;Hacker News&lt;/a&gt;&lt;/small&gt;&lt;/p&gt;


    &lt;p&gt;Tags: &lt;a href="https://simonwillison.net/tags/python"&gt;python&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/sandboxing"&gt;sandboxing&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/ai"&gt;ai&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/deno"&gt;deno&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/generative-ai"&gt;generative-ai&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/local-llms"&gt;local-llms&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/llms"&gt;llms&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/claude"&gt;claude&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/mistral"&gt;mistral&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/llm-tool-use"&gt;llm-tool-use&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/uv"&gt;uv&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/ollama"&gt;ollama&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/pydantic"&gt;pydantic&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/model-context-protocol"&gt;model-context-protocol&lt;/a&gt;&lt;/p&gt;



</summary><category term="python"/><category term="sandboxing"/><category term="ai"/><category term="deno"/><category term="generative-ai"/><category term="local-llms"/><category term="llms"/><category term="claude"/><category term="mistral"/><category term="llm-tool-use"/><category term="uv"/><category term="ollama"/><category term="pydantic"/><category term="model-context-protocol"/></entry><entry><title>Announcing Deno 2</title><link href="https://simonwillison.net/2024/Oct/10/announcing-deno-2/#atom-tag" rel="alternate"/><published>2024-10-10T04:11:02+00:00</published><updated>2024-10-10T04:11:02+00:00</updated><id>https://simonwillison.net/2024/Oct/10/announcing-deno-2/#atom-tag</id><summary type="html">
    
&lt;p&gt;&lt;strong&gt;&lt;a href="https://deno.com/blog/v2.0"&gt;Announcing Deno 2&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
The big focus of Deno 2 is compatibility with the existing Node.js and npm ecosystem:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Deno 2 takes all of the features developers love about Deno 1.x — zero-config, all-in-one toolchain for JavaScript and TypeScript development, web standard API support, secure by default — and makes it fully backwards compatible with Node and npm (in ESM).&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The npm support &lt;a href="https://docs.deno.com/runtime/fundamentals/node/#using-npm-packages"&gt;is documented here&lt;/a&gt;. You can write a script like this:&lt;/p&gt;
&lt;div class="highlight highlight-source-js"&gt;&lt;pre&gt;&lt;span class="pl-k"&gt;import&lt;/span&gt; &lt;span class="pl-c1"&gt;*&lt;/span&gt; &lt;span class="pl-k"&gt;as&lt;/span&gt; &lt;span class="pl-s1"&gt;emoji&lt;/span&gt; &lt;span class="pl-k"&gt;from&lt;/span&gt; &lt;span class="pl-s"&gt;"npm:node-emoji"&lt;/span&gt;&lt;span class="pl-kos"&gt;;&lt;/span&gt;
&lt;span class="pl-smi"&gt;console&lt;/span&gt;&lt;span class="pl-kos"&gt;.&lt;/span&gt;&lt;span class="pl-en"&gt;log&lt;/span&gt;&lt;span class="pl-kos"&gt;(&lt;/span&gt;&lt;span class="pl-s1"&gt;emoji&lt;/span&gt;&lt;span class="pl-kos"&gt;.&lt;/span&gt;&lt;span class="pl-en"&gt;emojify&lt;/span&gt;&lt;span class="pl-kos"&gt;(&lt;/span&gt;&lt;span class="pl-s"&gt;`:sauropod: :heart:  npm`&lt;/span&gt;&lt;span class="pl-kos"&gt;)&lt;/span&gt;&lt;span class="pl-kos"&gt;)&lt;/span&gt;&lt;span class="pl-kos"&gt;;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;And when you run it Deno will automatically fetch and cache the required dependencies:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;deno run main.js
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Another new feature that caught my eye was this:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;deno jupyter&lt;/code&gt; now supports outputting images, graphs, and HTML&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Deno has apparently shipped with &lt;a href="https://docs.deno.com/runtime/reference/cli/jupyter/"&gt;a Jupyter notebook kernel&lt;/a&gt; for a while, and it's had a major upgrade in this release.&lt;/p&gt;
&lt;p&gt;Here's &lt;a href="https://www.youtube.com/watch?v=d35SlRgVxT8&amp;amp;t=1829s"&gt;Ryan Dahl's demo&lt;/a&gt; of the new notebook support in his Deno 2 release video.&lt;/p&gt;
&lt;p&gt;I tried this out myself, and it's really neat. First you need to install the kernel:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;deno juptyer --install
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I was curious to find out what this actually did, so I dug around &lt;a href="https://github.com/denoland/deno/blob/251840a60d1e2ba4ceca85029bd8cc342b6cd038/cli/tools/jupyter/install.rs#L48-L57"&gt;in the code&lt;/a&gt; and then further &lt;a href="https://github.com/runtimed/runtimed/blob/e2cd9b1d88e44842e1b1076d3a1d1f202fcf7879/runtimelib/src/jupyter/dirs.rs#L81-L99"&gt;in the Rust runtimed dependency&lt;/a&gt;. It turns out installing Jupyter kernels, at least on macOS, involves creating a directory in &lt;code&gt;~/Library/Jupyter/kernels/deno&lt;/code&gt; and writing a &lt;code&gt;kernel.json&lt;/code&gt; file containing the following:&lt;/p&gt;
&lt;div class="highlight highlight-source-json"&gt;&lt;pre&gt;{
  &lt;span class="pl-ent"&gt;"argv"&lt;/span&gt;: [
    &lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;"&lt;/span&gt;/opt/homebrew/bin/deno&lt;span class="pl-pds"&gt;"&lt;/span&gt;&lt;/span&gt;,
    &lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;"&lt;/span&gt;jupyter&lt;span class="pl-pds"&gt;"&lt;/span&gt;&lt;/span&gt;,
    &lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;"&lt;/span&gt;--kernel&lt;span class="pl-pds"&gt;"&lt;/span&gt;&lt;/span&gt;,
    &lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;"&lt;/span&gt;--conn&lt;span class="pl-pds"&gt;"&lt;/span&gt;&lt;/span&gt;,
    &lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;"&lt;/span&gt;{connection_file}&lt;span class="pl-pds"&gt;"&lt;/span&gt;&lt;/span&gt;
  ],
  &lt;span class="pl-ent"&gt;"display_name"&lt;/span&gt;: &lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;"&lt;/span&gt;Deno&lt;span class="pl-pds"&gt;"&lt;/span&gt;&lt;/span&gt;,
  &lt;span class="pl-ent"&gt;"language"&lt;/span&gt;: &lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;"&lt;/span&gt;typescript&lt;span class="pl-pds"&gt;"&lt;/span&gt;&lt;/span&gt;
}&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;That file is picked up by any Jupyter servers running on your machine, and tells them to run &lt;code&gt;deno jupyter --kernel ...&lt;/code&gt; to start a kernel.&lt;/p&gt;
&lt;p&gt;I started Jupyter like this:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;jupyter-notebook /tmp
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Then started a new notebook, selected the Deno kernel and it worked as advertised:&lt;/p&gt;
&lt;p&gt;&lt;img alt="Jupyter notebook running the Deno kernel. I run 4 + 5 and get 9, then Deno.version and get back 2.0.0. I import Observable Plot and the penguins data, then render a plot which shows as a scatter chart." src="https://static.simonwillison.net/static/2024/deno-jupyter.jpg" /&gt;&lt;/p&gt;
&lt;div class="highlight highlight-source-ts"&gt;&lt;pre&gt;&lt;span class="pl-k"&gt;import&lt;/span&gt; &lt;span class="pl-c1"&gt;*&lt;/span&gt; &lt;span class="pl-k"&gt;as&lt;/span&gt; &lt;span class="pl-smi"&gt;Plot&lt;/span&gt; &lt;span class="pl-k"&gt;from&lt;/span&gt; &lt;span class="pl-s"&gt;"npm:@observablehq/plot"&lt;/span&gt;&lt;span class="pl-kos"&gt;;&lt;/span&gt;
&lt;span class="pl-k"&gt;import&lt;/span&gt; &lt;span class="pl-kos"&gt;{&lt;/span&gt; &lt;span class="pl-smi"&gt;document&lt;/span&gt;&lt;span class="pl-kos"&gt;,&lt;/span&gt; &lt;span class="pl-s1"&gt;penguins&lt;/span&gt; &lt;span class="pl-kos"&gt;}&lt;/span&gt; &lt;span class="pl-k"&gt;from&lt;/span&gt; &lt;span class="pl-s"&gt;"jsr:@ry/jupyter-helper"&lt;/span&gt;&lt;span class="pl-kos"&gt;;&lt;/span&gt;
&lt;span class="pl-k"&gt;let&lt;/span&gt; &lt;span class="pl-s1"&gt;p&lt;/span&gt; &lt;span class="pl-c1"&gt;=&lt;/span&gt; &lt;span class="pl-k"&gt;await&lt;/span&gt; &lt;span class="pl-en"&gt;penguins&lt;/span&gt;&lt;span class="pl-kos"&gt;(&lt;/span&gt;&lt;span class="pl-kos"&gt;)&lt;/span&gt;&lt;span class="pl-kos"&gt;;&lt;/span&gt;

&lt;span class="pl-smi"&gt;Plot&lt;/span&gt;&lt;span class="pl-kos"&gt;.&lt;/span&gt;&lt;span class="pl-en"&gt;plot&lt;/span&gt;&lt;span class="pl-kos"&gt;(&lt;/span&gt;&lt;span class="pl-kos"&gt;{&lt;/span&gt;
  &lt;span class="pl-c1"&gt;marks&lt;/span&gt;: &lt;span class="pl-kos"&gt;[&lt;/span&gt;
    &lt;span class="pl-smi"&gt;Plot&lt;/span&gt;&lt;span class="pl-kos"&gt;.&lt;/span&gt;&lt;span class="pl-en"&gt;dot&lt;/span&gt;&lt;span class="pl-kos"&gt;(&lt;/span&gt;&lt;span class="pl-s1"&gt;p&lt;/span&gt;&lt;span class="pl-kos"&gt;.&lt;/span&gt;&lt;span class="pl-en"&gt;toRecords&lt;/span&gt;&lt;span class="pl-kos"&gt;(&lt;/span&gt;&lt;span class="pl-kos"&gt;)&lt;/span&gt;&lt;span class="pl-kos"&gt;,&lt;/span&gt; &lt;span class="pl-kos"&gt;{&lt;/span&gt;
      &lt;span class="pl-c1"&gt;x&lt;/span&gt;: &lt;span class="pl-s"&gt;"culmen_depth_mm"&lt;/span&gt;&lt;span class="pl-kos"&gt;,&lt;/span&gt;
      &lt;span class="pl-c1"&gt;y&lt;/span&gt;: &lt;span class="pl-s"&gt;"culmen_length_mm"&lt;/span&gt;&lt;span class="pl-kos"&gt;,&lt;/span&gt;
      &lt;span class="pl-c1"&gt;fill&lt;/span&gt;: &lt;span class="pl-s"&gt;"species"&lt;/span&gt;&lt;span class="pl-kos"&gt;,&lt;/span&gt;
    &lt;span class="pl-kos"&gt;}&lt;/span&gt;&lt;span class="pl-kos"&gt;)&lt;/span&gt;&lt;span class="pl-kos"&gt;,&lt;/span&gt;
  &lt;span class="pl-kos"&gt;]&lt;/span&gt;&lt;span class="pl-kos"&gt;,&lt;/span&gt;
  document&lt;span class="pl-kos"&gt;,&lt;/span&gt;
&lt;span class="pl-kos"&gt;}&lt;/span&gt;&lt;span class="pl-kos"&gt;)&lt;/span&gt;&lt;span class="pl-kos"&gt;;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;


    &lt;p&gt;Tags: &lt;a href="https://simonwillison.net/tags/javascript"&gt;javascript&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/nodejs"&gt;nodejs&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/npm"&gt;npm&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/jupyter"&gt;jupyter&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/typescript"&gt;typescript&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/deno"&gt;deno&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/observable-plot"&gt;observable-plot&lt;/a&gt;&lt;/p&gt;



</summary><category term="javascript"/><category term="nodejs"/><category term="npm"/><category term="jupyter"/><category term="typescript"/><category term="deno"/><category term="observable-plot"/></entry><entry><title>fav.farm</title><link href="https://simonwillison.net/2024/Oct/7/fav-farm/#atom-tag" rel="alternate"/><published>2024-10-07T06:46:50+00:00</published><updated>2024-10-07T06:46:50+00:00</updated><id>https://simonwillison.net/2024/Oct/7/fav-farm/#atom-tag</id><summary type="html">
    
&lt;p&gt;&lt;strong&gt;&lt;a href="https://fav.farm/"&gt;fav.farm&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
Neat little site by Wes Bos: it serves SVG (or PNG &lt;a href="https://github.com/wesbos/favicon/blob/dd3e2fcddfbb01cfb9080c70d0c89853d7372f68/index.ts#L69"&gt;for Safari&lt;/a&gt;) favicons of every Emoji, which can be added to any site like this:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;link rel="icon" href="https://fav.farm/🔥" /&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The source code is &lt;a href="https://github.com/wesbos/favicon"&gt;on GitHub&lt;/a&gt;. It runs on Deno and Deno Deploy, and recently added per-Emoji hit counters powered by the Deno KV store, implemented in &lt;a href="https://github.com/wesbos/favicon/blob/dd3e2fcddfbb01cfb9080c70d0c89853d7372f68/db.ts"&gt;db.ts&lt;/a&gt; using this pattern:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;export function incrementCount(emoji: string) {
  const VIEW_KEY = [`favicon`, `${emoji}`];
  return db.atomic().sum(
    VIEW_KEY, 1n
  ).commit(); // Increment KV by 1
}
&lt;/code&gt;&lt;/pre&gt;

    &lt;p&gt;&lt;small&gt;&lt;/small&gt;Via &lt;a href="https://www.tiktok.com/@wesbos/video/7421944278802287877"&gt;Wes Bos on TikTok&lt;/a&gt;&lt;/small&gt;&lt;/p&gt;


    &lt;p&gt;Tags: &lt;a href="https://simonwillison.net/tags/favicons"&gt;favicons&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/javascript"&gt;javascript&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/svg"&gt;svg&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/deno"&gt;deno&lt;/a&gt;&lt;/p&gt;



</summary><category term="favicons"/><category term="javascript"/><category term="svg"/><category term="deno"/></entry><entry><title>System prompt for val.town/townie</title><link href="https://simonwillison.net/2024/Aug/28/system-prompt-for-townie/#atom-tag" rel="alternate"/><published>2024-08-28T03:33:11+00:00</published><updated>2024-08-28T03:33:11+00:00</updated><id>https://simonwillison.net/2024/Aug/28/system-prompt-for-townie/#atom-tag</id><summary type="html">
    
&lt;p&gt;&lt;strong&gt;&lt;a href="https://gist.github.com/simonw/d8cc934ad76b3bba82127937d45dc719"&gt;System prompt for val.town/townie&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;a href="https://www.val.town/"&gt;Val Town&lt;/a&gt; (&lt;a href="https://simonwillison.net/2024/Jun/21/search-based-rag/"&gt;previously&lt;/a&gt;) provides hosting and a web-based coding environment for Vals - snippets of JavaScript/TypeScript that can run server-side as scripts, on a schedule or hosting a web service.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://www.val.town/townie"&gt;Townie&lt;/a&gt; is Val's new AI bot, providing a conversational chat interface for creating fullstack web apps (with blob or SQLite persistence) as Vals.&lt;/p&gt;
&lt;p&gt;In the &lt;a href="https://twitter.com/stevekrouse/status/1828454235756798287"&gt;most recent release&lt;/a&gt; of Townie Val added the ability to inspect and edit its system prompt!&lt;/p&gt;
&lt;p&gt;I've archived a copy &lt;a href="https://gist.github.com/simonw/d8cc934ad76b3bba82127937d45dc719"&gt;in this Gist&lt;/a&gt;, as a snapshot of how Townie works today. It's surprisingly short, relying heavily on the model's existing knowledge of Deno and TypeScript.&lt;/p&gt;
&lt;p&gt;I enjoyed the use of "tastefully" in this bit:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;Tastefully add a view source link back to the user's val if there's a natural spot for it and it fits in the context of what they're building. You can generate the val source url via import.meta.url.replace("esm.town", "val.town").&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The prompt includes a few code samples, like this one demonstrating how to use Val's SQLite package:&lt;/p&gt;
&lt;div class="highlight highlight-source-ts"&gt;&lt;pre&gt;&lt;span class="pl-k"&gt;import&lt;/span&gt; &lt;span class="pl-kos"&gt;{&lt;/span&gt; &lt;span class="pl-s1"&gt;sqlite&lt;/span&gt; &lt;span class="pl-kos"&gt;}&lt;/span&gt; &lt;span class="pl-k"&gt;from&lt;/span&gt; &lt;span class="pl-s"&gt;"https://esm.town/v/stevekrouse/sqlite"&lt;/span&gt;&lt;span class="pl-kos"&gt;;&lt;/span&gt;
&lt;span class="pl-k"&gt;let&lt;/span&gt; &lt;span class="pl-smi"&gt;KEY&lt;/span&gt; &lt;span class="pl-c1"&gt;=&lt;/span&gt; &lt;span class="pl-k"&gt;new&lt;/span&gt; &lt;span class="pl-smi"&gt;URL&lt;/span&gt;&lt;span class="pl-kos"&gt;(&lt;/span&gt;&lt;span class="pl-k"&gt;import&lt;/span&gt;&lt;span class="pl-kos"&gt;.&lt;/span&gt;&lt;span class="pl-c1"&gt;meta&lt;/span&gt;&lt;span class="pl-kos"&gt;.&lt;/span&gt;&lt;span class="pl-c1"&gt;url&lt;/span&gt;&lt;span class="pl-kos"&gt;)&lt;/span&gt;&lt;span class="pl-kos"&gt;.&lt;/span&gt;&lt;span class="pl-c1"&gt;pathname&lt;/span&gt;&lt;span class="pl-kos"&gt;.&lt;/span&gt;&lt;span class="pl-en"&gt;split&lt;/span&gt;&lt;span class="pl-kos"&gt;(&lt;/span&gt;&lt;span class="pl-s"&gt;"/"&lt;/span&gt;&lt;span class="pl-kos"&gt;)&lt;/span&gt;&lt;span class="pl-kos"&gt;.&lt;/span&gt;&lt;span class="pl-en"&gt;at&lt;/span&gt;&lt;span class="pl-kos"&gt;(&lt;/span&gt;&lt;span class="pl-c1"&gt;-&lt;/span&gt;&lt;span class="pl-c1"&gt;1&lt;/span&gt;&lt;span class="pl-kos"&gt;)&lt;/span&gt;&lt;span class="pl-kos"&gt;;&lt;/span&gt;
&lt;span class="pl-kos"&gt;(&lt;/span&gt;&lt;span class="pl-k"&gt;await&lt;/span&gt; &lt;span class="pl-s1"&gt;sqlite&lt;/span&gt;&lt;span class="pl-kos"&gt;.&lt;/span&gt;&lt;span class="pl-en"&gt;execute&lt;/span&gt;&lt;span class="pl-kos"&gt;(&lt;/span&gt;&lt;span class="pl-s"&gt;`select * from &lt;span class="pl-s1"&gt;&lt;span class="pl-kos"&gt;${&lt;/span&gt;&lt;span class="pl-smi"&gt;KEY&lt;/span&gt;&lt;span class="pl-kos"&gt;}&lt;/span&gt;&lt;/span&gt;_users where id = ?`&lt;/span&gt;&lt;span class="pl-kos"&gt;,&lt;/span&gt; &lt;span class="pl-kos"&gt;[&lt;/span&gt;&lt;span class="pl-c1"&gt;1&lt;/span&gt;&lt;span class="pl-kos"&gt;]&lt;/span&gt;&lt;span class="pl-kos"&gt;)&lt;/span&gt;&lt;span class="pl-kos"&gt;)&lt;/span&gt;&lt;span class="pl-kos"&gt;.&lt;/span&gt;&lt;span class="pl-c1"&gt;rows&lt;/span&gt;&lt;span class="pl-kos"&gt;[&lt;/span&gt;&lt;span class="pl-c1"&gt;0&lt;/span&gt;&lt;span class="pl-kos"&gt;]&lt;/span&gt;&lt;span class="pl-kos"&gt;.&lt;/span&gt;&lt;span class="pl-c1"&gt;id&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;It also reveals the existence of Val's very own delightfully simple &lt;a href="https://www.val.town/v/maxm/imggenurl"&gt;image generation endpoint Val&lt;/a&gt;, currently powered by &lt;a href="https://fal.ai/models/fal-ai/fast-lightning-sdxl"&gt;Stable Diffusion XL Lightning on fal.ai&lt;/a&gt;.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;If you want an AI generated image, use https://maxm-imggenurl.web.val.run/the-description-of-your-image to dynamically generate one.&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Here's &lt;a href="https://maxm-imggenurl.web.val.run/a%20fun%20colorful%20raccoon%20with%20a%20wildly%20inapropriate%20hat"&gt;a fun colorful raccoon with a wildly inappropriate hat&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Val are also running their own &lt;a href="https://www.val.town/v/std/openaiproxy"&gt;gpt-4o-mini proxy&lt;/a&gt;, free to users of their platform:&lt;/p&gt;
&lt;div class="highlight highlight-source-ts"&gt;&lt;pre&gt;&lt;span class="pl-k"&gt;import&lt;/span&gt; &lt;span class="pl-kos"&gt;{&lt;/span&gt; &lt;span class="pl-smi"&gt;OpenAI&lt;/span&gt; &lt;span class="pl-kos"&gt;}&lt;/span&gt; &lt;span class="pl-k"&gt;from&lt;/span&gt; &lt;span class="pl-s"&gt;"https://esm.town/v/std/openai"&lt;/span&gt;&lt;span class="pl-kos"&gt;;&lt;/span&gt;
&lt;span class="pl-k"&gt;const&lt;/span&gt; &lt;span class="pl-s1"&gt;openai&lt;/span&gt; &lt;span class="pl-c1"&gt;=&lt;/span&gt; &lt;span class="pl-k"&gt;new&lt;/span&gt; &lt;span class="pl-smi"&gt;OpenAI&lt;/span&gt;&lt;span class="pl-kos"&gt;(&lt;/span&gt;&lt;span class="pl-kos"&gt;)&lt;/span&gt;&lt;span class="pl-kos"&gt;;&lt;/span&gt;
&lt;span class="pl-k"&gt;const&lt;/span&gt; &lt;span class="pl-s1"&gt;completion&lt;/span&gt; &lt;span class="pl-c1"&gt;=&lt;/span&gt; &lt;span class="pl-k"&gt;await&lt;/span&gt; &lt;span class="pl-s1"&gt;openai&lt;/span&gt;&lt;span class="pl-kos"&gt;.&lt;/span&gt;&lt;span class="pl-c1"&gt;chat&lt;/span&gt;&lt;span class="pl-kos"&gt;.&lt;/span&gt;&lt;span class="pl-c1"&gt;completions&lt;/span&gt;&lt;span class="pl-kos"&gt;.&lt;/span&gt;&lt;span class="pl-en"&gt;create&lt;/span&gt;&lt;span class="pl-kos"&gt;(&lt;/span&gt;&lt;span class="pl-kos"&gt;{&lt;/span&gt;
  &lt;span class="pl-c1"&gt;messages&lt;/span&gt;: &lt;span class="pl-kos"&gt;[&lt;/span&gt;
    &lt;span class="pl-kos"&gt;{&lt;/span&gt; &lt;span class="pl-c1"&gt;role&lt;/span&gt;: &lt;span class="pl-s"&gt;"user"&lt;/span&gt;&lt;span class="pl-kos"&gt;,&lt;/span&gt; &lt;span class="pl-c1"&gt;content&lt;/span&gt;: &lt;span class="pl-s"&gt;"Say hello in a creative way"&lt;/span&gt; &lt;span class="pl-kos"&gt;}&lt;/span&gt;&lt;span class="pl-kos"&gt;,&lt;/span&gt;
  &lt;span class="pl-kos"&gt;]&lt;/span&gt;&lt;span class="pl-kos"&gt;,&lt;/span&gt;
  &lt;span class="pl-c1"&gt;model&lt;/span&gt;: &lt;span class="pl-s"&gt;"gpt-4o-mini"&lt;/span&gt;&lt;span class="pl-kos"&gt;,&lt;/span&gt;
  &lt;span class="pl-c1"&gt;max_tokens&lt;/span&gt;: &lt;span class="pl-c1"&gt;30&lt;/span&gt;&lt;span class="pl-kos"&gt;,&lt;/span&gt;
&lt;span class="pl-kos"&gt;}&lt;/span&gt;&lt;span class="pl-kos"&gt;)&lt;/span&gt;&lt;span class="pl-kos"&gt;;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Val developer JP Posma wrote a lot more about Townie in &lt;a href="https://blog.val.town/blog/codegen/"&gt;How we built Townie – an app that generates fullstack apps&lt;/a&gt;, describing their prototyping process and revealing that the current model it's using is Claude 3.5 Sonnet.&lt;/p&gt;
&lt;p&gt;Their current system prompt was refined over many different versions - initially they were including 50 example Vals at quite a high token cost, but they were able to reduce that down to the linked system prompt which includes condensed documentation and just one templated example.

    &lt;p&gt;&lt;small&gt;&lt;/small&gt;Via &lt;a href="https://twitter.com/stevekrouse/status/1828454235756798287"&gt;@stevekrouse&lt;/a&gt;&lt;/small&gt;&lt;/p&gt;


    &lt;p&gt;Tags: &lt;a href="https://simonwillison.net/tags/javascript"&gt;javascript&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/sqlite"&gt;sqlite&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/ai"&gt;ai&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/typescript"&gt;typescript&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/deno"&gt;deno&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/prompt-engineering"&gt;prompt-engineering&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/generative-ai"&gt;generative-ai&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/llms"&gt;llms&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/ai-assisted-programming"&gt;ai-assisted-programming&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/anthropic"&gt;anthropic&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/claude"&gt;claude&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/val-town"&gt;val-town&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/claude-3-5-sonnet"&gt;claude-3-5-sonnet&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/text-to-image"&gt;text-to-image&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/system-prompts"&gt;system-prompts&lt;/a&gt;&lt;/p&gt;



</summary><category term="javascript"/><category term="sqlite"/><category term="ai"/><category term="typescript"/><category term="deno"/><category term="prompt-engineering"/><category term="generative-ai"/><category term="llms"/><category term="ai-assisted-programming"/><category term="anthropic"/><category term="claude"/><category term="val-town"/><category term="claude-3-5-sonnet"/><category term="text-to-image"/><category term="system-prompts"/></entry><entry><title>What we got wrong about HTTP imports</title><link href="https://simonwillison.net/2024/Jul/30/what-we-got-wrong-about-http-imports/#atom-tag" rel="alternate"/><published>2024-07-30T06:33:11+00:00</published><updated>2024-07-30T06:33:11+00:00</updated><id>https://simonwillison.net/2024/Jul/30/what-we-got-wrong-about-http-imports/#atom-tag</id><summary type="html">
    
&lt;p&gt;&lt;strong&gt;&lt;a href="https://deno.com/blog/http-imports"&gt;What we got wrong about HTTP imports&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
HTTP imports are one of the most interesting design features of Deno:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;import { assertEquals } from "https://deno.land/std@0.224.0/assert/mod.ts";
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Six years after their introduction, Ryan Dahl reviews their disadvantages:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Lengthy (non-memorable) URLs littering the codebase&lt;/li&gt;
&lt;li&gt;A slightly cumbersome &lt;code&gt;import { concat } from "../../deps.ts";&lt;/code&gt; pattern for managing dependencies in one place&lt;/li&gt;
&lt;li&gt;Large projects can end up using multiple slightly different versions of the same dependencies&lt;/li&gt;
&lt;li&gt;If a website becomes unavailable, new builds will fail (existing builds will continue to use their cached version)&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Deno 2 - due in September - will continue to support them, but will lean much more on the combination of import maps (design borrowed from modern browsers) and the Deno project's &lt;a href="https://jsr.io/"&gt;JSR&lt;/a&gt; npm competitor. An import map like this:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;{
  "imports": {
    "@std/assert": "jsr:@std/assert@1"
  }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Will then enable import statements that look like this:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;import { assertEquals } from "@std/assert";
&lt;/code&gt;&lt;/pre&gt;

    &lt;p&gt;&lt;small&gt;&lt;/small&gt;Via &lt;a href="https://lobste.rs/s/vfnby3/what_we_got_wrong_about_http_imports"&gt;lobste.rs&lt;/a&gt;&lt;/small&gt;&lt;/p&gt;


    &lt;p&gt;Tags: &lt;a href="https://simonwillison.net/tags/javascript"&gt;javascript&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/ryan-dahl"&gt;ryan-dahl&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/deno"&gt;deno&lt;/a&gt;&lt;/p&gt;



</summary><category term="javascript"/><category term="ryan-dahl"/><category term="deno"/></entry><entry><title>How we built JSR</title><link href="https://simonwillison.net/2024/Apr/12/how-we-built-jsr/#atom-tag" rel="alternate"/><published>2024-04-12T15:49:03+00:00</published><updated>2024-04-12T15:49:03+00:00</updated><id>https://simonwillison.net/2024/Apr/12/how-we-built-jsr/#atom-tag</id><summary type="html">
    
&lt;p&gt;&lt;strong&gt;&lt;a href="https://deno.com/blog/how-we-built-jsr"&gt;How we built JSR&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
Really interesting deep dive by Luca Casonato into the engineering behind the new JSR alternative JavaScript package registry launched recently by Deno.&lt;/p&gt;

&lt;p&gt;The backend uses PostgreSQL and a Rust API server hosted on Google Cloud Run.&lt;/p&gt;

&lt;p&gt;The frontend uses Fresh, Deno’s own server-side JavaScript framework which leans heavily in the concept of “islands”—a progressive enhancement technique where pages are rendered on the server and small islands of interactivity are added once the page has loaded.

    &lt;p&gt;&lt;small&gt;&lt;/small&gt;Via &lt;a href="https://news.ycombinator.com/item?id=40013620"&gt;Hacker News&lt;/a&gt;&lt;/small&gt;&lt;/p&gt;


    &lt;p&gt;Tags: &lt;a href="https://simonwillison.net/tags/javascript"&gt;javascript&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/postgresql"&gt;postgresql&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/progressive-enhancement"&gt;progressive-enhancement&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/rust"&gt;rust&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/deno"&gt;deno&lt;/a&gt;&lt;/p&gt;



</summary><category term="javascript"/><category term="postgresql"/><category term="progressive-enhancement"/><category term="rust"/><category term="deno"/></entry><entry><title>Astro DB</title><link href="https://simonwillison.net/2024/Mar/12/astro-db/#atom-tag" rel="alternate"/><published>2024-03-12T18:02:13+00:00</published><updated>2024-03-12T18:02:13+00:00</updated><id>https://simonwillison.net/2024/Mar/12/astro-db/#atom-tag</id><summary type="html">
    
&lt;p&gt;&lt;strong&gt;&lt;a href="https://astro.build/db/"&gt;Astro DB&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
A new scale-to-zero hosted SQLite offering, described as “A fully-managed SQL database designed exclusively for Astro”. It’s built on top of LibSQL, the SQLite fork maintained by the Turso database team.&lt;/p&gt;

&lt;p&gt;Astro DB encourages defining your tables with TypeScript, and querying them via the Drizzle ORM.&lt;/p&gt;

&lt;p&gt;Running Astro locally uses a local SQLite database. Deployed to Astro Cloud switches to their DB product, where the free tier currently includes 1GB of storage, one billion row reads per month and one million row writes per month.&lt;/p&gt;

&lt;p&gt;Astro itself is a “web framework for content-driven websites”—so hosted SQLite is a bit of an unexpected product from them, though it does broadly fit the ecosystem they are building.&lt;/p&gt;

&lt;p&gt;This approach reminds me of how Deno K/V works—another local SQLite storage solution that offers a proprietary cloud hosted option for deployment.


    &lt;p&gt;Tags: &lt;a href="https://simonwillison.net/tags/javascript"&gt;javascript&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/sqlite"&gt;sqlite&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/typescript"&gt;typescript&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/deno"&gt;deno&lt;/a&gt;&lt;/p&gt;



</summary><category term="javascript"/><category term="sqlite"/><category term="typescript"/><category term="deno"/></entry><entry><title>The first four Val Town runtimes</title><link href="https://simonwillison.net/2024/Feb/8/the-first-four-val-town-runtimes/#atom-tag" rel="alternate"/><published>2024-02-08T18:38:39+00:00</published><updated>2024-02-08T18:38:39+00:00</updated><id>https://simonwillison.net/2024/Feb/8/the-first-four-val-town-runtimes/#atom-tag</id><summary type="html">
    
&lt;p&gt;&lt;strong&gt;&lt;a href="https://blog.val.town/blog/first-four-val-town-runtimes/"&gt;The first four Val Town runtimes&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
Val Town solves one of my favourite technical problems: how to run untrusted code in a safe sandbox. They're on their fourth iteration of this now, currently using a Node.js application that launches Deno sub-processes using the &lt;a href="https://github.com/casual-simulation/node-deno-vm"&gt;node-deno-vm&lt;/a&gt; npm package and runs code in those, taking advantage of the Deno sandboxing mechanism and terminating processes that take too long in order to protect against &lt;code&gt;while(true)&lt;/code&gt; style attacks.

    &lt;p&gt;&lt;small&gt;&lt;/small&gt;Via &lt;a href="https://twitter.com/tmcw/status/1755616125474504960"&gt;@tmcw&lt;/a&gt;&lt;/small&gt;&lt;/p&gt;


    &lt;p&gt;Tags: &lt;a href="https://simonwillison.net/tags/javascript"&gt;javascript&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/nodejs"&gt;nodejs&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/sandboxing"&gt;sandboxing&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/deno"&gt;deno&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/tom-macwright"&gt;tom-macwright&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/val-town"&gt;val-town&lt;/a&gt;&lt;/p&gt;



</summary><category term="javascript"/><category term="nodejs"/><category term="sandboxing"/><category term="deno"/><category term="tom-macwright"/><category term="val-town"/></entry><entry><title>Announcing Deno Cron</title><link href="https://simonwillison.net/2023/Nov/29/announcing-deno-cron/#atom-tag" rel="alternate"/><published>2023-11-29T17:49:31+00:00</published><updated>2023-11-29T17:49:31+00:00</updated><id>https://simonwillison.net/2023/Nov/29/announcing-deno-cron/#atom-tag</id><summary type="html">
    
&lt;p&gt;&lt;strong&gt;&lt;a href="https://deno.com/blog/cron"&gt;Announcing Deno Cron&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
Scheduling tasks in deployed applications is surprisingly difficult. Deno clearly understand this, and they’ve added a new Deno.cron(name, cron_definition, callback) mechanism for running a JavaScript function every X minutes/hours/etc.&lt;/p&gt;

&lt;p&gt;As with several other recent Deno features, there are two versions of the implementation. The first is an in-memory implementation in the Deno open source binary, while the second is a much more robust closed-source implementation that runs in Deno Deploy:&lt;/p&gt;

&lt;p&gt;“When a new production deployment of your project is created, an ephemeral V8 isolate is used to evaluate your project’s top-level scope and to discover any Deno.cron definitions. A global cron scheduler is then updated with your project’s latest cron definitions, which includes updates to your existing crons, new crons, and deleted crons.”&lt;/p&gt;

&lt;p&gt;Two interesting features: unlike regular cron the Deno version prevents cron tasks that take too long from ever overlapping each other, and a backoffSchedule: [1000, 5000, 10000] option can be used to schedule attempts to re-run functions if they raise an exception.


    &lt;p&gt;Tags: &lt;a href="https://simonwillison.net/tags/cron"&gt;cron&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/deno"&gt;deno&lt;/a&gt;&lt;/p&gt;



</summary><category term="cron"/><category term="deno"/></entry><entry><title>deno_python</title><link href="https://simonwillison.net/2023/Aug/12/deno_python/#atom-tag" rel="alternate"/><published>2023-08-12T22:14:10+00:00</published><updated>2023-08-12T22:14:10+00:00</updated><id>https://simonwillison.net/2023/Aug/12/deno_python/#atom-tag</id><summary type="html">
    
&lt;p&gt;&lt;strong&gt;&lt;a href="https://github.com/denosaurs/deno_python"&gt;deno_python&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
A wildly impressive hack: deno_python uses Deno’s FFI interface to load your system’s Python framework (.dll/.dylib/.so) and sets up JavaScript proxy objects for imported Python objects—so you can run JavaScript code that instantiates objects from Python libraries and uses them to process data in different ways.&lt;/p&gt;

&lt;p&gt;The latest release added pip support, so things like ’const np = await pip.import(“numpy”)’ now work.

    &lt;p&gt;&lt;small&gt;&lt;/small&gt;Via &lt;a href="https://news.ycombinator.com/item?id=37086753"&gt;Hacker News&lt;/a&gt;&lt;/small&gt;&lt;/p&gt;


    &lt;p&gt;Tags: &lt;a href="https://simonwillison.net/tags/python"&gt;python&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/deno"&gt;deno&lt;/a&gt;&lt;/p&gt;



</summary><category term="python"/><category term="deno"/></entry><entry><title>Deno 1.34: deno compile supports npm packages</title><link href="https://simonwillison.net/2023/May/25/deno-compile-npm/#atom-tag" rel="alternate"/><published>2023-05-25T17:01:08+00:00</published><updated>2023-05-25T17:01:08+00:00</updated><id>https://simonwillison.net/2023/May/25/deno-compile-npm/#atom-tag</id><summary type="html">
    
&lt;p&gt;&lt;strong&gt;&lt;a href="https://deno.com/blog/v1.34"&gt;Deno 1.34: deno compile supports npm packages&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
This feels like it could be extremely useful: Deno can load code from npm these days (&lt;code&gt;import { say } from "npm:cowsay@1.5.0"&lt;/code&gt;) and now the &lt;code&gt;deno compile&lt;/code&gt; command can resolve those imports, fetch all of the dependencies and bundle them together with Deno itself into a single executable binary. This means pretty much anything that's been built as an npm package can now be easily converted into a standalone binary, including cross-compilation to Windows x64, macOS x64, macOS ARM and Linux x64.


    &lt;p&gt;Tags: &lt;a href="https://simonwillison.net/tags/javascript"&gt;javascript&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/npm"&gt;npm&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/deno"&gt;deno&lt;/a&gt;&lt;/p&gt;



</summary><category term="javascript"/><category term="npm"/><category term="deno"/></entry><entry><title>Weeknotes: sqlite-utils 3.31, download-esm, Python in a sandbox</title><link href="https://simonwillison.net/2023/May/10/weeknotes/#atom-tag" rel="alternate"/><published>2023-05-10T22:07:01+00:00</published><updated>2023-05-10T22:07:01+00:00</updated><id>https://simonwillison.net/2023/May/10/weeknotes/#atom-tag</id><summary type="html">
    &lt;p&gt;A couple of speaking appearances last week - one planned, one unplanned. Plus &lt;code&gt;sqlite-utils 3.31&lt;/code&gt;, &lt;code&gt;download-esm&lt;/code&gt; and a new TIL.&lt;/p&gt;
&lt;h4&gt;Prompt injection video, Leaked Google document audio&lt;/h4&gt;
&lt;p&gt;I participated in the LangChain webinar about prompt injection. The session was recorded, so I extracted my 12 minute introduction to the topic and turned it into &lt;a href="https://simonwillison.net/2023/May/2/prompt-injection-explained/"&gt;a blog post&lt;/a&gt; complete with a Whisper transcription, a video and the slides I used in the talk.&lt;/p&gt;
&lt;p&gt;Then on Thursday I wrote about &lt;a href="https://simonwillison.net/2023/May/4/no-moat/"&gt;the leaked internal Google document&lt;/a&gt; that argued that Google and OpenAI have no meaningful moat given the accelerating pace of open source LLM research.&lt;/p&gt;
&lt;p&gt;This lead to a last minute invitation to participate in a Latent Space Twitter Space about the document, which is now available &lt;a href="https://www.latent.space/p/no-moat#details"&gt;as a podcast&lt;/a&gt;.&lt;/p&gt;
&lt;h4&gt;sqlite-utils 3.31&lt;/h4&gt;
&lt;p&gt;I realized that &lt;a href="https://sqlite-utils.datasette.io/"&gt;sqlite-utils&lt;/a&gt; had been quietly accumulating small fixes and pull requests since the 3.30 release last October, and spent a day tidying those up and turning them into a release.&lt;/p&gt;
&lt;p&gt;Notably, four contributors get credited in &lt;a href="https://sqlite-utils.datasette.io/en/stable/changelog.html#v3-31"&gt;the release notes&lt;/a&gt;: Chris Amico, Kenny Song, Martin Carpenter and Scott Perry.&lt;/p&gt;
&lt;p&gt;Key changes are listed below:&lt;/p&gt;
&lt;blockquote&gt;
&lt;ul&gt;
&lt;li&gt;Automatically locates the SpatiaLite extension on Apple Silicon. Thanks, Chris Amico. (&lt;a href="https://github.com/simonw/sqlite-utils/pull/536"&gt;#536&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;New &lt;code&gt;--raw-lines&lt;/code&gt; option for the &lt;code&gt;sqlite-utils query&lt;/code&gt; and &lt;code&gt;sqlite-utils memory&lt;/code&gt; commands, which outputs just the raw value of the first column of evy row. (&lt;a href="https://github.com/simonw/sqlite-utils/issues/539"&gt;#539&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;Fixed a bug where &lt;code&gt;table.upsert_all()&lt;/code&gt; failed if the &lt;code&gt;not_null=&lt;/code&gt; option was passed. (&lt;a href="https://github.com/simonw/sqlite-utils/issues/538"&gt;#538&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;table.convert(..., skip_false=False)&lt;/code&gt; and &lt;code&gt;sqlite-utils convert --no-skip-false&lt;/code&gt; options, for avoiding a misfeature where the &lt;a href="http://127.0.0.1:8000/python-api.html#python-api-convert"&gt;convert()&lt;/a&gt; mechanism skips rows in the database with a falsey value for the specified column. Fixing this by default would be a backwards-incompatible change and is under consideration for a 4.0 release in the future. (&lt;a href="https://github.com/simonw/sqlite-utils/issues/527"&gt;#527&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;Tables can now be created with self-referential foreign keys. Thanks, Scott Perry. (&lt;a href="https://github.com/simonw/sqlite-utils/pull/537"&gt;#537&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;sqlite-utils transform&lt;/code&gt; no longer breaks if a table defines default values for columns. Thanks, Kenny Song. (&lt;a href="https://github.com/simonw/sqlite-utils/issues/509"&gt;#509&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;Fixed a bug where repeated calls to &lt;code&gt;table.transform()&lt;/code&gt; did not work correctly. Thanks, Martin Carpenter. (&lt;a href="https://github.com/simonw/sqlite-utils/issues/525"&gt;#525&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;h4&gt;download-esm&lt;/h4&gt;
&lt;p&gt;As part of my ongoing mission to figure out how to write modern JavaScript without surrendering to one of the many different JavaScript build tools, I built &lt;a href="https://github.com/simonw/download-esm"&gt;download-esm&lt;/a&gt; - a Python CLI tool for downloading the ECMAScript module versions of an npm package along with all of their module dependencies.&lt;/p&gt;
&lt;p&gt;I wrote more about my justification for building that tool in &lt;a href="https://simonwillison.net/2023/May/2/download-esm/"&gt;download-esm: a tool for downloading ECMAScript modules&lt;/a&gt;.&lt;/p&gt;
&lt;h4&gt;Running Python in a Deno/Pyodide sandbox&lt;/h4&gt;
&lt;p&gt;I'm still trying to find the best way to run untrusted Python code in a safe WebAssembly sandbox.&lt;/p&gt;
&lt;p&gt;My latest attempt takes advantage of Pyodide and Deno. It was inspired by &lt;a href="https://github.com/pyodide/pyodide/issues/3420#issuecomment-1542742906"&gt;this comment&lt;/a&gt; by Milan Raj, showing how Deno can load Pyodide now. Pyodide was previously only available in web browsers.&lt;/p&gt;
&lt;p&gt;I came up with a somewhat convoluted mechanism that starts a Deno process running in a Python &lt;code&gt;subprocess&lt;/code&gt; and then runs Pyodide inside of Deno.&lt;/p&gt;
&lt;p&gt;See &lt;a href="https://til.simonwillison.net/deno/pyodide-sandbox"&gt;Running Python code in a Pyodide sandbox via Deno&lt;/a&gt; for the code and my thoughts on next steps for that prototype.&lt;/p&gt;
&lt;h4&gt;Blog entries this week&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://simonwillison.net/2023/May/4/no-moat/"&gt;Leaked Google document: "We Have No Moat, And Neither Does OpenAI"&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://simonwillison.net/2023/May/4/midjourney-51/"&gt;Midjourney 5.1&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://simonwillison.net/2023/May/2/prompt-injection-explained/"&gt;Prompt injection explained, with video, slides, and a transcript&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://simonwillison.net/2023/May/2/download-esm/"&gt;download-esm: a tool for downloading ECMAScript modules&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://simonwillison.net/2023/May/1/lets-be-bear-or-bunny/"&gt;Let's be bear or bunny&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;Releases this week&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://github.com/simonw/sqlite-utils/releases/tag/3.31"&gt;sqlite-utils 3.31&lt;/a&gt;&lt;/strong&gt; - 2023-05-08&lt;br /&gt;Python CLI utility and library for manipulating SQLite databases&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;TIL this week&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://til.simonwillison.net/deno/pyodide-sandbox"&gt;Running Python code in a Pyodide sandbox via Deno&lt;/a&gt; - 2023-05-10&lt;/li&gt;
&lt;/ul&gt;
    
        &lt;p&gt;Tags: &lt;a href="https://simonwillison.net/tags/projects"&gt;projects&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/python"&gt;python&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/weeknotes"&gt;weeknotes&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/deno"&gt;deno&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/sqlite-utils"&gt;sqlite-utils&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/pyodide"&gt;pyodide&lt;/a&gt;&lt;/p&gt;
    

</summary><category term="projects"/><category term="python"/><category term="weeknotes"/><category term="deno"/><category term="sqlite-utils"/><category term="pyodide"/></entry><entry><title>Making SQLite extensions npm install'able for Node.js, and on deno.land/x for Deno</title><link href="https://simonwillison.net/2023/Mar/29/sqlite-extensions-npm-installable/#atom-tag" rel="alternate"/><published>2023-03-29T22:13:21+00:00</published><updated>2023-03-29T22:13:21+00:00</updated><id>https://simonwillison.net/2023/Mar/29/sqlite-extensions-npm-installable/#atom-tag</id><summary type="html">
    
&lt;p&gt;&lt;strong&gt;&lt;a href="https://observablehq.com/@asg017/making-sqlite-extensions-npm-installable-and-deno"&gt;Making SQLite extensions npm install&amp;#x27;able for Node.js, and on deno.land/x for Deno&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
Alex Garcia figured out how to get his “pip install X” trick for distributing compiled SQLite extensions to work for Node too! Now you can “npm install” 10 of his extensions, including sqlite-regex and sqlite-xsv and sqlite-http and sqlite-html and more, and attach them to a node-sqlite3 or better-sqlite3 connection. He’s bundled them for Deno too!

    &lt;p&gt;&lt;small&gt;&lt;/small&gt;Via &lt;a href="https://datasette.io/discord"&gt;Datasette Discord&lt;/a&gt;&lt;/small&gt;&lt;/p&gt;


    &lt;p&gt;Tags: &lt;a href="https://simonwillison.net/tags/nodejs"&gt;nodejs&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/sqlite"&gt;sqlite&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/npm"&gt;npm&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/deno"&gt;deno&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/alex-garcia"&gt;alex-garcia&lt;/a&gt;&lt;/p&gt;



</summary><category term="nodejs"/><category term="sqlite"/><category term="npm"/><category term="deno"/><category term="alex-garcia"/></entry><entry><title>Playing with ActivityPub</title><link href="https://simonwillison.net/2022/Dec/10/playing-with-activitypub/#atom-tag" rel="alternate"/><published>2022-12-10T00:58:42+00:00</published><updated>2022-12-10T00:58:42+00:00</updated><id>https://simonwillison.net/2022/Dec/10/playing-with-activitypub/#atom-tag</id><summary type="html">
    
&lt;p&gt;&lt;strong&gt;&lt;a href="https://macwright.com/2022/12/09/activitypub.html"&gt;Playing with ActivityPub&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
Tom MacWright describes his attempts to build the simplest possible ActivityPub publication—for a static site powered by Jekyll, where he used Netlify functions to handle incoming subscriptions (storing them in PlanetScale via their Deno API library) and wrote a script which loops through and notifies all of his subscriptions every time he publishes something new.

    &lt;p&gt;&lt;small&gt;&lt;/small&gt;Via &lt;a href="https://lobste.rs/s/xvvjza/playing_with_activitypub"&gt;lobste.rs&lt;/a&gt;&lt;/small&gt;&lt;/p&gt;


    &lt;p&gt;Tags: &lt;a href="https://simonwillison.net/tags/deno"&gt;deno&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/tom-macwright"&gt;tom-macwright&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/mastodon"&gt;mastodon&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/activitypub"&gt;activitypub&lt;/a&gt;&lt;/p&gt;



</summary><category term="deno"/><category term="tom-macwright"/><category term="mastodon"/><category term="activitypub"/></entry><entry><title>Netlify Edge Functions: A new serverless runtime powered by Deno</title><link href="https://simonwillison.net/2022/Apr/19/netlify-edge-functions/#atom-tag" rel="alternate"/><published>2022-04-19T16:46:23+00:00</published><updated>2022-04-19T16:46:23+00:00</updated><id>https://simonwillison.net/2022/Apr/19/netlify-edge-functions/#atom-tag</id><summary type="html">
    
&lt;p&gt;&lt;strong&gt;&lt;a href="https://www.netlify.com/blog/announcing-serverless-compute-with-edge-functions"&gt;Netlify Edge Functions: A new serverless runtime powered by Deno&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
You can now run Deno scripts directly in Netlify’s edge CDN—bundled as part of their default pricing plan. Interesting that they decided to host it on Deno’s Deno Deploy infrastructure. The hello world example is pleasingly succinct:&lt;/p&gt;

&lt;p&gt;export default () =&amp;gt; new Response(“Hello world”)


    &lt;p&gt;Tags: &lt;a href="https://simonwillison.net/tags/serverless"&gt;serverless&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/deno"&gt;deno&lt;/a&gt;&lt;/p&gt;



</summary><category term="serverless"/><category term="deno"/></entry><entry><title>Deno by example</title><link href="https://simonwillison.net/2022/Mar/17/deno-by-example/#atom-tag" rel="alternate"/><published>2022-03-17T01:02:00+00:00</published><updated>2022-03-17T01:02:00+00:00</updated><id>https://simonwillison.net/2022/Mar/17/deno-by-example/#atom-tag</id><summary type="html">
    
&lt;p&gt;&lt;strong&gt;&lt;a href="https://examples.deno.land/"&gt;Deno by example&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
Interesting approach to documentation: a big list of annotated examples illustrating the Deno way of solving a bunch of common problems.

    &lt;p&gt;&lt;small&gt;&lt;/small&gt;Via &lt;a href="https://blog.jim-nielsen.com/2022/deno-is-webby-pt-2/"&gt;Jim Nielsen: Deno is Webby (pt. 2)&lt;/a&gt;&lt;/small&gt;&lt;/p&gt;


    &lt;p&gt;Tags: &lt;a href="https://simonwillison.net/tags/documentation"&gt;documentation&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/deno"&gt;deno&lt;/a&gt;&lt;/p&gt;



</summary><category term="documentation"/><category term="deno"/></entry><entry><title>Deno Deploy Beta 3</title><link href="https://simonwillison.net/2021/Nov/7/deno-deploy-beta-3/#atom-tag" rel="alternate"/><published>2021-11-07T01:51:30+00:00</published><updated>2021-11-07T01:51:30+00:00</updated><id>https://simonwillison.net/2021/Nov/7/deno-deploy-beta-3/#atom-tag</id><summary type="html">
    
&lt;p&gt;&lt;strong&gt;&lt;a href="https://deno.com/blog/deploy-beta3/"&gt;Deno Deploy Beta 3&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
I missed Deno Deploy when it first came out back in June: it’s a really interesting new hosting environment for scripts written in Deno, Node.js creator Ryan Dahl’s re-imagining of Node.js. Deno Deploy runs your code using v8 isolates running in 28 regions worldwide, with a clever BroadcastChannel mechanism (inspired by the browser API of the same name) that allows instances of the server-side code running in different regions to send each other messages. See the “via” link for my annotated version of a demo by Ondřej Žára that got me excited about what it can do.

    &lt;p&gt;&lt;small&gt;&lt;/small&gt;Via &lt;a href="https://til.simonwillison.net/deno/annotated-deno-deploy-demo"&gt;My TILs&lt;/a&gt;&lt;/small&gt;&lt;/p&gt;


    &lt;p&gt;Tags: &lt;a href="https://simonwillison.net/tags/javascript"&gt;javascript&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/ryan-dahl"&gt;ryan-dahl&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/v8"&gt;v8&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/deno"&gt;deno&lt;/a&gt;&lt;/p&gt;



</summary><category term="javascript"/><category term="ryan-dahl"/><category term="v8"/><category term="deno"/></entry><entry><title>Flat Data</title><link href="https://simonwillison.net/2021/May/19/flat-data/#atom-tag" rel="alternate"/><published>2021-05-19T01:05:54+00:00</published><updated>2021-05-19T01:05:54+00:00</updated><id>https://simonwillison.net/2021/May/19/flat-data/#atom-tag</id><summary type="html">
    
&lt;p&gt;&lt;strong&gt;&lt;a href="https://octo.github.com/projects/flat-data"&gt;Flat Data&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
New project from the GitHub OCTO (the Office of the CTO, love that backronym) somewhat inspired by my work on Git scraping: I’m really excited to see GitHub embracing git for CSV/JSON data in this way. Flat incorporates a reusable Action for scraping and storing data (using Deno), a VS Code extension for setting up those workflows and a very nicely designed Flat Viewer web app for browsing CSV and JSON data hosted on GitHub.


    &lt;p&gt;Tags: &lt;a href="https://simonwillison.net/tags/github"&gt;github&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/deno"&gt;deno&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/git-scraping"&gt;git-scraping&lt;/a&gt;&lt;/p&gt;



</summary><category term="github"/><category term="deno"/><category term="git-scraping"/></entry><entry><title>Deno 1.6 Release Notes</title><link href="https://simonwillison.net/2020/Dec/10/deno-16-release-notes/#atom-tag" rel="alternate"/><published>2020-12-10T01:25:48+00:00</published><updated>2020-12-10T01:25:48+00:00</updated><id>https://simonwillison.net/2020/Dec/10/deno-16-release-notes/#atom-tag</id><summary type="html">
    
&lt;p&gt;&lt;strong&gt;&lt;a href="https://deno.land/posts/v1.6"&gt;Deno 1.6 Release Notes&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
Two signature features in Deno 1.6 worth paying attention to: a built-in language server for code editors like VS Code, and the “deno compile” command which can build Deno JavaScript/TypeScript projects into standalone binaries. The ability to build binaries has turned out to be a killer feature of both Go and Rust, so seeing it ship as a default capability of a interpreted dynamic language is fascinating. I would love it if Python followed Deno’s example.


    &lt;p&gt;Tags: &lt;a href="https://simonwillison.net/tags/javascript"&gt;javascript&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/deno"&gt;deno&lt;/a&gt;&lt;/p&gt;



</summary><category term="javascript"/><category term="deno"/></entry><entry><title>Deno is a Browser for Code</title><link href="https://simonwillison.net/2020/May/29/deno-browser-code/#atom-tag" rel="alternate"/><published>2020-05-29T02:36:04+00:00</published><updated>2020-05-29T02:36:04+00:00</updated><id>https://simonwillison.net/2020/May/29/deno-browser-code/#atom-tag</id><summary type="html">
    
&lt;p&gt;&lt;strong&gt;&lt;a href="https://kitsonkelly.com/posts/deno-is-a-browser-for-code/"&gt;Deno is a Browser for Code&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
One of the most interesting ideas in Deno is that code imports are loaded directly from URLs—which can themselves depend on other URL-based packages. On first encounter it feels wrong—obviously insecure. Deno contributor Kitson Kelly provides a deeper exploration of the idea, and explains how the combination of caching and lock files makes it no less secure than code installed from npm or PyPI.

    &lt;p&gt;&lt;small&gt;&lt;/small&gt;Via &lt;a href="https://news.ycombinator.com/item?id=23343799"&gt;Hacker News&lt;/a&gt;&lt;/small&gt;&lt;/p&gt;


    &lt;p&gt;Tags: &lt;a href="https://simonwillison.net/tags/packaging"&gt;packaging&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/deno"&gt;deno&lt;/a&gt;&lt;/p&gt;



</summary><category term="packaging"/><category term="deno"/></entry><entry><title>Deno 1.0</title><link href="https://simonwillison.net/2020/May/13/deno-10/#atom-tag" rel="alternate"/><published>2020-05-13T23:38:27+00:00</published><updated>2020-05-13T23:38:27+00:00</updated><id>https://simonwillison.net/2020/May/13/deno-10/#atom-tag</id><summary type="html">
    
&lt;p&gt;&lt;strong&gt;&lt;a href="https://deno.land/v1"&gt;Deno 1.0&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
Deno is a new take on server-side JavaScript from a team lead by Ryan Dahl, who originally created Node.js. It’s built using Rust and crammed with fascinating ideas—like the ability to import code directly from a URL.


    &lt;p&gt;Tags: &lt;a href="https://simonwillison.net/tags/javascript"&gt;javascript&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/nodejs"&gt;nodejs&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/ryan-dahl"&gt;ryan-dahl&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/rust"&gt;rust&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/deno"&gt;deno&lt;/a&gt;&lt;/p&gt;



</summary><category term="javascript"/><category term="nodejs"/><category term="ryan-dahl"/><category term="rust"/><category term="deno"/></entry><entry><title>2020 Web Milestones</title><link href="https://simonwillison.net/2020/Jan/24/2020-web-milestones/#atom-tag" rel="alternate"/><published>2020-01-24T04:43:16+00:00</published><updated>2020-01-24T04:43:16+00:00</updated><id>https://simonwillison.net/2020/Jan/24/2020-web-milestones/#atom-tag</id><summary type="html">
    
&lt;p&gt;&lt;strong&gt;&lt;a href="https://mike.sherov.com/2020-web-milestones/"&gt;2020 Web Milestones&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
A lot of stuff is happening in 2020! Mike Sherov rounds it up—highlights include the release of Chromium Edge (Microsoft’s Chrome-powered browser for Windows 7+), Web Components supported in every major browser, Deno 1.x, SameSite Cookies turned on by default (which should dramatically reduce CSRF exposure) and Python 2 and Flash EOLs.

    &lt;p&gt;&lt;small&gt;&lt;/small&gt;Via &lt;a href="https://twitter.com/mikesherov/status/1220562604348846081"&gt;@mikesherov&lt;/a&gt;&lt;/small&gt;&lt;/p&gt;


    &lt;p&gt;Tags: &lt;a href="https://simonwillison.net/tags/chrome"&gt;chrome&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/csrf"&gt;csrf&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/flash"&gt;flash&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/internet-explorer"&gt;internet-explorer&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/javascript"&gt;javascript&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/python"&gt;python&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/web"&gt;web&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/deno"&gt;deno&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/samesite"&gt;samesite&lt;/a&gt;&lt;/p&gt;



</summary><category term="chrome"/><category term="csrf"/><category term="flash"/><category term="internet-explorer"/><category term="javascript"/><category term="python"/><category term="web"/><category term="deno"/><category term="samesite"/></entry><entry><title>GitHub Actions ci.yml for deno</title><link href="https://simonwillison.net/2019/Dec/18/github-actions-ciyml-deno/#atom-tag" rel="alternate"/><published>2019-12-18T08:49:40+00:00</published><updated>2019-12-18T08:49:40+00:00</updated><id>https://simonwillison.net/2019/Dec/18/github-actions-ciyml-deno/#atom-tag</id><summary type="html">
    
&lt;p&gt;&lt;strong&gt;&lt;a href="https://github.com/denoland/deno/blob/c93ae0b05a4c4fe5b43a9bd2b6430637b17979d0/.github/workflows/ci.yml"&gt;GitHub Actions ci.yml for deno&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
Spotted this today: it’s one of the cleanest examples I’ve seen of a complex CI configuration for GitHub Actions, testing, linting, benchmarking and building Ryan Dahl’s Deno JavaScript runtime.


    &lt;p&gt;Tags: &lt;a href="https://simonwillison.net/tags/continuous-integration"&gt;continuous-integration&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/github"&gt;github&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/ryan-dahl"&gt;ryan-dahl&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/github-actions"&gt;github-actions&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/deno"&gt;deno&lt;/a&gt;&lt;/p&gt;



</summary><category term="continuous-integration"/><category term="github"/><category term="ryan-dahl"/><category term="github-actions"/><category term="deno"/></entry></feed>