Skip to content

phpClaw for OpenCart

The OpenCart adapter is an extension with separate builds for OpenCart 3 and 4. It adds admin pages, opened from its module entry phpClaw AI Agent, a CLI script, and 13 tools.


RequirementVersion
PHP8.1 or later
OpenCart3 or 4

Download for OpenCart 4 (.ocmod.zip)

Download for OpenCart 3 (.ocmod.zip)

Upload the ZIP for your version under Extensions → Installer, then install the module under Extensions → Extensions → Modules. Installing creates phpclaw_conversations, phpclaw_messages and phpclaw_memory, and gives the installing admin’s user group every phpClaw permission.

Then open phpClaw AI Agent from Extensions → Extensions → Modules and use its Settings button to choose a provider and enter the API key. The extension adds no entry to the admin menu.

Need a specific version? Browse all releases →

phpClaw in an OpenCart store

The Settings page shows when a newer version is available. Installing runs Plugin::runMigration(), whose CREATE TABLE IF NOT EXISTS statements leave existing tables and rows in place.


The Settings page stores provider, model, API key, Base URL (for the Custom provider; https://, or http:// on localhost, 127.0.0.1 or ::1), system prompt, Store Messages (on by default), max iterations (1 to 50, default 20), Remote Skill URLs and the phpClaw Cloud fields in OpenCart’s settings. Cloud is used only while Store Messages is on.

Remote Skill URLs keeps only https:// URLs whose path ends in .md or .json.

With Store Messages off, the agent stores no message content. See Memory.

Seven more fields switch on the building blocks:

FieldNotes
Fallback ProviderOff by default; lists only providers with the same tool format as the provider, never Custom
Fallback Modelempty uses the fallback provider’s default
Fallback API Keyhidden when Fallback Provider is Off or Ollama
Rate Limit (requests/min)0 to 600, default 0 (off)
Response Cacheoff by default
Response Cache TTL (seconds)shown when Response Cache is on; 60 to 86400, default 3600
Max Token Budget0 to 10,000,000, default 0 (off)

The rate limit and the response cache are kept as files in a phpclaw folder under OpenCart’s cache directory. In Chat, a spent token budget answers 422 with “Token budget reached for this run.” and a rate limit 429 with “Rate limit reached, try again shortly.”; the CLI prints the same message.

Separately from the Rate Limit field, the extension always registers core’s rate limit guard at 60 messages per minute per client IP, counted in APCu (without APCu it counts per PHP process only). Past it, Chat answers “Request blocked by security guard.” with status 200.

Two fields set which tools the model is offered:

FieldNotes
Max Tools Per Turndefault 0, the automatic per-turn limit; -1 turns the limit off, though the token budget can still drop tools; below -1 is saved as -1
Always Include Toolscomma-separated tool names offered on every turn, outside the limit; a name that is not a tool on the store is skipped, and a tool in tool_deny stays denied

The module’s config/phpclaw.php holds settings with no form field: workspace_root (default phpclaw under OpenCart’s storage directory), shell_allowlist (core’s default), tool_deny, guards, hooks, skills, events_bridge and update_server. Several can be set by defining a PHP constant, such as PHPCLAW_SHELL_ALLOWLIST. shell_allowlist sets the commands a ShellTool added through the phpclaw/extra/tools event may run.


phpClaw uses OpenCart’s route permissions, set under System → Users → User Groups. On OpenCart 3 the route is extension/module/phpclaw; on OpenCart 4 it is extension/phpclaw/module/phpclaw.

PermissionAllows
access on the phpClaw routethe Chat, Analytics, Guide and About pages, and every OpenCart tool except raw SQL
modify on the phpClaw routesending messages from the Chat page
access on the route followed by /manage_allthe Settings page, Test Connection, seeing every admin’s conversations, and db_query

An OpenCart tool call without access returns a FORBIDDEN error. db_query without /manage_all fails with an error saying raw SQL needs the manage-all permission. The CLI script skips both checks.


13 tools, plus core’s load_skill, which the chat and CLI agent get because core’s discovered skills, at least php_best_practices, are always registered. The Guide page and the MCP server list the 13:

GroupTools
OpenCartoc_product, oc_category, oc_manufacturer, oc_order, oc_customer, oc_review, oc_coupon, oc_shipping, db_query, read_log
Corecode_search, project_info, file_read

db_query runs one read-only SELECT and refuses the setting table, where extensions keep their credentials, and the phpclaw_conversations and phpclaw_messages tables. See Tools for the core tools.

ToolDoes
oc_productsearches and inspects products with stock and pricing
oc_categorybrowses the category hierarchy
oc_manufacturerlists and searches manufacturers
oc_ordersearches and inspects orders with revenue and status
oc_customersearches and inspects customers with order history statistics
oc_reviewlists reviews by product, rating or status
oc_couponlists active and expired coupons and their usage
oc_shippingsearches and inspects shipping methods
db_queryruns one read-only SELECT
read_logreads and searches system/storage/logs/error.log

shell_exec, http_request, file_write and file_edit are not registered: core marks them opt-in, and the module asks core only for its default tools. A listener for the phpclaw/extra/tools event adds tools as objects or as class names. An object is used as it is. The class name \PhpClaw\Tools\ShellTool::class is built with shell_allowlist, and FileWriteTool::class and FileEditTool::class with workspace_root, both from config/phpclaw.php. Any other tool class whose constructor needs no argument is built with new, and anything else is dropped. A ShellTool a listener builds with no allowlist uses core’s default, ls, pwd, df, wc, date, uptime, hostname and whoami, and the allowlist matches the first word of the command exactly, case included.

Tools added through the phpclaw/extra/tools event are placed before the built-in tools.

tool_deny in config/phpclaw.php removes tools by name or group:

GroupTools
group:commerceoc_product, oc_order, oc_customer, oc_coupon
group:catalogoc_category, oc_manufacturer, oc_review
group:systemdb_query, read_log, oc_shipping

Every agent is built with CliApprovalGate. In a terminal you are asked before a tool changes something; in the admin there is nobody to ask, so the change is refused. See Security: approval.

file_write, file_edit and shell_exec exist only when added through the phpclaw/extra/tools event. That event fires only in admin requests, where the gate refuses every file_write and file_edit call and any shell_exec command on the allowlist but outside core’s read-only command list. The CLI script builds the agent without OpenCart’s registry, so no phpclaw/extra/* event fires there and those tools are not added.


The same script ships for both versions. The installer places it at extension/phpclaw/cli/phpclaw.php on OpenCart 4 and at system/library/phpclaw/cli/phpclaw.php on OpenCart 3. From the OpenCart 4 root:

Terminal window
# interactive session
php extension/phpclaw/cli/phpclaw.php chat
php extension/phpclaw/cli/phpclaw.php chat --conv-id=01JXYZ...
php extension/phpclaw/cli/phpclaw.php chat --continue
# one-shot send
php extension/phpclaw/cli/phpclaw.php send "check low stock products"
php extension/phpclaw/cli/phpclaw.php send "summarise today's orders" --stream --provider=groq
php extension/phpclaw/cli/phpclaw.php send "and which of them are out of stock?" --continue --trace
php extension/phpclaw/cli/phpclaw.php mcp-server

send takes --stream, --provider, --model, --conv-id, --continue and --trace, and runs with every tool including raw SQL. chat opens an interactive session and takes --conv-id and --continue.

send prints the reply, then [provider:<p> model:<m> tokens:<n> iterations:<n> conversation:<id>] on stderr; with --stream it prints the reply only. --conv-id=<id> continues that stored conversation; an id with no stored conversation prints a warning and starts a new one. --continue picks the last conversation, whose id is kept in phpclaw/.last-conversation in OpenCart’s storage folder: one value per site, so every shell user continues the same conversation. The CLI reopens only the conversations it created; another admin’s id prints Conversation <id> is not available to the console and starts a new one. --trace prints one line per tool call on stderr, the tool name plus a short path or command, never the result.

chat keeps one conversation open, streams each reply and prints the tool calls as they run, then a line with the provider, model, input and output tokens, the tools that ran and the conversation id. It needs a terminal: with piped input it refuses and exits 1. A line starting with / is a command and is never sent to the agent:

CommandWhat it does
/helpList these commands
/toolsList the active tools
/model <name>Switch the model for this session only
/provider <slug>Switch the provider for this session only
/newStart a new conversation
/convPrint the conversation id
/quietTurn the tool trace off or on
/clearClear the screen
/exitLeave; Ctrl+D also leaves

While the agent works, a Thinking... spinner shows until the first word of the reply arrives. It is not shown when the output is not a terminal, and without the pcntl extension a still Thinking... line is printed instead of the animation. A failed turn prints one line without the exception text and the session goes on; the exception goes to the PHP error log, which is the terminal’s stderr when PHP has no error_log set. On leaving it prints the command to resume. /model and /provider never write the settings; a provider that cannot be built is named and the session keeps the current one.

mcp-server serves the tools over stdio; see MCP.

PhpClaw\OpenCart\PhpClawLibrary is the OpenCart registry form. Its send() returns the reply text and getEngine() returns the agent. It builds the agent with PhpClawFactory, which reads the provider, model and message storage from PHP constants such as PHPCLAW_PROVIDER and PHPCLAW_MODEL, not from the Settings page, so the seven fields above do not apply to it. It is built with no database handle and no OpenCart registry, so no phpclaw/extra/* event fires for it, and outside the CLI script every OpenCart tool returns FORBIDDEN.

$registry->set('phpClaw', new \PhpClaw\OpenCart\PhpClawLibrary());
$text = $registry->get('phpClaw')->send('Check order queue depth.');

PagePermissionShows
Settings/manage_allthe settings and Test Connection
Chataccess (modify to send)the chat interface with the admin’s conversations
Analyticsaccessconversation and message counts; store-wide with /manage_all, otherwise the admin’s own
Guideaccessthe registered tools
Aboutaccessextension information

Each conversation stores the creating admin’s user id in owner_id. Conversations created from the CLI store 0. An admin sees and opens only their own conversations; opening another’s is refused. The CLI reopens only the 0 conversations it created, never an admin’s. Admins with /manage_all see every conversation.

The agent always uses the oc_router memory driver, OcRouterMemory, which sends conversations to OcDbConversationMemory and everything else to OcDbMemory. oc_setting (OcSettingMemory) stores in OpenCart’s settings table instead. With oc_router, conversations go to the conversation tables, everything else in phpclaw_memory.


Extensions register additions through OpenCart events named phpclaw/extra/tools, phpclaw/extra/guards, phpclaw/extra/hooks, phpclaw/extra/skills, phpclaw/extra/memory and phpclaw/extra/providers. These events, and the lifecycle events that events_bridge sends as phpclaw/{event}, fire only in admin requests: the CLI script builds the agent without OpenCart’s registry.