Imported from bradvin/clawpress (
AGENTS.md). Install upstream withnpx skills add bradvin/clawpress. Copyright stays with the author.
AGENTS.md - AI Assistant Context
This is a WordPress plugin ClawPress. When working with this codebase, follow these patterns and conventions.
Project Overview
The plugin includes:
- React-based admin UI using DataViews
- REST API with namespaced endpoints
- Floating wp-admin panel UI (
src/panel) - wp-scripts build system
Architecture Patterns
PHP Structure
- Main file (
clawpress.php): Only defines constants and requires modules - Feature modules (
includes/class-*.php): Each feature isolated in its own namespaced class file - Strict types: All PHP files use
declare( strict_types=1 ) - Namespace convention:
ClawPress\FeatureName - Coding standards: WordPress Coding Standards (WPCS) - use tabs, spaces inside parentheses
- Linting config:
phpcs.xml.dist- runnpm run lint:phpto check
JavaScript Structure
- Entry point:
src/js/admin/index.js- mounts React app on plugin admin page - Panel entry point:
src/panel/index.jsx- mounts floating admin panel - Components:
src/js/admin/components/- React components - Hooks:
src/js/admin/hooks/- Custom hooks (data fetching, state) - Config:
src/js/admin/config/- Field definitions, actions, settings
JavaScript Formatting Rules
Apply these rules consistently to avoid large lint/fix churn:
- Use tabs for indentation in JS/JSX files.
- Use single quotes for JS strings/imports (unless escaping/template use makes that inappropriate).
- Let Prettier collapse JSX/expressions to single-line when short; do not force manual multi-line wrapping.
- Do not manually align tokens/spaces for visual columns; keep standard Prettier spacing.
- Keep object/array/function formatting Prettier-first; avoid hand-formatted stylistic layouts.
- Avoid nested ternaries; expand to clear
if/elsewhen logic branches. - Keep
ideas/out of JS lint scope (ignored via.eslintignoreand changed-file lint script). - Before committing JS changes, run
npm run lint:js -- --fix(or scoped equivalent) and thennpm run lint:js.
REST API Pattern
Located in includes/class-rest-api.php:
- Namespace:
clawpress/v1 - Always include
permission_callback - Use
sanitize_callbackandvalidate_callbackfor args - Return
WP_REST_Responsewith appropriate status codes
Note: The DataViews demo uses @wordpress/core-data which handles REST calls for post types internally. Custom endpoints are only needed for operations not covered by WordPress core (custom business logic, aggregations, etc.).
DataViews Pattern
The admin UI uses @wordpress/dataviews with the WordPress Data Layer:
- fields: Define columns in
config/itemConfig.js - actions: Define row actions (view, edit, trash) in same file
- useItems hook: Uses
useEntityRecordsfrom@wordpress/core-data
To switch post types, change 'page' to your CPT slug in useItems.js.
Key Files to Modify
When adding features:
| Task | Files to Edit |
|---|---|
| Add custom post type | includes/class-post-types.php |
| Add REST endpoint | includes/class-rest-api.php |
| Add admin component | src/js/admin/components/, import in App.js |
| Update floating panel UI | src/panel/ and includes/class-panel.php |
| Add PHP heartbeat/scheduler hook | includes/class-heartbeat.php |
Helper Class Reference
Use helpers in includes/helpers/ as the primary integration surface for shared logic.
| Helper | File | Responsibility | Usage Rule |
|---|---|---|---|
Action_Log_Helper |
includes/helpers/class-action-log-helper.php |
Action/event log persistence and retrieval in clawpress_action_logs |
Route action/event log writes and reads through this helper. |
Agent_File_Helper |
includes/helpers/class-agent-file-helper.php |
Bootstrap and resolve agent files from clawpress_agent_file |
Resolve logical files through this helper; do not bypass with ad-hoc lookups. |
Chat_Helper |
includes/helpers/class-chat-helper.php |
Online/offline reply orchestration and AI-call integration | Route model replies through this helper from chat flows. |
Chat_History_Helper |
includes/helpers/class-chat-history-helper.php |
Per-user chat transcript persistence | Use for chat history reads/writes and clears. |
Context_Helper |
includes/helpers/class-context-helper.php |
Builds system prompt + message arrays from bootstrap/memory/skills/history | Use this as the central context builder for LLM calls. |
Memory_Helper |
includes/helpers/class-memory-helper.php |
Memory persistence/retrieval in clawpress_agent_mem (memory.md + memory-ddmmyyyy.md) |
All memory save/read/clear operations must use this helper only. |
Model_Helper |
includes/helpers/class-model-helper.php |
Provider-specific model option lists and defaults | Use for model option resolution in UI/commands. |
Panel_Helper |
includes/helpers/class-panel-helper.php |
Floating panel state normalization and defaults | Use for panel state storage and hydration. |
Provider_Helper |
includes/helpers/class-provider-helper.php |
Provider availability/configuration/model resolution | Use for provider detection and configured-provider fallback logic. |
Settings_Helper |
includes/helpers/class-settings-helper.php |
Typed plugin settings read/write and sanitization | Use for plugin setting access instead of direct option mutation. |
Status_Helper |
includes/helpers/class-status-helper.php |
Canonical status payload for REST/UI | Use for /status payload generation. |
User_Helper |
includes/helpers/class-user-helper.php |
Agent user creation and validation | Use for agent-user setup and verification. |
Workspace_Helper |
includes/helpers/class-workspace-helper.php |
Agent workspace path/hash creation and structure | Use for workspace creation/path resolution. |
Helper Guardrails
- Do not duplicate helper logic in controllers/commands.
- Do not add new direct memory storage access in commands/controllers/options.
- Memory data model is:
- Daily memory files:
memory-ddmmyyyy.md - Long-term memory file:
memory.md
- Daily memory files:
- Context assembly must read memory via
Memory_Helperand not from legacy options.
Data Flow
The demo uses the WordPress Data Layer (@wordpress/core-data):
WordPress REST API (built-in /wp/v2/pages)
↓
useEntityRecords (src/js/admin/hooks/useItems.js)
↓
DataViews component (src/js/admin/components/App.js)
The Data Layer handles authentication, caching, and optimistic updates automatically. To use a custom post type, change 'page' to your CPT slug in useItems.js.
For custom endpoints (settings, business logic), use includes/class-rest-api.php with wp_localize_script in includes/class-admin-page.php. These endpoints can then be called from your React components using apiFetch.
Common Tasks
Changing the post type
// src/js/admin/hooks/useItems.js
// Change 'page' to your custom post type slug
useEntityRecords( 'postType', 'your_cpt_slug', { ... } );
Adding a new DataViews field
// src/js/admin/config/itemConfig.js
{
id: 'new_field',
label: 'New Field',
type: 'text',
enableSorting: true,
getValue: ({ item }) => item.new_field,
}
Adding a REST endpoint
// includes/class-rest-api.php
register_rest_route(
'clawpress/v1',
'/new-endpoint',
array(
'methods' => 'GET',
'callback' => __NAMESPACE__ . '\handle_new_endpoint',
'permission_callback' => function () {
return current_user_can( 'manage_options' );
},
)
);
Dependencies
Scripts rely on WordPress packages extracted at build time:
@wordpress/element- React wrapper@wordpress/components- UI components@wordpress/core-data- Data layer (REST API abstraction)@wordpress/dataviews- Table/grid views@wordpress/icons- Icon library@wordpress/dom-ready- Admin app bootstrap@wordpress/element- React root rendering
Internationalization (Required)
All user-facing strings must be translatable.
- Never ship hardcoded UI text in PHP or JS.
- Always use text domain:
clawpress. - PHP strings: use
__(),_x(),esc_html__(),esc_attr__(),sprintf()with translator comments when placeholders are used. - JS strings: import from
@wordpress/i18nand use__,_x,_n,sprintfas needed. - Keep command identifiers/keys untranslated (e.g.,
/help, option keys, slugs), but translate labels/messages/descriptions shown to users. - When adding new script entry points/handles, ensure script translations are loaded via
wp_set_script_translations( $handle, 'clawpress', CLAWPRESS_DIR . 'languages' ).
Unit Tests And WordPress Stubs
When writing or refactoring PHPUnit tests:
- Never add test-only logic, boot contracts, or test-oriented exceptions/messages to plugin runtime code in
includes/orclawpress.php. - Do not introduce production
assert_*helpers, runtime throws, orfunction_exists()guards solely to make tests pass. - If PHPUnit needs a missing WordPress API, add a deterministic stub in
tests/Support/WordPressStubs.phpinstead of changing plugin behavior. - When a stub needs state, store it in
WordPress_Stubsand reset it inWordPress_Stubs::reset()so tests remain isolated. - Keep stubs minimal and behavior-focused: enough for assertions without recreating WordPress internals.
- Tests must validate real plugin behavior and observable outcomes, not internal test scaffolding.
- Prefer exercising registered hooks with
do_action()/apply_filters()and asserting side effects (registered menus/routes, enqueued assets, persisted meta/options, scheduler calls). - Avoid low-value tests that only assert stub presence (for example
function_exists()contract lists) or only test helper assertions without behavior coverage. - If behavior is truly optional in production (version-gated or feature-detected APIs), keep runtime guards and cover both paths in tests.
Verification Expectations
- Run targeted PHPUnit tests for the changed module first.
- Run the full PHPUnit suite when shared test support files (like
WordPressStubs.php) are changed. - Prefer assertions that verify integration calls and state transitions happened (for example submenu registration/removal and metadata checks).
Local CI With Agent CI
- Install the
agent-ciskill one time withnpx skills add redwoodjs/agent-ci --skill agent-ci. - Before completing substantial work, run
npm run ci:agent:ciornpm run ci:agentand fix any failures before reporting the work as done. - If Agent CI pauses on a failed step, fix the issue and resume with
npm run ci:agent:retry -- --name <runner-name>. - Keep local Agent CI secrets in
.env.agent-ci. Never commit that file.
Important Notes
- Asset files (
build/scripts/*.asset.php) are auto-generated - never edit manually - The
build/,node_modules/, andvendor/directories are gitignored - Always run
composer install && npm install && npm run buildafter cloning - After adding, renaming, or removing PHP class files in the plugin, run
composer dump-autoloadbefore testing. - PHP must follow WordPress Coding Standards - run
npm run lint:phpbefore committing - PHP namespaces must match directory structure for autoloading compatibility
- The Data Layer (
@wordpress/core-data) handles REST auth automatically - Admin page uses
add_menu_page()and mounts the app into a dedicated root element - Avoiding adding manual inline style overrides to components unless specifically requested.