Skill v1.0.0
currentAutomated scan100/100version: "1.0.0" name: rock description: > This skill should be used when the user asks to interact with Rock RMS in any way: "look up a person in Rock", "search for someone in Rock RMS", "check attendance", "view giving records", "manage groups", "add someone to a group", "launch a workflow", "send a communication", "manage content channels", "check campuses", "find a resource", "query Rock data", "create a record in Rock", "update Rock data", "delete a Rock record", "check prayer requests", "view connections", "manage events", "view registrations", "check schedules", "manage security roles", "view steps", "check streaks", "manage tags", "view notes", "check notifications", "manage learning courses", "browse the Rock server filesystem", "upload a plugin file", "edit a theme file", "deploy a custom block", "list files in /Plugins", "download a Rock theme file", or any task involving Rock RMS church management data. The CLI uses a single generic resource command that covers all 317 Rock RMS v2 API controllers, plus dedicated rock sql and rock files commands for the Triumph Tech Magnus REST endpoints. allowed-tools: Bash(rock:*)
Rock RMS CLI (v2 Generic Resource API)
Overview
The rock CLI provides access to ALL 317 Rock RMS v2 API controllers through a single generic rock resource command. Instead of individual commands per entity (people, groups, etc.), you use rock resource search <Resource>, rock resource get <Resource> <id>, etc.
Installation & Setup
# Installbun add -g github:leighton-tidwell/rock-cli# Configure connectionrock config init <url> <apiKey># Example:rock config init "https://rock.example.com" "your-api-key-here"# Verifyrock config show# Upgrade to latestrock config upgrade
Command Reference
Resource Commands (covers all 317 controllers)
rock resource list [--category <cat>] # List all available resourcesrock resource search <Resource> [options] # Search/list recordsrock resource get <Resource> <id> # Get a single record by IDrock resource create <Resource> --body <json> # Create a new recordrock resource update <Resource> <id> --body <json> # Update an existing recordrock resource delete <Resource> <id> # Delete a recordrock resource attributes <Resource> <id> # Get attribute values for a recordrock resource set-attributes <Resource> <id> --body <json> # Update attribute values
Server Filesystem (Magnus plugin required — see references/files.md)
rock files ls [path] # List a directory (default: root)rock files cat <path> # Read a file to stdoutrock files get <remote> [local] # Download a filerock files put <local> <remote> # Upload (creates or overwrites)rock files write <remote> # Overwrite existing file from stdinrock files rm <path> # Delete a file or folderrock files mkdir <path> # Create a folder
Roots: /Plugins, /Themes, /Content, /App_Data. Requires "magnus": true on the profile.
Raw HTTP Access
rock raw <METHOD> <path> [--body <json>]# Examples:rock raw GET /api/v2/Peoplerock raw POST /api/v2/Workflows --body '{"Name": "Test"}'rock raw PATCH /api/v2/People/123 --body '{"Email": "new@example.com"}'rock raw DELETE /api/v2/Groups/456
Configuration
rock config init <url> <apiKey> # Initialize configurationrock config show # Show current configurationrock config set-url <url> # Update API URLrock config set-key <key> # Update API keyrock config profile [name] # Switch or list profilesrock config profile add <name> --url <url> --key <key> # Add a profilerock config upgrade # Upgrade rock-cli to latest version
Search Options (Dynamic LINQ - NOT OData)
The v2 API uses Dynamic LINQ for querying, NOT OData. This is a critical difference.
| Option | Description | |
|---|---|---|
--where | Dynamic LINQ filter expression | |
--select | Projection expression (choose fields) | |
--sort | Sort expression | |
--take | Max number of records to return | |
--offset | Number of records to skip (for pagination) |
Dynamic LINQ Syntax
Comparison Operators
== Equal LastName == "Smith"!= Not equal Gender != 0> Greater than BirthYear > 1990< Less than BirthYear < 2000>= Greater or equal CreatedDateTime >= DateTime(2024, 1, 1)<= Less or equal TotalAmount <= 100.00
Logical Operators
&& AND LastName == "Smith" && IsDeceased == false|| OR LastName == "Smith" || LastName == "Jones"
String Methods
LastName.Contains("mit") # Contains substringLastName.StartsWith("Sm") # Starts withEmail.EndsWith("@gmail.com") # Ends withLastName.ToUpper() == "SMITH" # Case conversion
Collection Methods (for navigating related data)
PhoneNumbers.Any(Number.StartsWith("210")) # Any phone starts with 210Members.All(GroupMemberStatus == 1) # All members activeGroupMembers.Count() > 5 # More than 5 members
DateTime Handling
TransactionDateTime >= DateTime(2024, 1, 1)TransactionDateTime < DateTime(2025, 1, 1)CreatedDateTime >= DateTime(2024, 6, 15, 8, 0, 0) # With timeBirthDate.Month == 12 # December birthdays
Null Checks
CampusId != nullEmail == null
Projection with --select
--select 'new (Id, FirstName, LastName, Email)'--select 'new (Id, Name, GroupTypeId, IsActive)'
Sorting with --sort
--sort 'LastName'--sort 'LastName, FirstName'--sort 'LastName desc'--sort 'CreatedDateTime desc, LastName'
Resource Categories
Use rock resource list --category "<name>" to filter by category.
| Category | Key Resources | |
|---|---|---|
| People & Families | People, PersonAlias, PhoneNumber, PersonSearchKey, PersonBadge, PersonDuplicate, PersonMergeRequest | |
| Groups & Membership | Group, GroupMember, GroupType, GroupTypeRole, GroupScheduleExclusion, GroupMemberAssignment | |
| Financial | FinancialTransaction, FinancialTransactionDetail, FinancialAccount, FinancialBatch, FinancialGateway, FinancialPledge, FinancialScheduledTransaction | |
| Attendance & Check-in | Attendance, AttendanceOccurrence, CheckInLabel, Device, Location | |
| Communication | Communication, CommunicationRecipient, CommunicationTemplate, SystemCommunication, SystemEmail | |
| Workflows | Workflow, WorkflowType, WorkflowActivity, WorkflowActivityType, WorkflowAction, WorkflowActionType, WorkflowTrigger | |
| CMS & Pages | Page, Block, BlockType, Layout, Site, PageRoute, HtmlContent | |
| Content & Media | ContentChannel, ContentChannelItem, ContentChannelType, MediaFolder, MediaElement | |
| Events & Registration | EventItem, EventItemOccurrence, Registration, RegistrationInstance, RegistrationTemplate, EventCalendar | |
| Connections | ConnectionRequest, ConnectionOpportunity, ConnectionType, ConnectionStatus, ConnectionActivityType | |
| Steps & Streaks | Step, StepProgram, StepType, StepStatus, Streak, StreakType | |
| Data & Reporting | DataView, Report, ReportField, PersistedDataset, MetricValue, Metric | |
| Security & Auth | Auth, UserLogin, RestAction, RestController, PersonToken | |
| Interactions & Engagement | Interaction, InteractionChannel, InteractionComponent, InteractionSession | |
| Notes & Documents | Note, NoteType, Document, DocumentType, BinaryFile, BinaryFileType | |
| Prayer | PrayerRequest, PrayerRequestComment | |
| Benevolence | BenevolenceRequest, BenevolenceType, BenevolenceResult, BenevolenceWorkflow | |
| Scheduling | Schedule, ScheduleCategoryExclusion, AttendanceOccurrenceSchedule | |
| Learning | LearningCourse, LearningClass, LearningActivity, LearningParticipant, LearningProgram | |
| Notifications & Reminders | Reminder, ReminderType, NotificationMessage, NotificationRecipient | |
| Tags | Tag, TaggedItem | |
| AI | AiProvider, AiAutomation | |
| Analytics | AnalyticsDimFamilyCurrent, AnalyticsDimPersonCurrent, AnalyticsFactAttendance, AnalyticsFactFinancialTransaction | |
| System & Admin | Campus, DefinedType, DefinedValue, EntityType, Attribute, AttributeValue, Category, SystemConfiguration, ServiceJob |
Core Workflow Patterns
Find a Person
# Search by last namerock resource search People --where 'LastName == "Smith"' --take 10# Search by emailrock resource search People --where 'Email == "jane@example.com"'# Search by phone numberrock resource search People --where 'PhoneNumbers.Any(Number.StartsWith("555"))'# Search with projection (faster, less data)rock resource search People --where 'LastName == "Smith"' \--select 'new (Id, FirstName, LastName, Email)' --take 10# Get full person recordrock resource get People 123# Get person's attribute values (baptism date, t-shirt size, etc.)rock resource attributes People 123
Manage Groups
# List small groups (GroupTypeId 25 is typical)rock resource search Group --where 'GroupTypeId == 25 && IsActive == true' --take 20# Get group detailsrock resource get Group 42# List group membersrock resource search GroupMember --where 'GroupId == 42' \--select 'new (Id, PersonId, GroupRoleId, GroupMemberStatus)'# Add person to grouprock resource create GroupMember --body '{"GroupId": 42,"PersonId": 789,"GroupRoleId": 2,"GroupMemberStatus": 1}'# Remove person from group (find the GroupMember ID first)rock resource search GroupMember --where 'GroupId == 42 && PersonId == 789'# Then delete by GroupMember ID:rock resource delete GroupMember 5678
Check Giving / Financial
# Find a person's alias ID (needed for financial queries)rock resource search PersonAlias --where 'PersonId == 123' --take 1# Get transactions for a person in a date rangerock resource search FinancialTransaction \--where 'AuthorizedPersonAliasId == 456 && TransactionDateTime >= DateTime(2025, 1, 1) && TransactionDateTime < DateTime(2026, 1, 1)' \--sort 'TransactionDateTime desc'# List financial accountsrock resource search FinancialAccount --where 'IsActive == true'# Get transaction details (line items)rock resource search FinancialTransactionDetail \--where 'Transaction.AuthorizedPersonAliasId == 456' \--select 'new (Id, Amount, AccountId, Transaction.TransactionDateTime)'# Get financial batchesrock resource search FinancialBatch \--where 'Status == 1' --sort 'BatchStartDateTime desc' --take 10
Workflows
# List workflow typesrock resource search WorkflowType --where 'IsActive == true' \--select 'new (Id, Name, Description)'# Launch a workflow (create a Workflow instance)rock resource create Workflow --body '{"WorkflowTypeId": 15,"Name": "New Member Follow-Up"}'# Check workflow statusrock resource get Workflow 301# Find active (incomplete) workflows of a typerock resource search Workflow \--where 'WorkflowTypeId == 15 && CompletedDateTime == null' \--sort 'ActivatedDateTime desc'
Attendance
# Get attendance for a group in a date rangerock resource search Attendance \--where 'Occurrence.GroupId == 42 && StartDateTime >= DateTime(2025, 1, 1) && StartDateTime < DateTime(2026, 1, 1)' \--sort 'StartDateTime desc'# Record attendancerock resource create Attendance --body '{"OccurrenceId": 100,"PersonAliasId": 456,"StartDateTime": "2025-03-27T09:00:00","DidAttend": true}'
Content Management
# List content channelsrock resource search ContentChannel --where 'IsActive == true'# List items in a channelrock resource search ContentChannelItem \--where 'ContentChannelId == 5 && Status == 2' \--sort 'StartDateTime desc' --take 20# Create a content itemrock resource create ContentChannelItem --body '{"ContentChannelId": 5,"Title": "Sunday Recap","Content": "<p>This week...</p>","Status": 1,"StartDateTime": "2026-04-01"}'# Publish (set status to Approved=2)rock resource update ContentChannelItem 201 --body '{"Status": 2}'
Connections
# List connection opportunitiesrock resource search ConnectionOpportunity --where 'IsActive == true'# Find open connection requestsrock resource search ConnectionRequest \--where 'ConnectionState == 0' --sort 'CreatedDateTime desc' --take 20# Create a connection requestrock resource create ConnectionRequest --body '{"ConnectionOpportunityId": 5,"PersonAliasId": 456,"ConnectionState": 0,"ConnectionStatusId": 1}'
Communications
# List communication templatesrock resource search CommunicationTemplate --where 'IsActive == true' \--select 'new (Id, Name, Subject)'# List system communicationsrock resource search SystemCommunication \--select 'new (Id, Title, Subject, IsActive)'# Create a communicationrock resource create Communication --body '{"CommunicationType": 1,"Subject": "Welcome!","Message": "<p>Welcome to our church</p>","SenderPersonAliasId": 1}'
Other Common Tasks
# List campusesrock resource search Campus --select 'new (Id, Name, IsActive)'# Get defined values (lookup lists)rock resource search DefinedValue --where 'DefinedTypeId == 32' \--select 'new (Id, Value, Description)'# List prayer requestsrock resource search PrayerRequest \--where 'IsActive == true && IsApproved == true' \--sort 'CreatedDateTime desc' --take 20# Search notes for a personrock resource search Note --where 'EntityId == 123'# List schedulesrock resource search Schedule --where 'IsActive == true' \--select 'new (Id, Name, Description)'# Get steps for a personrock resource search Step --where 'PersonAliasId == 456' \--sort 'CompletedDateTime desc'
Two-Tier Data Model
Rock stores data in two tiers:
- Database Fields (FirstName, LastName, Email, etc.)
- Returned by default in search/get results
- Fully queryable with --where, --select, --sort
- Attributes (custom fields like Baptism Date, T-Shirt Size)
- NOT returned in normal search/get results
- Must be fetched with
rock resource attributes <Resource> <id> - Can be updated with
rock resource set-attributes <Resource> <id> --body <json> - Cannot be filtered server-side; fetch and filter client-side
# Get person's database fieldsrock resource get People 123# Get person's attribute valuesrock resource attributes People 123# Update person's attribute valuesrock resource set-attributes People 123 --body '{"BaptismDate": "2025-06-15", "TShirtSize": "L"}'
Pagination
Use --take and --offset for pagination:
# Page 1 (first 100 records)rock resource search People --where 'LastName == "Smith"' --take 100 --offset 0# Page 2rock resource search People --where 'LastName == "Smith"' --take 100 --offset 100# Page 3rock resource search People --where 'LastName == "Smith"' --take 100 --offset 200
Important Notes
- Resource names are PascalCase and case-sensitive:
People,Group,FinancialTransaction - Use
rock resource listto discover all available resources - Use
rock resource list --category "People & Families"to filter by category - The v2 API uses Dynamic LINQ, NOT OData. Do not use
eq,$filter, etc. - Many entities reference
PersonAliasIdinstead ofPersonId- look up aliases first - DateTime values in --body JSON should be ISO 8601 strings
- DateTime values in --where use
DateTime(year, month, day)syntax - Field names are PascalCase:
FirstName,LastName,GroupTypeId - Use
rock rawas an escape hatch for any endpoint not covered by resource commands
Deep-Dive Documentation
| Reference | When to Use | |
|---|---|---|
| references/resources.md | Full list of all 317 resources organized by category | |
| references/querying.md | Dynamic LINQ query syntax, operators, and examples | |
| references/troubleshooting.md | Error diagnosis and common fixes | |
| references/sql.md | Direct SQL access via the Triumph Magnus plugin (requires magnus: true on the profile) | |
| references/files.md | Read/write the Rock server filesystem (/Plugins, /Themes, /Content, /App_Data) via Magnus (requires magnus: true) |
Ready-to-Use Templates
| Template | Description | |
|---|---|---|
| templates/giving-summary.sh | Retrieve giving data for a person in a year | |
| templates/new-member-workflow.sh | Find/create person, add to group, launch workflow | |
| templates/attendance-report.sh | Pull attendance records for a group over a date range |