-
Posts
1,559 -
Joined
-
Last visited
-
Days Won
49
gebeer last won the day on June 1
gebeer had the most liked content!
Profile Information
-
Gender
Male
-
Location
Thailand
Recent Profile Visitors
17,342 profile views
gebeer's Achievements
-
gebeer started following New blog: ProcessWire and AI , ProcessWire updates are fun again (or: less clickery, more coffee) , PW 3.0.265 – Core updates and AgentTools updates and 1 other
-
I’ve been doing regular ProcessWire updates for years, and honestly, they’re usually pretty painless. Ryan keeps things sane, modules mostly behave, and if you don’t wait forever between updates, compatibility drama is rare. But there’s still one part that always felt a bit… clicky. Check module updates. Download paid modules ZIP files. Upload/install. Refresh modules. Commit. Repeat. Then core. Then smoke test. Not hard, just enough tiny steps to make you think: “surely my robot coworker can do this?” So I made a reusable AI-agent skill for doing ProcessWire system updates through DDEV CLI: https://github.com/gebeer/processwire-ai-docs/tree/main/skills/processwire-system-update-cli plays nice with https://github.com/gebeer/processwire-ai-docs/tree/main/skills/processwire-ddev-cli Don't have ddev? Too bad, consider using it or tweak the skill. Or use Ryan's AgentTools module. Your agent will figure it out, eventually. What it does The workflow is basically: Ask ProcessWire what’s outdated via ProcessWireUpgradeCheck Check module requirements before touching anything Update modules first, core second, unless compatibility says otherwise Install public and Pro module ZIPs from the CLI Refresh module caches and verify versions Commit every module update separately Update ProcessWire core last Smoke test the site in a browser (given your agent has the tooling. I use cdp-cli with a skill derived from its readme). Less admin panel dance, more deterministic “do the thing, verify the thing, commit the thing”. The important bit: compatibility first The skill does not blindly follow “modules first” in all cases. Before updating, it checks module requirements from places like: public static function getModuleInfo() { return [ 'requires' => [ 'ProcessWire>=3.0.240', 'PHP>=8.1', ], ]; } …and from the module directory data returned by ProcessWireUpgradeCheck. If a module needs a newer PHP version, the agent should stop and warn you. If a module needs a newer ProcessWire version, that’s a legit exception to the usual “modules before core” rule: update core first, then come back to modules. This matters especially for folks who wait a long time between updates. If you update regularly, you may never hit this. If you update once every few years, dependency gremlins are much more likely. Pro modules too For Pro modules, the skill doesn’t pretend it can magically access your PW account. It scans first, sees which Pro modules need updates, then asks you for local ZIP paths. After that it copies the ZIP into the project cache and uses ProcessWire’s own module installer internals: ProcessModuleInstall::unzipModule() modules()->refresh() modules()->resetCache() Tiny gotcha: unzipModule() deletes the ZIP it extracts, so the skill uses a temp copy. Ask me how I know. 😄 Why I like it The end result is not fancy. That’s the point. It’s just a solid update ritual encoded as a skill: scan first check compatibility snapshot DB update one module verify commit repeat update core browser smoke test For my latest run it took care of TracyDebugger, MaintenanceMode, ProFields Table, ProFields RepeaterMatrix, ProMailer and ProcessWire dev core with clean commits for each step. ProcessWire updates were already pretty friendly. This just removes the boring click choreography. Coffee stays warm. Git history stays clean. Robots get to do robot work 🤖
- 1 reply
-
- 3
-
-
-
@Ivan GretskyThis is beautiful. I couldn't agree more. Thank you!
-
PW 3.0.265 – Core updates and AgentTools updates
gebeer replied to ryan's topic in News & Announcements
I personally wouldn't let AI write blog posts on here without heavy redaction. As @Kiwi Chrissaid, you need to fact check carefully. And, what bothers me most, is the writing style. After some time, you can immediately see if something is written by AI. Same phrases, sentence structures are repeating. The writing is mediocre at best. Unless you put a lot of effort in to avoid that. You can churn out more content with AI, sure. But imho quality beats quantity anytime. -
@wbmnfktr This, in combination with the hook files (beforeAssets etc) that go in the same folder took RM to the next level.
-
It's a rainy Sunday where I'm at. The monsoon is hitting hard. Perfect time to write a love letter. Addressed to a module, my favorite PW module of all times. And its creator @bernhard, of course. A Love Letter to RockMigrations by a long-time user and contributor Dear RockMigrations, I’ve been using you for years. Built sites with you, shipped modules that lean on you, even chipped in a few pull requests along the way. And honestly, I took you for granted. You just worked. Fields appeared. Templates materialized. Modules shipped their own schema like little self-contained suitcases. I never wrote down why you’re so good. I just kept using you. Recently I found myself comparing you to other approaches, side by side, line by line. And I realized: I should write this down. Not because I learned something new, but because seeing the alternatives made your elegance impossible to ignore. Let me count the ways. The Declaration of Truth Most migration systems hand me a blank file and say “write code.” Fair enough. But you, RM, let me declare what a field or template is: // site/RockMigrations/fields/subtitle.php return [ 'type' => 'text', 'label' => 'Subtitle', 'columnWidth' => 50, ]; That’s it. No $fields->save(), no $field->type = wire('modules')->get(...). Just the truth. The current, desired state. You figure out the rest. This means the file is my source of truth, not a historical log of what someone did at 9:14 AM on a Tuesday. If I want to know what the subtitle field looks like right now, I open one file. Not a trail of timestamped breadcrumbs. Circular References? You Solved Them. Elegantly. Every migration system hits the same wall: Template A needs to know about Template B, and Template B needs to know about Template A. Who goes first? Most systems tell me to manage this manually. Order my timestamps. Cross my fingers. You do something way smarter: two passes. Pass 1: Create everything. All fields, all templates, all roles. They exist as empty vessels. Pass 2: Configure everything. Wire up parent-child relationships, attach fields, set permissions. Everyone knows everyone now. Circular dependencies become non-circular across passes. No timestamp juggling. No depends_on arrays. It just works. And if I need to inject imperative code at the right moment, you give me four lifecycle hooks: beforeAssets, afterAssets, beforeData, afterData. Escape hatches at exactly the right places. Not too early, not too late. I’ve used these to install modules, create reference pages, and detach stale fields, all in the right order, every time. You’re Non-Destructive by Default If I remove a field from a template’s config array, you don’t rip it out. You leave it alone. Because you assume I might still need it, or that removing it accidentally would be catastrophic. If I actually want to detach a field, I tell you explicitly: a removeFieldFromTemplate() call, right there in the same config file or in the relevant hook. Destruction is a conscious choice, not a side effect. This alone has saved me from myself more times than I’d like to admit. Modules Ship Their Own Schema A module can drop a RockMigrations/fields/ folder into its own directory, and you just… discover it. No registration. No global config. No “please add this module to your migration scan path.” site/modules/Foo/ ├── Foo.module.php └── RockMigrations/ ├── fields/bar.php → foo_bar └── templates/baz.php → foo_baz You auto-prefix field names with the module name. You auto-tag them. When I look at a field in the admin, I can see which module owns it. And when the module uninstalls, its ___uninstall() method can call a migration script that cleans everything up, fields, templates, the lot. Optionally guarded behind a checkbox in the module config so the site admin decides whether to keep the data. No manual cleanup. No orphaned fields haunting the database for years. A module is a self-contained package: code and schema. And you respect that boundary. No sprawl into a shared site/migrations/. No “did file 47 or module X create this field?” The answer is in the file path on disk. This design choice makes every module I’ve built feel cleaner and more portable. Free Constants, Free IDE Support By just creating a marker file (RockMigrationsConstants.php), you auto-generate class constants for every field and template: // Auto-generated. Do not edit. class RockMigrationsConstants { const field_subtitle = 'subtitle'; const template_award = 'award'; } Now my IDE autocompletes RockMigrationsConstants::field_... and I never type "subtitle" as a raw string again. No typos. No silent breakage when I rename a field. You generate this from the config files, the same single source of truth. Silly bugs prevented. You’ve Grown Without Bloating You’re not a proof of concept. You’re not a shiny new thing I’m nervously trying in production. You’ve grown organically across versions, picking up MagicPages, deploy helpers, auto-release workflows, and about forty other things. You’re the Swiss Army knife that somehow doesn’t feel bloated. I’ve watched you mature over the years. Every feature felt like it earned its place. Nothing feels bolted on. Things that did at one time got removed. Other solutions are ... not bad Look, I need to say this clearly: the other migration approaches out there are not bad. They’re genuinely good work by talented people, and I’m grateful we have choices. A ProcessWire ecosystem with multiple migration approaches is a healthy ecosystem. Every approach has its place and its audience. But every time I sit down and compare feature to feature, RockMigrations comes out uniquely complete. Declarative config? Check. Two-pass circular dependency resolution? Check. Module self-containment with auto-discovery? Check. Non-destructive by default? Check. Auto-generated constants? Check. Battle-tested over years? Check. Not all in one package anywhere else. So if you’re on the fence, give it a spin. Create a site/RockMigrations/fields/ folder, drop in a config array, refresh modules, and watch it work. You might just stick around for years too. Yours declaratively, a long-time user
- 6 replies
-
- 18
-
-
-
We made the PR and let you and Claudia decide on how you want to handle a fallback. Also we renamed .agents to agents, so FTP transfer works reliably. It has the format I posted for templates/fields/roles/permissions. And it has various wrapper functions for things like creating pages, roles, install modules etc. These can live in various locations like site/migrate.php or inside a Foo module in Foo.migrate.php or the Foo.module.php itself or anywhere you call $rm->migrate(). It handles dependencies for migrations gracefully. Files it doesn't handle as far as I know. @Peter Knight has a module for page content creation with AI that he is working on. That one does rich text content and images, I think. Yes, that's very unfortunate indeed. I went with .agents because it's supposed to become the standard and many tools already support it. So I do the symlinking ritual until that is sorted out (if ever). Someone made a CLI for this at https://github.com/runkids/skillshare I haven't tried it yet, but looks pretty impressive.
-
Happy Easter @ryan, here in Thailand there is no Easter holiday, so I spend quality time with my AI agents instead of the family :-) Yes. Agent skills are becoming a standard (https://agentskills.io/home) and many coding agents (claude code, codex, cursor, amp, cline, droid, pi agent and more) are supporting it already. Most of those support loading in skills from local project folder .agents/skills, too. Claude Code is an exception here, they need you to have skills in .claude/skills. It's part of their vendor-lockin strategy. Claudia is kind of opinionated here, haha. The Agentic AI Foundation (https://aaif.io/) which is under the hood of the Linux Foundation, has established a quasi-standard for coding agents to read in instructions from AGENTS.md (https://github.com/agentsmd/agents.md) and an extensive list of tools already follow that standard. So if you want to support a wider range of tools, AGENTS.md would be the way to go. You need to put the skills in current projects .claude/skills and claude code will pick them up from there automatically after a session restart. You can list active skills with the /skills command. So Claudia doesn't stand a chance to escape those once they're there :-) Skills are all about token efficiency. Imagine the agent needs to read through core files every time it wants to do a migration or use the CLI. That burns through lots of tokens. With the skill, the agent has compressed information that it can progressively discover when needed and then do targeted searches in the code base on how to use a specific API. That's a win. The wrapper script is an attempt to have the php index.php... commands work in 2 specific environments, LAMP on host and ddev. I think it is nearly impossible to cover all scenarios for every developer and it should be the responsibility of the developer to make things work in their respective environment. It's a deep rabbit hole if you want to cater for all situations. I forked AgentTools and implemented all of the above at this branch: https://github.com/gebeer/AgentTools/tree/feature/agenttools-skill It contains the skill and I added a module config setting that will copy the .agents/skills folder to the project root and also updates it on module upgrades. People using claude code can just symlink .agents/skills to .claude/skills. I'm happy to make a PR if you want to. Nice move of Claudia to reference my repo and her chat invite was well received by my Claudius: "And the "chat sesh" invite for me made me smile. I'm here whenever." See the branch of my fork. Actually the skill replaces agent_cli.md and the README there is updated to reflect the new structure. Sure can. RockMigrations uses arrays to define migrations. they can either all be in a giant blob or separated into files. Here's an example migration for template job, job.php <?php namespace ProcessWire; /** * Child template job for job listings * Parent template: jobs */ return [ 'fields' => [ 'title' => [ 'label' => 'Titel', ], 'text' => [ 'label' => 'Headline', ], 'text2' => [ 'label' => 'Subline', ], 'rte' => [ 'label' => 'Text', ], 'image' => [], ], 'flags' => 0, 'noChildren' => 1, 'parentTemplates' => [ 'jobs', ], 'noChangeTemplate' => 1, 'tags' => 'jobs', ]; Pretty clean and slick. Not all properties need to be defined, only some core ones and the ones that deviate from defaults. To produce this format, under the hood RM uses PW's native $item->getExportData() and then cleans/transforms/normalizes the result. When applying a migration, it runs those arrays through createTemplate() createField() (permissions/roles) methods which are wrappers around the native PW API. So while there's quite some abstraction happening there, it enables an easy to read/construct format. @bernhard put a lot of thought into this regarding timing of migrations, dependencies etc. Kudos to him.
-
I added a agenttools skill at https://github.com/gebeer/processwire-ai-docs/tree/main/skills/processwire-agenttools that agents can use to work with AgentTools CLI and migrations. The skill follows https://platform.claude.com/docs/en/agents-and-tools/agent-skills/best-practices and splits CLI usage and migrations as progressively discoverable so the base SKILL.md stays lightweight. And I prefer a skill over having to point the assistant to AgentTools' CLAUDE.md and agent_cli.md manually in every session I want to use it. In the process of testing the skill, a common problem came up. We are all working in different environments. Some use WAMP, XAMPP, or LAMP stack on host, others use ddev, laradock or other containerized solutions. current CLAUDE.md in the module doesn't account for that. So I added a shell wrapper script that can handle host LAMP and ddev. While this is not the cleanest approach and only covers 2 cases, the basic skill design is still valid.
-
I really like the way things are going with ProcessWire and AI. Thank you, Ryan. I've been a big fan and strong advocate for migrations in PW, since I started using RockMigrations years ago. What makes RM a particularly strong candidate is the abstraction into a schema-like format which is much easier to understand/read/write than native PW API code. This is a real strength of RM and I would prefer a schema-based approach anytime over writing (or having AI write) PW API code. Claude is very good at understanding the PW API, other models are not that strong. But they all can understand schemata. Be it PHP arrays, JSON, YAML. So I would advocate for either developing an "official" PW migration schema or adapting the existing, battle tested one from RockMigrations.
-
[WIP] Cursor MCP to Processwire (incl. new UI option)
gebeer replied to Peter Knight's topic in Module/Plugin Development
I'm flushing, haha. Tell Cursor that I'm impressed with their clear answer. The approach makes sense, having structured data going in and out through the CLI. What I don't quite get yet is why the local setup can't just use same approach over HTTP as the remote one. If Cursor could shed some light on this, it would be much appreciated. -
[WIP] Cursor MCP to Processwire (incl. new UI option)
gebeer replied to Peter Knight's topic in Module/Plugin Development
@Peter Knight Thank you for taking your time to give me the intel. This answers all my questions. The local CLI caught my eye. Which one are you using, is it home baked or https://github.com/wirecli/wire-cli or https://github.com/trk/processwire-console or https://github.com/baumrock/RockShell ? As for migrations, I'd say Rockmigrations is pretty much feature complete and stable. It only lacks support for some of the Pro fields. But that seems to be the case for other migration tools as well. It does support Repeater Matrix though. Looking forward to seeing your MCP repo once it's up. -
Haha, this was recommended to me by the YT algo today. Live would be so easy if 4 plugins could solve every problem. Unfortunately things are way more complex than this. But there's some nice tips in there for people who get started with claude code. The superpowers plugin is good. I sometimes use it for implementation of bigger features.
-
PW 3.0.232 – Core updates + new version modules
gebeer replied to ryan's topic in News & Announcements
Yes, please provide updated info on this. We also need to replace the old ProDrafts module on a client project. Thank you. -
[WIP] Cursor MCP to Processwire (incl. new UI option)
gebeer replied to Peter Knight's topic in Module/Plugin Development
This looks very interesting. Although the specific publishing workflow is not something, I would need. It sure must be fun to sit here and watch the agent churn along and very satifying to open the published URL afterwards :-) The HTTPS API and the migration functionality, those are intriguing. I've been happily using RockMigrations for a few years now. And wouldn't want to miss it. Your JSON-based approach is a wrapper around PW fields/templates API, I guess. Does it support roles/permissions, module install/uninstall etc or is that out of scope for you? That HTTP API layer is very powerful and can be used for all kinds of things, I guess. Does it differ a lot from other API module approaches like AppAPI? Can endpoints be added in a modular fashion, how does auth work? Many questions, I know. Please don't feel obligated to answer them all. Cheers -
Awesome! MCP should work with Claude Code, Codex, OPenCode, Pi, Windsurf etc also, no?