The Camel Cometh
The Camel has come to Aspire.
I have worked in Perl off and on for about 16 years now. I started working with it in 2010 by chance. I would learn that I didn’t even know of Perl’s existence until after it was considered a dead language. Along the way I’ve seen lots of signs of life in the ecosystem, but it’s scattered. On the spectrum of ghost town to thriving ecosystem, it certainly lives in the middle.
How many people reading this have ever even really used Perl? Your container images almost certainly resolve the command ‘perl -v’ unless you’ve opted specifically for one of the extreme lightweight distros - which is something I learned along the way.
I don’t blame people who call it a dead language.
Never forget: What is dead may never die.
With the preamble out of the way - I’ll be blunt: I didn’t choose to do make this integration. I was baited into it.
When I first heard about Aspire, I was just excited to try it as a user. I was always annoyed at starting up individual apps when making an api that had something else calling it. It was intriguing to do it in one “app.” I knew there were other frameworks to be used, but I saw too much yaml and I hate secret key/value memorization tests and since it wasn’t forced upon me I just never worked much in distributed systems.
As I got to tinkering with Aspire I watched as the team started demoing with languages outside of dotnet. I thought that was really cool, until I happened to see that one of those was Python and I got… flustered. My first professional job was in Python and I just can’t understand how it won the scripting language wars, I really liked Perl much more, which I came to after Python. Perl’s got a lot of nice things about it and the package management system is really solid when you consider it kinda started in 1995. I’ve been seeing Python become more official in the last several years - from being baked into Excel to getting official tabbed documentation throughout Microsoft Learn articles - it taunts me.
I started lurking in the discord back when it was a channel the DotNetEvolution server. Once they set up their own Discord I eventually began perusing the guide to making an integration which was pinned in the Discord’s #building-resources-and-integrations channel. Then I found out about the Community Toolkit which had a few of other languages supported: Go, Rust, and Java - but no Perl. So I got curious and began creating a Perl integration in September.
Looking back at the questions I was asking in the Discord I was attempting to start with Perl as a container, because I still wasn’t quite understanding the full picture.
By October I was able to see Perl called via Aspire, and communicating with the dashboard via stderr but I was just scratching the surface. At this point, I’d gotten into looking around the Community Toolkit which exposed me to dev containers, which was a nice side quest.
Around November, Aspire did it a-damn-gain. With version 13, Python got top billing as a “First Class” crying and screaming language in the Aspire repo itself, along with a demo of debugging it from the Apphost. Utter decadence. Extremely distasteful.
Writing an integration was a nice way to learn more about Aspire internals, and I had no idea what I was getting myself into in late September when I started. I had to pivot from just making an integration and committed to trying to match Python’s “first-class” feature set with Perl - for honor.
As I made progress, I kept banging my head up against Python features that ultimately were internal only at the time because Aspire used internal types / apis to let Python be an all-star.
I’m not jealous, please don’t write that I am jealous.
By this point it’s December and I’m figuring out OpenTelemetry (see below) in Perl to have more proper communication with the dashboard, but progress is slow. I’ve only got so much spare time in the week. Around this time work was pushing us towards using more AI, so I started to play with it and was unimpressed at first, but a particular blog post by Jonathan Channon really shook me out of the negativity and back into the curiosity phase. After some ah-ha moments at work, I got a $10 dollar Copilot subscription for home to practice more.
I will spare you a big “I was wrong and agentic coding is awesome.” tanget here and just say - briefly - that I started leveraging Copilot with great success. I had Copilot compare what I had already written of the Perl integration to the Python integration. From that analysis I had it create a plan to get the Perl integration to feature parity with actionable steps for the features. I told it to make roadmap items when it hit internal boundaries. The steps were placed in a chart and details were linked below. It was a fantastic tool for being able to keep my head in the project when I would have to drop it or pick it up after days of not touching it. It also helped me keep the agent working in small enough chunks that I could monitor it and actually code review what it was putting out and understand what I was making.
This basically was the pathway for me to leverage my tiny 1-2 hour window of spare time after work and family time into something “useful” while making that experience pleasant enough that I didn’t end up leaving the project abandoned.
I have now successfully merged it to main in the Community Toolkit for the 13.3 release.
For full transparency, since I mentioned AI usage. The subisdization period ends on 6/1/2026. My April usage - mostly Claude Opus 4.6 and some GPT 5.4 - only ended up burning $28.60 in tokens. A good chunk of that was because for April I tried out the $39 dollar copilot plan as I was using all my requests on the $10 dollar plan. I was NOWHERE near able to utilize the full $39 dollar plan with my limited ‘programming for myself’ time. I did want to see how much more I could squeeze out of it without being bound to 300 requests of the $10 dollar plan, though. I was burning requests towards the end of the month on ideas as much as I could, but I still didn’t make it through 70% of my requests.
I’m not using AI like some of the people you read about doing squads or multi agent workflows. Just one person one agent in the loop thinking through and shaping the code. Even with extra attempts at usage my unsubsidized bill would have only been $28.60 using primarily Claude Opus 4.6 - the most expensive model at that time- for most of April.
Don’t tokenmaxx, you should be okay on cost, keep an eye on it.
Big Learnings
Number 1: Dev Containers
I’d never had experience working with a dev container. I now have a decent amount of experience working with them and configuring them. The Community Toolkit is configured with one, and instead of fighting it I leaned into trying it. It was fairly simple to just get the extensions and let VS Code spin it up. That lead to playing with options and tweaking it to add things related to Perl. It was a great way to walk into an existing setup that works and come out of it understanding what various pieces of the devcontainer.json are doing and used for - not to mention how to shell out commands after the container builds.
Number 2: Github Actions
I’ve only ever used Azure Pipelines, and because I chose to integrate with the Community Toolkit I got a crash course in how to use Github Actions. I also learned that the official Github images for the Runners include Perl (even on Windows!) which was a nice treat to simplifying what I needed to get my integration tests working in the workflow.
Number 3: Perl kinda cooked with Package Management
CPAN, which you can read about on wikipedia, began development in 1993, and has been active for over 30 years now. It released in 1995!
Number 4: Some BRAVE soul made an OpenTelemetry SDK in Perl!
The biggest shout out to JJAtria for his work on the OpenTelemetry::SDK library! That really was what made the Perl Integration feel so much better with minimal effort. The hardest thing was figuring out exactly how to get it to build on Windows - an area of Perl that receives little love. I ultimately ended up making a full Windows developer setup guide which was immensely helpful in truly understanding more about how Perl works in general AND how to get OpenTelemetry working with the Google Protobuf libraries - even on Windows.
Number 5: Aspire has a TON of Uses
I think one of the coolest things I had an idea to do was, with a language like Perl that has a lot of dead zones in what it provides, Aspire with LLMs could help reviatlize it. For example, there’s no Azure SDK in Perl. There are several little Azure libraries, but they are largely one off service wrappers that are abandoned. Aspire allows us to use emulators in containers to run against. That means we could easily iterate with live integration tests against Key Vault or what have you in order to flesh out weak spots in the Perl ecosystem.
You could just inject your library under development into an Aspire app and point your scripts to use that library as you develop it. All languages could do this, but it would be a way to use LLMs to spruce up the place with firm testable guardrails.
Then you can have your agent synthesize requirements from other language’s SDKs and help you create a roadmap to building the features required with emulators run via Aspire as the playground. It would let you easily have a firm integration test environment to play with as you summon things into existence.
The agent will get itself into loops finding errors and fixing them because straight to camera Aspire gives it eyes.
Marketing send me a check.
It’s been very interesting being a fan of Aspire as someone who does not use it at all for deployment. It is just a fantastic development tool.
Summary
I have things about the integration that I already don’t like and will iterate against, but it’s made, it works, and it orchestrates Perl projects.
What it can do already
- It has the ability to use all 3 of the big package managers
- You can model a script that runs once or as a service
- You can model an API
- You can add a separate Perl environment (in Linux, for now)
- It has the ability to put out a dockerfile for the resource
Looking forward:
- I want to add debugging
- I want to create a package manager / package API instead of having the cute .WithCpanminus / .WithCarton methods..
- I want to really get the publish docker file working
- I would like to create a ContainerResource for it with sane defaults (for like worker services or apis).
- I would like to equip it to work with Typescript apphosts.
I’ve got a quick start guide for how to use it over at nuget
I’ve got detailed documentation for how to use it over at the Aspire.dev site here aspire.dev/integrations
I’ve made some samples - and will be continuing to add to them - you can view them at github.com/Omnideth/aspire-perl-examples
I’ll write more as I add more features!