add draft blog post and license
This commit is contained in:
parent
a3fd8aad45
commit
797a1f14cd
33
LICENSE
Normal file
33
LICENSE
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2026 Living Software Ltd
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
This repository contains a port of Allium skills to pi.dev format.
|
||||||
|
The upstream Allium content (reference documents, skill methodologies)
|
||||||
|
is copyright (c) 2026 JUXT Ltd and licensed under the MIT License.
|
||||||
|
|
||||||
|
Port adapter files (SKILL.md frontmatter modifications) are also
|
||||||
|
released under the MIT License.
|
||||||
|
|
||||||
|
Upstream: https://github.com/juxt/allium
|
||||||
|
Allium docs: https://juxt.github.io/allium/
|
||||||
116
README.md
Normal file
116
README.md
Normal file
@ -0,0 +1,116 @@
|
|||||||
|
# Allium for Pi.dev
|
||||||
|
|
||||||
|
Port of [Allium](https://github.com/juxt/allium) (v3) to [pi.dev](https://pi.dev) skills.
|
||||||
|
|
||||||
|
Allium is a formal language for capturing software behaviour at the domain level. It sits between informal feature descriptions and implementation, providing a precise way to specify what software does without prescribing how it's built.
|
||||||
|
|
||||||
|
## What this is
|
||||||
|
|
||||||
|
This repository ports Allium's AI skills from the Claude Code plugin format to pi.dev skills, while keeping upstream content referenced by symlink rather than copied. The goal: stay in sync with upstream Allium without maintaining a full fork.
|
||||||
|
|
||||||
|
## Skills
|
||||||
|
|
||||||
|
| Skill | Invocation | Purpose |
|
||||||
|
|-------|------------|---------|
|
||||||
|
| **allium** | `/skill:allium` | Root skill — routing table and language reference |
|
||||||
|
| **elicit** | `/skill:elicit` | Elicit requirements and design decisions from stakeholders |
|
||||||
|
| **distill** | `/skill:distill` | Extract a `.allium` spec from existing code |
|
||||||
|
| **propagate** | `/skill:propagate` | Generate test obligations from a `.allium` spec |
|
||||||
|
| **tend** | `/skill:tend` | Maintain and evolve `.allium` specs (ported from Claude agent) |
|
||||||
|
| **weed** | `/skill:weed` | Check spec-code alignment (ported from Claude agent) |
|
||||||
|
|
||||||
|
## Directory layout
|
||||||
|
|
||||||
|
```
|
||||||
|
pi-allium-port/
|
||||||
|
├── allium-main/ ← git clone of juxt/allium (upstream)
|
||||||
|
├── .pi/
|
||||||
|
│ └── skills/
|
||||||
|
│ ├── allium/
|
||||||
|
│ │ ├── SKILL.md ← adapted frontmatter + upstream content
|
||||||
|
│ │ └── references/ → ../../../allium-main/references/
|
||||||
|
│ ├── elicit/
|
||||||
|
│ │ ├── SKILL.md
|
||||||
|
│ │ └── references/ → symlinks to allium-main/
|
||||||
|
│ ├── distill/
|
||||||
|
│ │ ├── SKILL.md
|
||||||
|
│ │ └── references/ → symlinks to allium-main/
|
||||||
|
│ ├── propagate/
|
||||||
|
│ │ ├── SKILL.md
|
||||||
|
│ │ └── references/ → symlinks to allium-main/
|
||||||
|
│ ├── tend/
|
||||||
|
│ │ ├── SKILL.md
|
||||||
|
│ │ └── references/ → symlinks to allium-main/
|
||||||
|
│ └── weed/
|
||||||
|
│ ├── SKILL.md
|
||||||
|
│ └── references/ → symlinks to allium-main/
|
||||||
|
├── turn-limit/ ← test target (pi-turn-limit extension)
|
||||||
|
└── README.md ← this file
|
||||||
|
```
|
||||||
|
|
||||||
|
## Symlink strategy
|
||||||
|
|
||||||
|
Each skill's `references/` directory contains symlinks pointing into `allium-main/`. This means:
|
||||||
|
|
||||||
|
- **Upstream updates propagate automatically** — when `allium-main` is updated (e.g., `git pull`), all referenced content is current.
|
||||||
|
- **No content duplication** — the port maintains only the SKILL.md frontmatter adapters, not copies of reference documents.
|
||||||
|
- **Relative paths** — symlinks use relative paths so the structure is portable (as long as `allium-main/` stays in the same relative position).
|
||||||
|
|
||||||
|
### Staying in sync
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd allium-main
|
||||||
|
git pull origin main
|
||||||
|
```
|
||||||
|
|
||||||
|
That's it. The symlinks ensure all skills see the updated content immediately.
|
||||||
|
|
||||||
|
## Prerequisites
|
||||||
|
|
||||||
|
- [pi.dev](https://pi.dev) installed and configured
|
||||||
|
- [Allium CLI](https://juxt.github.io/allium/installation) installed (for `allium check` validation)
|
||||||
|
- Clone this repository with `allium-main/` present
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
1. Open pi in this directory: `pi -p`
|
||||||
|
2. Invoke skills with `/skill:allium`, `/skill:elicit`, `/skill:distill`, `/skill:propagate`, `/skill:tend`, `/skill:weed`
|
||||||
|
3. Skills guide the model through Allium workflows
|
||||||
|
|
||||||
|
## Known limitations vs Claude Code version
|
||||||
|
|
||||||
|
| Feature | Claude Code | Pi.dev port | Notes |
|
||||||
|
|---------|-------------|-------------|-------|
|
||||||
|
| **Model selection** | Agents run on specific models (e.g., Opus for tend/weed) | Runs on default model | Pi has no native agent model selection |
|
||||||
|
| **Tool restrictions** | Agents have scoped tool permissions | No tool scoping | Skills can use any tool the model has |
|
||||||
|
| **Auto-trigger** | `auto_trigger` activates skills on file patterns/keywords | Manual invocation only | Pi uses `disable-model-invocation` instead |
|
||||||
|
| **Post-write hooks** | `allium-check.mjs` runs automatically after Edit/Write | Manual `allium check` instruction in skills | Skills instruct the model to run validation, but it's not automatic |
|
||||||
|
| **Rules** | `.claude/rules/` with glob-based activation | Content folded into SKILL.md or references | No glob-based rule activation in pi |
|
||||||
|
| **Syntax rules** | Dedicated rules file with anti-patterns | Symlinked into `references/allium-rules.md` | Same content, different delivery mechanism |
|
||||||
|
|
||||||
|
## Tested against
|
||||||
|
|
||||||
|
The [pi-turn-limit](https://gitea.apps.sustainabledelivery.com/QWAN/monotonic-pi-extensions) extension served as the test target:
|
||||||
|
|
||||||
|
- **Distill**: Extracted `.allium` spec from existing code
|
||||||
|
- **Propagate**: Generated 30+ test obligations from the spec
|
||||||
|
- **Elicit**: Explored "disable turn limit" feature requirements
|
||||||
|
- **TDD cycle**: Red → Green using propagate-generated tests
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
Allium is licensed under the [MIT License](https://opensource.org/licenses/MIT), copyright (c) 2026 JUXT Ltd.
|
||||||
|
|
||||||
|
This port adapts the Allium skills for pi.dev. The upstream Allium content (reference documents, skill methodologies) remains the intellectual property of JUXT Ltd under the MIT License. The port adapter files (SKILL.md frontmatter) are also released under MIT.
|
||||||
|
|
||||||
|
See [LICENSE](./LICENSE) for full terms.
|
||||||
|
|
||||||
|
## Attribution
|
||||||
|
|
||||||
|
- **Allium**: [juxt/allium](https://github.com/juxt/allium) by JUXT Ltd
|
||||||
|
- **Allium documentation**: [juxt.github.io/allium](https://juxt.github.io/allium/)
|
||||||
|
- **Pi.dev**: [pi.dev](https://pi.dev)
|
||||||
|
|
||||||
|
## Contributing
|
||||||
|
|
||||||
|
If you find issues with the port or have improvements, please open an issue or pull request. For Allium language questions, refer to the [upstream repository](https://github.com/juxt/allium).
|
||||||
@ -136,11 +136,11 @@ The Claude Code version runs `allium-check.mjs` as a PostToolUse hook on Edit/Wr
|
|||||||
### Phase 7: Documentation and upstream
|
### Phase 7: Documentation and upstream
|
||||||
_Goal: publishable result._
|
_Goal: publishable result._
|
||||||
|
|
||||||
- [ ] Add README.md with attribution (MIT license from JUXT)
|
- [x] Add README.md with attribution (MIT license from JUXT)
|
||||||
- [ ] Add LICENSE
|
- [x] Add LICENSE
|
||||||
- [ ] Document the symlink-based approach for staying in sync with upstream
|
- [x] Document the symlink-based approach for staying in sync with upstream
|
||||||
- [ ] Document known limitations vs Claude Code version
|
- [x] Document known limitations vs Claude Code version
|
||||||
- [ ] Write blog post draft (separate file)
|
- [x] Write blog post draft (separate file)
|
||||||
- [ ] Share with allium team and pi.dev community
|
- [ ] Share with allium team and pi.dev community
|
||||||
|
|
||||||
## Key URLs
|
## Key URLs
|
||||||
|
|||||||
146
blog-post-draft.md
Normal file
146
blog-post-draft.md
Normal file
@ -0,0 +1,146 @@
|
|||||||
|
# Porting Allium to Pi.dev: Keeping Upstream by Reference
|
||||||
|
|
||||||
|
The below (from 'As the agent said')was generated by a coding agent, after implementation. The agent has not picked up on that we could replicate the behaviour of claude code hooks inside a Pi extension. I didn't go for that, yet, as I wanted to make it work, then make it right.
|
||||||
|
|
||||||
|
There are a couple of third party skills I want to take with me from Claude Code to [Pi](https://pi.dev). Anything markdown and scripts is a matter of moving things around, as Pi supports the agents skill standard.
|
||||||
|
|
||||||
|
Plugins with agents are a bit different. The mapping is not one-on-one, and that is by design. Pi follows the unix philosophy of small, composable tools, Pi itself being one - invoke with `Pi -p` or `--json` for non-interactive use. The interactive prompt with its' fast `/reload` feels more like a Lisp REPL or Smalltalk workspace.
|
||||||
|
|
||||||
|
I come from Claude Code. I use it in a variety of ways. Sometimes quickly building out a prototype in as close to production quality as possible, taking bigger steps after iterative brainstorming. Sometimes in-the-loop with short cycles when I want something small and focused, or am exploring how a particular flow with agents or llms' works.
|
||||||
|
|
||||||
|
Surprisingly [Allium](https://github.com/juxt/allium) adds value for both cases. Allium to me is conversational formal verification. The conversation can be more detailed, while staying playful and iterative. I can generate tests, or take an implementation, and have it find gaps.
|
||||||
|
|
||||||
|
Read on for a brief explanation of a gap found in [pi-turn-limit](https://gitea.apps.sustainabledelivery.com/QWAN/monotonic-pi-extensions). I made pi-turn-limit exploring how far `/reload` and a local model would go in making an extensoin. Allium + the same local model found a gap, and helped make a new feature with tests. Directed by claude code. That non-interactive mode of `Pi` makes iterating in a loop easy.
|
||||||
|
|
||||||
|
Enjoy,
|
||||||
|
|
||||||
|
Willem van en Ende
|
||||||
|
|
||||||
|
P.S. I see I need to rename the skills. Will probably be skill:allium-* instead of skill:*
|
||||||
|
|
||||||
|
# As the agent said...
|
||||||
|
|
||||||
|
(agent was Pi with Qwen3.6-27b)
|
||||||
|
|
||||||
|
|
||||||
|
> How to adapt an AI agent skill framework for a new platform without forking the source.
|
||||||
|
|
||||||
|
[Allium](https://github.com/juxt/allium) is a formal language for specifying software behavior at the domain level. It sits between informal feature descriptions and implementation code, giving AI agents something more structured to work with than raw Markdown prompts.
|
||||||
|
|
||||||
|
Allium ships as a Claude Code plugin with six skills: **elicit**, **distill**, **propagate**, **tend**, and **weed** (plus a root skill for routing). Each skill is a SKILL.md file with frontmatter and a body of instructions, supported by reference documents.
|
||||||
|
|
||||||
|
When I wanted to use Allium with [pi.dev](https://pi.dev), I faced a choice: fork the entire repository and maintain a parallel copy, or find a way to reference the upstream content directly. I chose the latter.
|
||||||
|
|
||||||
|
## The symlink strategy
|
||||||
|
|
||||||
|
The key insight: most of Allium's content is universal — the language reference, the elicitation methodology, the distillation workflow. What's platform-specific is the frontmatter (metadata format) and the invocation paths (`/allium:elicit` vs `/skill:elicit`).
|
||||||
|
|
||||||
|
So the port structure is:
|
||||||
|
|
||||||
|
```
|
||||||
|
.pi/skills/elicit/
|
||||||
|
├── SKILL.md ← thin adapter: pi frontmatter + invocation paths
|
||||||
|
└── references/ ← symlinks to upstream
|
||||||
|
├── language-reference.md → ../../../../allium-main/references/language-reference.md
|
||||||
|
└── library-spec-signals.md → ../../../../allium-main/skills/elicit/references/library-spec-signals.md
|
||||||
|
```
|
||||||
|
|
||||||
|
The SKILL.md files are thin adapters. They change the YAML frontmatter from Claude Code format to pi.dev format, update skill invocation references, and include a few pi-specific instructions. Everything else flows through symlinks.
|
||||||
|
|
||||||
|
**Result**: when upstream Allium updates, I run `git pull` in `allium-main/` and the port is current. No merge conflicts, no duplication, no drift.
|
||||||
|
|
||||||
|
## What changed
|
||||||
|
|
||||||
|
### Frontmatter
|
||||||
|
|
||||||
|
Claude Code plugins use `name`, `description`, `version`, and `auto_trigger`. Pi.dev skills use `name`, `description`, `disable-model-invocation`, `license`, and `metadata`:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
---
|
||||||
|
name: elicit
|
||||||
|
description: Elicit requirements and design decisions
|
||||||
|
disable-model-invocation: true
|
||||||
|
license: MIT
|
||||||
|
metadata:
|
||||||
|
upstream: https://github.com/juxt/allium
|
||||||
|
version: 3
|
||||||
|
---
|
||||||
|
```
|
||||||
|
|
||||||
|
### Invocation paths
|
||||||
|
|
||||||
|
Every `/allium:X` becomes `/skill:X`. The routing table in the root skill maps tasks to the correct skill:
|
||||||
|
|
||||||
|
| Task | Claude Code | Pi.dev |
|
||||||
|
|-----------|---------------------|--------------------|
|
||||||
|
| Root | `/allium` | `/skill:allium` |
|
||||||
|
| Elicit | `/allium:elicit` | `/skill:elicit` |
|
||||||
|
| Distill | `/allium:distill` | `/skill:distill` |
|
||||||
|
| Propagate | `/allium:propagate` | `/skill:propagate` |
|
||||||
|
|
||||||
|
### Agents become skills
|
||||||
|
|
||||||
|
Allium's **tend** and **weed** are Claude Code agents — they specify a model (Opus) and tool permissions (Read, Glob, Grep, Edit, Write, Bash). Pi.dev doesn't have native agent support with model selection or tool scoping.
|
||||||
|
|
||||||
|
The pragmatic solution: port them as regular skills with `disable-model-invocation: true`. They run on whatever model you're using, with whatever tools are available. The methodology is the same; only the enforcement differs.
|
||||||
|
|
||||||
|
### Rules become references
|
||||||
|
|
||||||
|
Claude Code's `.claude/rules/allium.md` contains syntax rules and anti-patterns that activate on glob patterns. Pi.dev has no glob-based rule activation.
|
||||||
|
|
||||||
|
Solution: symlink the rules file into `references/allium-rules.md` and add a "Syntax rules" section to each skill instructing the model to read it before writing `.allium` files. Same content, different delivery.
|
||||||
|
|
||||||
|
### Hooks become instructions
|
||||||
|
|
||||||
|
The Claude Code version runs `allium-check.mjs` as a PostToolUse hook — every time the model writes or edits a file, validation runs automatically. Pi.dev has no equivalent hook system.
|
||||||
|
|
||||||
|
Solution: add a "Verification" section to skills that write `.allium` files, instructing the model to run `allium check <file>` after writing. It's not automatic, but it's explicit.
|
||||||
|
|
||||||
|
## Testing with a real project
|
||||||
|
|
||||||
|
I tested the port against [pi-turn-limit](https://gitea.apps.sustainabledelivery.com/QWAN/monotonic-pi-extensions), a pi.dev extension that limits conversation turns.
|
||||||
|
|
||||||
|
The workflow:
|
||||||
|
|
||||||
|
1. **Distill** (`/skill:distill`) — extracted a `.allium` spec from existing TypeScript code. The spec captured turn counting, enable/disable, config persistence, and UI separation.
|
||||||
|
2. **Propagate** (`/skill:propagate`) — generated 30 test obligations: 10 unit tests for pure functions, 8 config/command tests, 3 entity state tests, and 5 rule tests.
|
||||||
|
3. **Elicit** (`/skill:elicit`) — explored a new "disable turn limit" feature. Three design decisions emerged: unlimited means no boundary check, hard reset on re-enable, and config value is not entity state.
|
||||||
|
4. **TDD cycle** — wrote 8 new tests from propagate output (red: 8 failing), implemented unlimited mode, ran tests (green: 29/29 passing).
|
||||||
|
|
||||||
|
The ported skills produced the same quality of output as the Claude Code originals.
|
||||||
|
|
||||||
|
## Trade-offs
|
||||||
|
|
||||||
|
The symlink strategy works well but has trade-offs:
|
||||||
|
|
||||||
|
| Advantage | Trade-off |
|
||||||
|
|-----------------------------|----------------------------------------------------------|
|
||||||
|
| Zero content duplication | Symlinks must resolve — repo structure matters |
|
||||||
|
| Automatic upstream sync | No automatic sync — you still need to `git pull` |
|
||||||
|
| Minimal maintenance surface | Platform gaps (agents, hooks, rules) require workarounds |
|
||||||
|
| Clear attribution | Upstream content remains under JUXT's copyright |
|
||||||
|
|
||||||
|
## Known limitations
|
||||||
|
|
||||||
|
The port doesn't replicate three Claude Code features (yet):
|
||||||
|
|
||||||
|
1. **Model selection** — tend/weed run on your default model, not Opus
|
||||||
|
2. **Tool scoping** — skills can use any available tool, not a restricted set
|
||||||
|
3. **Automatic validation** — `allium check` is instructed, not enforced
|
||||||
|
|
||||||
|
|
||||||
|
## Conclusion
|
||||||
|
|
||||||
|
The symlink-based port pattern works well for adapting AI agent skills across platforms when:
|
||||||
|
|
||||||
|
- The core methodology is platform-agnostic
|
||||||
|
- Platform differences are mostly in metadata and invocation
|
||||||
|
- You want to stay in sync with upstream without forking
|
||||||
|
|
||||||
|
It's not a perfect solution — the agent and hook workarounds are manual. But it's maintainable, and it produces results.
|
||||||
|
|
||||||
|
The port is available at [github.com/.../pi-allium-port](https://github.com/.../pi-allium-port) (link TBD).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
*Allium is developed by [JUXT Ltd](https://github.com/juxt) and licensed under MIT. This port adapts Allium for pi.dev while keeping upstream content by reference.*
|
||||||
4113
transcripts/port-agents-transcript
Normal file
4113
transcripts/port-agents-transcript
Normal file
File diff suppressed because one or more lines are too long
Loading…
x
Reference in New Issue
Block a user