Skip to content

Commit be8cda6

Browse files
committed
update adding claude.md
1 parent 170a6b4 commit be8cda6

11 files changed

Lines changed: 872 additions & 47 deletions

File tree

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
#!/bin/sh
2+
if grep -q "caliber" .git/hooks/pre-commit 2>/dev/null; then
3+
exit 0
4+
fi
5+
FLAG="/tmp/caliber-nudge-$(echo "$PWD" | shasum | cut -c1-8)"
6+
find /tmp -maxdepth 1 -name "caliber-nudge-*" -mmin +120 -delete 2>/dev/null
7+
if [ -f "$FLAG" ]; then
8+
exit 0
9+
fi
10+
touch "$FLAG"
11+
printf '{"decision":"block","reason":"Caliber agent config sync is not set up on this machine. Tell the user: This project uses Caliber to keep agent configs in sync — it is not set up yet. Want me to run /setup-caliber? (~30 seconds)"}'

.claude/settings.json

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
{
2+
"hooks": {
3+
"Stop": [
4+
{
5+
"matcher": "",
6+
"hooks": [
7+
{
8+
"type": "command",
9+
"command": ".claude/hooks/caliber-check-sync.sh",
10+
"description": "Caliber: offer setup if not configured"
11+
}
12+
]
13+
}
14+
],
15+
"PostToolUse": [
16+
{
17+
"matcher": "",
18+
"hooks": [
19+
{
20+
"type": "command",
21+
"command": "caliber learn observe",
22+
"description": "Caliber: recording tool usage for session learning"
23+
}
24+
]
25+
}
26+
],
27+
"PostToolUseFailure": [
28+
{
29+
"matcher": "",
30+
"hooks": [
31+
{
32+
"type": "command",
33+
"command": "caliber learn observe --failure",
34+
"description": "Caliber: recording tool failure for session learning"
35+
}
36+
]
37+
}
38+
],
39+
"UserPromptSubmit": [
40+
{
41+
"matcher": "",
42+
"hooks": [
43+
{
44+
"type": "command",
45+
"command": "caliber learn observe --prompt",
46+
"description": "Caliber: recording user prompt for correction detection"
47+
}
48+
]
49+
}
50+
],
51+
"SessionEnd": [
52+
{
53+
"matcher": "",
54+
"hooks": [
55+
{
56+
"type": "command",
57+
"command": "caliber learn finalize --auto",
58+
"description": "Caliber: finalizing session learnings"
59+
}
60+
]
61+
},
62+
{
63+
"matcher": "",
64+
"hooks": [
65+
{
66+
"type": "command",
67+
"command": "caliber refresh --quiet",
68+
"description": "Caliber: auto-refreshing docs based on code changes"
69+
}
70+
]
71+
}
72+
]
73+
},
74+
"permissions": {
75+
"allow": [
76+
"Bash(git *)"
77+
]
78+
}
79+
}
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
---
2+
name: find-skills
3+
description: Discovers and installs community skills from the public registry. Use when the user mentions a technology, framework, or task that could benefit from specialized skills not yet installed, asks 'how do I do X', 'find a skill for X', or starts work in a new technology area. Proactively suggest when the user's task involves tools or frameworks without existing skills.
4+
---
5+
6+
# Find Skills
7+
8+
Search the public skill registry for community-contributed skills
9+
relevant to the user's current task and install them into this project.
10+
11+
## Instructions
12+
13+
1. Identify the key technologies, frameworks, or task types from the
14+
user's request that might have community skills available
15+
2. Ask the user: "Would you like me to search for community skills
16+
for [identified technologies]?"
17+
3. If the user agrees, run:
18+
```bash
19+
caliber skills --query "<relevant terms>"
20+
```
21+
This outputs the top 5 matching skills with scores and descriptions.
22+
4. Present the results to the user and ask which ones to install
23+
5. Install the selected skills:
24+
```bash
25+
caliber skills --install <slug1>,<slug2>
26+
```
27+
6. Read the installed SKILL.md files to load them into your current
28+
context so you can use them immediately in this session
29+
7. Summarize what was installed and continue with the user's task
30+
31+
## Examples
32+
33+
User: "let's build a web app using React"
34+
-> "I notice you want to work with React. Would you like me to search
35+
for community skills that could help with React development?"
36+
-> If yes: run `caliber skills --query "react frontend"`
37+
-> Show the user the results, ask which to install
38+
-> Run `caliber skills --install <selected-slugs>`
39+
-> Read the installed files and continue
40+
41+
User: "help me set up Docker for this project"
42+
-> "Would you like me to search for Docker-related skills?"
43+
-> If yes: run `caliber skills --query "docker deployment"`
44+
45+
User: "I need to write tests for this Python ML pipeline"
46+
-> "Would you like me to find skills for Python ML testing?"
47+
-> If yes: run `caliber skills --query "python machine-learning testing"`
48+
49+
## When NOT to trigger
50+
51+
- The user is working within an already well-configured area
52+
- You already suggested skills for this technology in this session
53+
- The user is in the middle of urgent debugging or time-sensitive work
54+
- The technology is too generic (e.g. just "code" or "programming")
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
---
2+
name: myadmin-requirements
3+
description: Adds file/class requirements via getRequirements() in src/Plugin.php using $loader->add_requirement(). Use when user says 'add requirement', 'load file', 'register class', or needs to expose a new src file to the MyAdmin loader. Do NOT use for Composer dependencies — those go in composer.json.
4+
---
5+
# myadmin-requirements
6+
7+
## Critical
8+
9+
- **Never** add Composer packages here — use `composer.json` for that.
10+
- All paths must start with `/../vendor/detain/myadmin-novnc-plugin/src/` (leading `/../` is required by the MyAdmin loader).
11+
- Class file alias format: `class.ClassName`. Function/procedure aliases use the function name directly (e.g. `deactivate_abuse`).
12+
- Multiple functions in the same file each get their own `add_requirement()` call with identical paths.
13+
- Use tabs for indentation — not spaces.
14+
15+
## Instructions
16+
17+
1. **Identify the alias and file path.**
18+
- For a class: alias = `class.ClassName`, path = the full `/../vendor/detain/myadmin-novnc-plugin/src/` path to the class source file.
19+
- For a function/include: alias = the function name (e.g. `deactivate_abuse`), path = the source file containing it.
20+
- Verify the target file exists in `src/` before proceeding:
21+
```bash
22+
ls src/
23+
```
24+
25+
2. **Open `src/Plugin.php` and locate `getRequirements()`** (currently at line 53).
26+
The method body always starts with:
27+
```php
28+
$loader = $event->getSubject();
29+
```
30+
Add the new `add_requirement()` call after the existing calls, before the closing `}`.
31+
32+
3. **Add the line using this exact pattern:**
33+
```php
34+
$loader->add_requirement('alias', '/../vendor/detain/myadmin-novnc-plugin/src/SourceFile.php');
35+
```
36+
If multiple functions live in the same file, add one line per alias — all pointing to the same path.
37+
38+
4. **Update the test** in `tests/PluginTest.php`:
39+
- Increment the count in `testGetRequirementsRegistersExpectedRequirements()` (`assertCount(N, ...)`).
40+
- Add `assertContains('new_alias', $names)` for the new alias.
41+
- If the file is new, add a path assertion verifying it `assertStringContainsString('NewFile.php', $path)`.
42+
43+
5. **Run tests to verify:**
44+
```bash
45+
vendor/bin/phpunit
46+
```
47+
All tests must pass before committing.
48+
49+
## Examples
50+
51+
**User says:** "Add a requirement for the `open_novnc_console` function"
52+
53+
**Actions taken:**
54+
55+
1. Confirm the source file exists in `src/` by running `ls src/`.
56+
2. In `src/Plugin.php`, append inside `getRequirements()`:
57+
```php
58+
$loader->add_requirement('open_novnc_console', '/../vendor/detain/myadmin-novnc-plugin/src/NovncConsole.php');
59+
```
60+
3. In `tests/PluginTest.php`, update `testGetRequirementsRegistersExpectedRequirements()`:
61+
```php
62+
$this->assertCount(5, $loader->requirements, 'Should register exactly 5 requirements');
63+
// ...
64+
$this->assertContains('open_novnc_console', $names);
65+
```
66+
4. Run `vendor/bin/phpunit` — all tests green.
67+
68+
**Result:** `getRequirements()` now registers `open_novnc_console` and the loader can lazy-load it on demand.
69+
70+
## Common Issues
71+
72+
- **Test fails with `assertCount` mismatch** (e.g. `Failed asserting that 4 matches expected 5`): You added the requirement in `src/Plugin.php` but forgot to update the count in `testGetRequirementsRegistersExpectedRequirements()` — increment `assertCount(N, ...)` to match.
73+
- **Loader silently ignores the requirement at runtime**: The path does not start with `/../`. Ensure it is `'/../vendor/detain/...'` not `'/vendor/detain/...'`.
74+
- **`vendor/bin/phpunit` reports class not found**: The `src/` file does not exist yet. Create it before adding the requirement, or the loader will error when the alias is triggered.
75+
- **Two functions registered from the same file but only one works**: Each function alias needs its own `add_requirement()` line — the loader maps aliases to files one-to-one. Verify both lines are present.
Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
---
2+
name: plugin-hook
3+
description: Adds a new event hook to the MyAdmin NoVNC plugin system. Registers the hook in `getHooks()` and implements the corresponding static handler method on `Plugin` in `src/Plugin.php`. Use when user says 'add hook', 'register event', 'handle event', or needs to respond to a new MyAdmin event. Do NOT use for modifying `getMenu()` or `getRequirements()` — those have dedicated patterns.
4+
---
5+
# plugin-hook
6+
7+
## Critical
8+
9+
- All handler methods MUST be `public static` — never instance methods.
10+
- The `$event` parameter MUST be typed as `\Symfony\Component\EventDispatcher\GenericEvent`.
11+
- Use `__CLASS__` (not `self::class`) as the callable class reference in `getHooks()` — matches existing code.
12+
- Use tabs for indentation throughout `src/Plugin.php`.
13+
- Never remove or alter existing hooks in `getHooks()` — only add new entries.
14+
15+
## Instructions
16+
17+
1. **Identify the event name and handler method name.**
18+
Confirm the MyAdmin event string (e.g., `'system.settings'`, `'ui.menu'`) and choose a `camelCase` method name for the handler (e.g., `handleVncConnect`). Verify no method of that name already exists in `src/Plugin.php` before proceeding.
19+
20+
2. **Register the hook in `getHooks()`.**
21+
Open `src/Plugin.php` and add an entry to the returned array:
22+
```php
23+
public static function getHooks()
24+
{
25+
return [
26+
'your.event.name' => [__CLASS__, 'yourHandlerMethod'],
27+
];
28+
}
29+
```
30+
If active hooks are currently commented out (e.g., `//`), add your entry as a live line — do not uncomment unrelated hooks.
31+
32+
3. **Implement the handler method.**
33+
Add the static method immediately after `getSettings()`, following this exact signature and doc-block pattern from the existing handlers:
34+
```php
35+
/**
36+
* @param \Symfony\Component\EventDispatcher\GenericEvent $event
37+
*/
38+
public static function yourHandlerMethod(GenericEvent $event)
39+
{
40+
$subject = $event->getSubject();
41+
// handler logic here
42+
}
43+
```
44+
Use `$event->getSubject()` to get the payload object. No return value is needed (handlers are void).
45+
46+
4. **Add a PHPUnit test for the new hook.**
47+
Open `tests/PluginTest.php` and add two tests:
48+
- Assert `getHooks()` contains the new event key pointing to `[Plugin::class, 'yourHandlerMethod']`.
49+
- Assert the handler method is public and static via `ReflectionClass`.
50+
Follow the doc-block style already in `PluginTest.php`.
51+
52+
5. **Run tests to verify.**
53+
```bash
54+
vendor/bin/phpunit
55+
```
56+
All existing tests must still pass. The new tests must pass too.
57+
58+
## Examples
59+
60+
**User says:** "Add a hook for the `system.novnc_connect` event that logs the connection subject."
61+
62+
**Actions taken:**
63+
64+
`getHooks()` updated:
65+
```php
66+
public static function getHooks()
67+
{
68+
return [
69+
'system.novnc_connect' => [__CLASS__, 'handleNovncConnect'],
70+
];
71+
}
72+
```
73+
74+
New method added after `getSettings()`:
75+
```php
76+
/**
77+
* @param \Symfony\Component\EventDispatcher\GenericEvent $event
78+
*/
79+
public static function handleNovncConnect(GenericEvent $event)
80+
{
81+
$subject = $event->getSubject();
82+
// connection handling logic
83+
}
84+
```
85+
86+
Test added to `tests/PluginTest.php`:
87+
```php
88+
public function testGetHooksContainsNovncConnect(): void
89+
{
90+
$hooks = Plugin::getHooks();
91+
$this->assertArrayHasKey('system.novnc_connect', $hooks);
92+
$this->assertSame([Plugin::class, 'handleNovncConnect'], $hooks['system.novnc_connect']);
93+
}
94+
95+
public function testHandleNovncConnectIsStatic(): void
96+
{
97+
$reflection = new ReflectionClass(Plugin::class);
98+
$method = $reflection->getMethod('handleNovncConnect');
99+
$this->assertTrue($method->isStatic());
100+
$this->assertTrue($method->isPublic());
101+
}
102+
```
103+
104+
**Result:** `vendor/bin/phpunit` passes with all tests green.
105+
106+
## Common Issues
107+
108+
- **`Call to undefined method` at runtime:** The method name in `getHooks()` must exactly match the implemented method name — PHP is case-sensitive for string-based callables.
109+
- **`testPublicMethodCount` fails (expected 5, got 6):** The existing test in `PluginTest.php:410` asserts exactly 5 own public methods. Update that assertion to reflect the new count after adding your handler.
110+
- **`GenericEvent` not found / class not imported:** Confirm `use Symfony\Component\EventDispatcher\GenericEvent;` is at the top of `src/Plugin.php` — it is already present in the existing file.
111+
- **Indentation inconsistency causes CS failures:** `src/Plugin.php` uses tabs. If your editor inserts spaces, the `.scrutinizer.yml` coding-style check will fail. Run `make php-cs-fixer` (from the parent MyAdmin project) or manually verify tabs are used.
112+
- **Hook never fires:** Confirm the event string matches exactly what the MyAdmin framework dispatches — check `include/config/hooks.json` in the parent project for the authoritative event name list.

0 commit comments

Comments
 (0)