A modern, Typescript-based platform for creating interactive fiction with a powerful event-driven architecture and extensible design.
What is Sharpee?
Sharpee is a comprehensive interactive fiction engine that empowers both authors and developers to create rich, dynamic storytelling experiences. Built with Typescript from the ground up, it provides a robust foundation for everything from simple text adventures to complex narrative systems.
Key Features
Event-Driven Architecture - All state changes are immutable events, ensuring consistency and enabling features like undo/redo
Extension System - Add magic, combat, economics, or any game mechanic through plugins
Rich World Model - Sophisticated entity system with traits, behaviors, and relationships
Natural Language Parser - Understands complex player commands with semantic grammar
Capability System - Clean separation between physical world and abstract game state
Multi-Language Support - Built-in localization and text generation system
Type-Safe Throughout - Full Typescript with strict typing and I-prefix interfaces
It’s raw. It’s so raw, the README references git clone https://github.com/your-org/ instead of a real project. The “Create your first interactive fiction in minutes” part is not here yet, and “For Developers” instructions don’t work:
packages/lang-en-us prepublishOnly$ npm run clean && npm run build │ npm warn Unknown env config “verify-deps-before-run”. This will stop working in the next major version of npm. │ npm warn Unknown env config “_jsr-registry”. This will stop working in the next major version of npm. │ > @sharpee/lang-en-us@1.0.0-alpha.1 clean │ > rimraf dist │ npm warn Unknown env config “verify-deps-before-run”. This will stop working in the next major version of npm. │ npm warn Unknown env config “_jsr-registry”. This will stop working in the next major version of npm. │ > @sharpee/lang-en-us@1.0.0-alpha.1 build │ > tsc │ src/language-provider.ts(8,150): error TS2307: Cannot find module ‘@sharpee/if-domain’ or its corresponding type declarations. │ src/language-provider.ts(448,30): error TS7006: Parameter ‘example’ implicitly has an ‘any’ type. │ src/language-provider.ts(448,39): error TS7006: Parameter ‘index’ implicitly has an ‘any’ type. │ npm error Lifecycle script build failed with error: │ npm error code 2 │ npm error path [path]/sharpee/packages/lang-en-us │ npm error workspace @sharpee/lang-en-us@1.0.0-alpha.1 │ npm error location [path]/sharpee/packages/lang-en-us │ npm error command failed │ npm error command sh -c tsc └─ Failed in 1.1s at [path]/sharpee/packages/lang-en-us
@sharpee/text-service-template:build: tsconfig.json:9:5 - error TS6306: Referenced project ‘[path]/sharpee/packages/core’ must have setting “composite”: true. @sharpee/text-service-template:build: @sharpee/text-service-template:build: 9 { “path”: “../core” }, @sharpee/text-service-template:build: ~~~~~~~~~~~~~~~~~~~~~ @sharpee/text-service-template:build: @sharpee/text-service-template:build: tsconfig.json:10:5 - error TS6306: Referenced project ‘[path]/sharpee/packages/if-domain’ must have setting “composite”: true. @sharpee/text-service-template:build: @sharpee/text-service-template:build: 10 { “path”: “../if-domain” } @sharpee/text-service-template:build: ~~~~~~~~~~~~~~~~~~~~~~~~~~ @sharpee/text-service-template:build: @sharpee/text-service-template:build: @sharpee/text-service-template:build: Found 2 errors in the same file, starting at: tsconfig.json:9 @sharpee/text-service-template:build: @sharpee/text-service-template:build: ELIFECYCLE Command failed with exit code 2.
The whole author documentation past the first page is 404.
I know how much you swear by LLMs, so I have to ask to verify: Are any of these tests written by the LLM? Because I would throw generated tests out for serious conflict-of-interest reasons.
However, if you personally wrote all 2,700+ tests as a sanity check against the LLM, then well-done!
Your tests really should not be left up to a statistical model. They are your opportunity as a software developer to verify a contribution to your project.
Good! Writing your own tests is part of developing those guardrails!
This isn’t an issue specifically with LLMs, either! If another human coder sent me a contribution for such a large project, I wouldn’t want to simply accept “trust me, bro” to greenlight the merge. I’d check the code and have my unit tests (which I had written myself) to verify!
Seconded. There should be a link on the announcement post for the project.
I was interested in reading through the dev diaries until I discovered they were mostly written by an LLM. How do I know the dev diaries have anything to do with the actual implementation, or convey anything that would be useful to me?
If I’m reading this right, even the alpha release announcement was AI-generated, which…if you don’t care about your system enough to tell people about its features, why should any of us care? So hopefully I’m not reading that right.
It looks like this was in fact a problem during development, where the AI designed elaborate interfaces, tested that those interfaces worked…and then completely ignored them and reimplemented the same logic elsewhere without the tests.
I’m with Joey on this; I’d much rather have 27 tests designed by a human programmer who understands what’s being tested and why, than 2,700 tests designed by an LLM who assures you they all pass and everything is great.
I had a look over the package.json files across the project, and it’s good to see the imports are few and sensible.
I am curious to know why jest seems to be used in some parts of the project, while vitest gets used in other parts. Have you found that each testing framework seems to function better for only certain modules?
I thought you just meant that OP had generated the blog posts with an LLM. Which he has… but the AI is the author and refers to itself as “Claude” and everything!
And then the AI wrote the blog post you linked to, explaining what it did wrong.
Really bizarre stuff. If I’m understanding all this right, an AI made an IF system and blogged about it. Did the AI make any sample games too? Did it play them?
The duplication of action code was 100% on me. I had designed the behaviors in world model and then was a little absent-minded about it. Admittedly this is a pattern when using LLMs. You can have it very quickly write swaths of code, but if you’re not paying attention, it will do something off the rails. As mentioned in the blog, this is when we introduced architecture structure tests to prevent a similar failure.
A great deal of Sharpee was built while I was learning how to build Sharpee using Claude.
One of the goals of this project was to lean into Claude to do most of the work. I have blogged about that since day one. My regular job is as an enterprise application architect and understanding the capabilities of LLMs is critical to being able to work in today’s world. This is the way things are going and it’s clear major companies are only going to hire engineers with knowledge of LLMs and their use cases.
After this last week I’m convinced that with guardrails, a small team can build complex software using Claude Code with Opus 4.1.
There are references to “vibe coding” all over, but having gone through this process, I think senior software engineers and architects can use Claude Code as a serious code generation tool and extract a higher level set of results. Vibe coding to me is like the guy that created the T app and forgot about security. That’s not the LLM’s fault. That’s because a lot of “engineers” don’t have the experience to direct a technical project properly and define requirements like “data security”. Sharpee is just a game development platform, it’s open source, and this is a hobby. If the only thing that comes out of it is I personally can publish my own stories with it, I am completely okay with that.
Sharpee is alpha. There is still a lot of work to do, but the basic architecture has been proven. Cloak of Darkness works. An extension that I need for a representative game works and it’s not trivial.
I still have the fluent Forge layer and a standard Text Service/Client to build. There are still a of areas of the repo that need to be organized and cleaned up. I’m having a lot of fun.
That was over a week ago. Nearly everything related to that has been repaired or replaced. It’s not about bragging. It’s about transparency. I make no bones about using Claude and when it or I make small or large blunders. That’s a part of being honest with its capabilities and finding ways to keep it going in an approved direction with expected results.
This is all new territory. Everyone is still learning what they can and cannot do.
This is funny. That extension was meant to be private and I forgot to add it to .gitignore. If I can wrangle a small story together for the IFComp, I didn’t want any of the code published ahead of time. It’s been removed, but it is in the history.
No blood was spilled in the making of this IF platform.