Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 9 additions & 9 deletions USAGE.md
Original file line number Diff line number Diff line change
Expand Up @@ -522,21 +522,21 @@ cd rust
`SKILL.md` or a standalone markdown file. This is useful when a companion
repository ships a skill prompt that should be available through `/skills`.

For example, install TweetClaw as an X/Twitter automation skill:
For example, install the portable X Twitter Scraper Skill:

```bash
# From a parent directory that contains claw-code
git clone https://github.com/Xquik-dev/tweetclaw
git clone --depth 1 https://github.com/Xquik-dev/x-twitter-scraper
cd claw-code/rust
./target/debug/claw skills install ../../tweetclaw/skills/tweetclaw
./target/debug/claw skills show tweetclaw
./target/debug/claw skills uninstall tweetclaw
./target/debug/claw skills install ../../x-twitter-scraper/skills/x-twitter-scraper
./target/debug/claw skills show x-twitter-scraper
./target/debug/claw skills uninstall x-twitter-scraper
```

TweetClaw gives `claw` users a local skill guide for OpenClaw/Xquik workflows
such as tweet search, reply search, follower export, monitors, webhooks, and
approval-gated posting. Configure any Xquik credentials outside the prompt and
avoid pasting API keys into chat.
The Skill gives `claw` portable instructions for X research and Xquik API
workflows. Installing a Skill does not add a plugin or network transport.
Verify required tools separately. Configure credentials outside the prompt,
and never paste API keys into chat.

## Author a local agent

Expand Down
18 changes: 18 additions & 0 deletions rust/crates/commands/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4240,6 +4240,9 @@ fn parse_skill_frontmatter(contents: &str) -> (Option<String>, Option<String>) {
if trimmed == "---" {
break;
}
if line.trim_start() != line {
continue;
}
if let Some(value) = trimmed.strip_prefix("name:") {
let value = unquote_frontmatter_value(value.trim());
if !value.is_empty() {
Expand Down Expand Up @@ -4297,6 +4300,9 @@ fn parse_agent_frontmatter(
if trimmed == "---" {
break;
}
if line.trim_start() != line {
continue;
}
if let Some(value) = trimmed.strip_prefix("name:") {
let value = unquote_frontmatter_value(value.trim());
if !value.is_empty() {
Expand Down Expand Up @@ -7029,6 +7035,18 @@ mod tests {
assert_eq!(description.as_deref(), Some("Quoted description"));
}

#[test]
fn frontmatter_parsers_ignore_nested_metadata() {
let contents = "---\nname: root-name\ndescription: Root description\nmetadata:\n name: nested-name\n description: Nested description\n---\n";
let (skill_name, skill_description) = super::parse_skill_frontmatter(contents);
assert_eq!(skill_name.as_deref(), Some("root-name"));
assert_eq!(skill_description.as_deref(), Some("Root description"));

let (agent_name, agent_description, _, _) = super::parse_agent_frontmatter(contents);
assert_eq!(agent_name.as_deref(), Some("root-name"));
assert_eq!(agent_description.as_deref(), Some("Root description"));
}

#[test]
fn installs_skill_into_user_registry_and_preserves_nested_files() {
let workspace = temp_dir("skills-install-workspace");
Expand Down
Loading