Skip to content

Commit d472c07

Browse files
committed
update adding claude.md
1 parent 9bbd2aa commit d472c07

13 files changed

Lines changed: 1298 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: 146 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,146 @@
1+
---
2+
name: async-soap-script
3+
description: Creates a ReactPHP async SOAP script in bin/async/ for the myadmin-hyperv-vps plugin. Use when user says 'async version', 'non-blocking', 'ReactPHP', or wants a bin/async/ variant of a SOAP operation. Uses React\EventLoop, React\Socket\Connector (TLS verify disabled), React\Http\Browser, Clue\React\Soap\Client and Proxy. Do NOT use for standard synchronous bin/ scripts — those follow a different pattern in bin/ directly.
4+
---
5+
# async-soap-script
6+
7+
Create a ReactPHP async SOAP script in `bin/async/` for a Hyper-V SOAP operation.
8+
9+
## Critical
10+
11+
- **Include path is one level deeper** than `bin/`: `__DIR__.'/../../../../../include/functions.inc.php'` (five `../` segments, not four).
12+
- **TLS verification must be disabled** on both the `React\Socket\Connector` (`verify_peer`, `verify_peer_name`) — the Hyper-V SOAP endpoint uses a self-signed cert.
13+
- **Never use `Plugin::getSoapClientParams()`** in async scripts — that is synchronous `SoapClient` config. The async path fetches the WSDL via `$browser->get()` and passes the body string to `Clue\React\Soap\Client`.
14+
- **Result property name** mirrors the method name: `CheckVMExists``$result->CheckVMExistsResult`. Derive it as `{MethodName}Result`.
15+
- The outer try/catch block wraps `get_service_master()` and the entire event-loop setup. The inner `->done()` error callback handles async failures separately.
16+
17+
## Instructions
18+
19+
1. **Identify the target SOAP method and its parameters.**
20+
- Find the equivalent synchronous script in `bin/` (e.g. `bin/CheckVMExists.php`) and note the method name and its parameter array.
21+
- Verify the synchronous script exists before proceeding.
22+
23+
2. **Create the file inside `bin/async/`.**
24+
- Use the PascalCase SOAP method name, matching the synchronous counterpart exactly — e.g. `bin/async/TurnON.php` for the `TurnON` method, `bin/async/CheckVMExists.php` for `CheckVMExists`.
25+
26+
3. **Write the shebang and bootstrap block** (copy verbatim):
27+
```php
28+
#!/usr/bin/env php
29+
<?php
30+
include_once __DIR__.'/../../../../../include/functions.inc.php';
31+
ini_set('soap.wsdl_cache_enabled', '0');
32+
ini_set('default_socket_timeout', 1000);
33+
ini_set('max_input_time', '0');
34+
ini_set('max_execution_time', '0');
35+
ini_set('display_errors', '1');
36+
ini_set('error_reporting', E_ALL);
37+
```
38+
39+
4. **Write the argument count check.** Use the same `argc` minimum and die-message style as the sync script:
40+
```php
41+
if ($_SERVER['argc'] < 3) {
42+
die("Call like {$_SERVER['argv'][0]} <id> <vps>\nwhere <id> is the VPS Master / Host Server ID\nuse 423 for Hyperv-dev and 440 for Hyperv1\n and <vps> is the id of a vps\n");
43+
}
44+
```
45+
Adjust `< 3` and the message if the method takes fewer/more arguments (e.g. `GetVMList` only needs `<id>`, so `< 2`).
46+
47+
5. **Write the async body inside a try/catch block:**
48+
```php
49+
try {
50+
$master = get_service_master($_SERVER['argv'][1], 'vps', true);
51+
$loop = React\EventLoop\Factory::create();
52+
$connector = new React\Socket\Connector(['tls' => ['verify_peer' => false, 'verify_peer_name' => false]]);
53+
$browser = new React\Http\Browser($connector, $loop);
54+
$wsdl = "https://{$master['vps_ip']}/HyperVService/HyperVService.asmx?WSDL";
55+
$browser->get($wsdl)->done(
56+
function (Psr\Http\Message\ResponseInterface $response) use ($browser, $master) {
57+
$client = new Clue\React\Soap\Client($browser, (string)$response->getBody());
58+
$proxy = new Clue\React\Soap\Proxy($client);
59+
$proxy->MethodName(['vmId' => $_SERVER['argv'][2], 'hyperVAdmin' => 'Administrator', 'adminPassword' => $master['vps_root']])->then(function ($result) {
60+
print_r($result->MethodNameResult);
61+
});
62+
},
63+
function (Exception $e) {
64+
echo 'Error: ' . $e->getMessage() . PHP_EOL;
65+
}
66+
);
67+
$loop->run();
68+
} catch (Exception $e) {
69+
echo 'Caught exception: '.$e->getMessage().PHP_EOL;
70+
}
71+
```
72+
- Replace `MethodName` with the actual SOAP method (e.g. `CheckVMExists`).
73+
- Replace `MethodNameResult` with `{MethodName}Result` (e.g. `CheckVMExistsResult`).
74+
- Replace the `$proxy->MethodName([...])` parameter array with the exact params from the sync script.
75+
- For methods that return a simple response (not a `*Result` property), use `print_r($result)` instead.
76+
77+
6. **Make the file executable** (using `bin/async/TurnON.php` as the example):
78+
```bash
79+
chmod +x bin/async/TurnON.php
80+
```
81+
82+
7. **Verify the script runs without parse errors** (using `bin/async/TurnON.php` as the example):
83+
```bash
84+
php -l bin/async/TurnON.php
85+
```
86+
87+
## Examples
88+
89+
**User says:** "Create an async version of TurnON"
90+
91+
**Actions taken:**
92+
1. Read `bin/TurnON.php` — method is `TurnON`, params are `vmId`, `hyperVAdmin`, `adminPassword`, argc < 3.
93+
2. Create `bin/async/TurnON.php`:
94+
95+
```php
96+
#!/usr/bin/env php
97+
<?php
98+
include_once __DIR__.'/../../../../../include/functions.inc.php';
99+
ini_set('soap.wsdl_cache_enabled', '0');
100+
ini_set('default_socket_timeout', 1000);
101+
ini_set('max_input_time', '0');
102+
ini_set('max_execution_time', '0');
103+
ini_set('display_errors', '1');
104+
ini_set('error_reporting', E_ALL);
105+
if ($_SERVER['argc'] < 3) {
106+
die("Call like {$_SERVER['argv'][0]} <id> <vps>\nwhere <id> is the VPS Master / Host Server ID\nuse 423 for Hyperv-dev and 440 for Hyperv1\n and <vps> is the id of a vps\n");
107+
}
108+
try {
109+
$master = get_service_master($_SERVER['argv'][1], 'vps', true);
110+
$loop = React\EventLoop\Factory::create();
111+
$connector = new React\Socket\Connector(['tls' => ['verify_peer' => false, 'verify_peer_name' => false]]);
112+
$browser = new React\Http\Browser($connector, $loop);
113+
$wsdl = "https://{$master['vps_ip']}/HyperVService/HyperVService.asmx?WSDL";
114+
$browser->get($wsdl)->done(
115+
function (Psr\Http\Message\ResponseInterface $response) use ($browser, $master) {
116+
$client = new Clue\React\Soap\Client($browser, (string)$response->getBody());
117+
$proxy = new Clue\React\Soap\Proxy($client);
118+
$proxy->TurnON(['vmId' => $_SERVER['argv'][2], 'hyperVAdmin' => 'Administrator', 'adminPassword' => $master['vps_root']])->then(function ($result) {
119+
print_r($result);
120+
});
121+
},
122+
function (Exception $e) {
123+
echo 'Error: ' . $e->getMessage() . PHP_EOL;
124+
}
125+
);
126+
$loop->run();
127+
} catch (Exception $e) {
128+
echo 'Caught exception: '.$e->getMessage().PHP_EOL;
129+
}
130+
```
131+
132+
> Note: `TurnON` does not return a `TurnONResult` property — `print_r($result)` is used instead, matching the sync script.
133+
134+
**Result:** `bin/async/TurnON.php` created and executable.
135+
136+
## Common Issues
137+
138+
- **`include_once` fails with "No such file":** The async path needs five `../` (`__DIR__.'/../../../../../include/functions.inc.php'`), not four. Sync scripts in `bin/` use four.
139+
140+
- **`Class 'React\EventLoop\Factory' not found`:** The ReactPHP packages are not installed. Run `composer install` and verify `react/event-loop`, `react/socket`, `react/http`, and `clue/reactphp-soap` are in `composer.json`.
141+
142+
- **`Error: cURL error 60: SSL certificate problem`:** TLS options on the `Connector` are missing or wrong. Must be exactly `['tls' => ['verify_peer' => false, 'verify_peer_name' => false]]`.
143+
144+
- **`Undefined property: $result->CheckVMExistsResult`:** Result property name is wrong. The convention is `{MethodName}Result`. Check the sync script — if it uses `print_r($response)` rather than `print_r($response->SomeResult)`, the method has no `*Result` property; use `print_r($result)` directly.
145+
146+
- **Script exits immediately with no output:** `$loop->run()` was omitted or placed outside the try block. It must be the last statement inside try, after `$browser->get(...)->done(...)`.
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")

0 commit comments

Comments
 (0)