Skill: guilherme-funchal/cep-lookup (version 1.0.0)

--- name: cep-lookup description: Looks up address data for a Brazilian CEP using the ViaCEP API. metadata: { "openclaw": { "emoji": "📮", "requires": { "bins": ["node", "npm"] }, "install": [ { "id": "npm", "kind": "npm", "package": "axios", "bins": ["axios"], "label": "Install axios for HTTP requests", } ], }, } --- # CEP Lookup Looks up the full address for a Brazilian postal code (CEP) using the public [ViaCEP](https://viacep.com.br) API. No authentication required. ## Triggers Use this skill when the user mentions a CEP in any of these formats: - `cep 01001-000` - `CEP 20040020` - `details for CEP 30140-110` ## Output The skill returns: - Street (logradouro) - Neighborhood (bairro) - City (localidade) - State (UF) - Complement, if available (complemento) ## Error handling - Invalid CEP format → usage instruction - CEP not found in ViaCEP database → informative message - Network failure → generic error message

path: skill.json
content: {
    "name": "CEP Lookup",
    "description": "Skill that looks up address data for a Brazilian CEP using ViaCEP",
    "version": "1.0.0",
    "main": "index.js",
    "triggers": [
      {
        "type": "message",
        "pattern": "cep (\\d{5}-?\\d{3})"
      }
    ]
}

path: test.js
content: /**
 * test.js — Local test runner for the CEP Lookup skill
 *
 * Usage:
 *   node test.js          → runs with real ViaCEP API calls
 *   node test.js --mock   → runs with mocked responses (no internet needed)
 */

const MOCK_MODE = process.argv.includes('--mock');

// --- Mock axios in mock mode ---
if (MOCK_MODE) {
    const Module = require('module');
    const originalLoad = Module._load;

    Module._load = function (request, ...args) {
        if (request === 'axios') {
            return {
                get: async (url) => {
                    if (url.includes('01001000')) {
                        return {
                            data: {
                                logradouro: 'Praça da Sé',
                                bairro: 'Sé',
                                localidade: 'São Paulo',
                                uf: 'SP',
                                complemento: 'lado ímpar',
                            },
                        };
                    }
                    if (url.includes('00000000')) {
                        return { data: { erro: true } };
                    }
                    throw new Error('Network error');
                },
            };
        }
        return originalLoad(request, ...args);
    };
}

const skill = require('./index');

// Helper: simulate the OpenClaw context object
function makeContext(text) {
    return { message: { text } };
}

// --- Test cases ---
const tests = [
    {
        description: 'Valid CEP with dash',
        input: 'cep 01001-000',
        expect: (result) => result.includes('São Paulo'),
    },
    {
        description: 'Valid CEP without dash',
        input: 'cep 01001000',
        expect: (result) => result.includes('São Paulo'),
    },
    {
        description: 'English-style trigger',
        input: 'What are the details for CEP 01001-000',
        expect: (result) => result.includes('São Paulo'),
    },
    {
        description: 'Uppercase CEP keyword',
        input: 'CEP 01001-000',
        expect: (result) => result.includes('São Paulo'),
    },
    {
        description: 'CEP not found',
        input: 'cep 00000-000',
        expect: (result) => result.includes('not found'),
    },
    {
        description: 'Invalid format (too few digits)',
        input: 'cep 1234',
        expect: (result) => result.includes('Invalid CEP format'),
    },
    {
        description: 'No CEP in message',
        input: 'hello there',
        expect: (result) => result.includes('Invalid CEP format'),
    },
];

// --- Runner ---
async function run() {
    const mode = MOCK_MODE ? 'MOCK' : 'LIVE';
    console.log(`\nRunning CEP Skill tests... [${mode} mode]\n`);

    let passed = 0;
    let failed = 0;

    for (const test of tests) {
        process.stdout.write(`  ${test.description} ... `);
        try {
            const result = await skill(makeContext(test.input));
            const ok = test.expect(result);
            if (ok) {
                console.log('✅ PASS');
                passed++;
            } else {
                console.log('❌ FAIL');
                failed++;
            }
            // Always show the input and result
            console.log(`     Input:  "${test.input}"`);
            console.log(`     Result:`);
            result.split('\n').forEach((line) => console.log(`       ${line}`));
        } catch (err) {
            console.log('💥 ERROR');
            console.log(`     ${err.message}`);
            failed++;
        }
    }

    console.log(`\nResults: ${passed} passed, ${failed} failed out of ${tests.length} tests.\n`);
    process.exit(failed > 0 ? 1 : 0);
}

run();

path: index.js
content: const axios = require('axios');

module.exports = async function(context) {
    const message = context.message.text;

    // Supports: "cep 01001-000", "CEP 01001000" and "details for CEP 01001-000"
    const match = message.match(/cep[:\s]+(\d{5}-?\d{3})/i);

    if (!match) {
        return "Invalid CEP format. Try something like: cep 01001-000";
    }

    const cep = match[1].replace("-", "");

    try {
        const response = await axios.get(`https://viacep.com.br/ws/${cep}/json/`);
        const data = response.data;

        if (data.erro) {
            return `CEP ${cep} not found.`;
        }

        return `Details for CEP ${cep}:
- Street: ${data.logradouro}
- Neighborhood: ${data.bairro}
- City: ${data.localidade}
- State: ${data.uf}
- Complement: ${data.complemento || "none"}`;

    } catch (err) {
        console.error(err);
        return "Error looking up CEP. Please try again later.";
    }
};


path: README.md
content: # CEP Lookup Skill for OpenClaw 📮

This OpenClaw skill allows users to look up Brazilian postal codes (CEP) quickly and easily using the [ViaCEP API](https://viacep.com.br).  
It returns detailed address information including **street (logradouro), neighborhood (bairro), city (localidade), state (uf), and complement**.

---

## Features

- Query any valid Brazilian CEP.
- Returns complete address information.
- Easy to install and use with OpenClaw.
- No API key required – uses the public ViaCEP service.

---

## Installation

1. Copy the folder to the OpenClaw skills directory:

```bash
cp -r cepSkill ~/.openclaw/workspace/skills/

cd ~/.openclaw/workspace/skills/cepSkill
npm install
```

---

## Usage

Once installed, you can use the skill by simply asking:

```
cep 01001-000
```

or

```
What are the details for CEP 20040-020
```

The skill will return a message like:

```
Details for CEP 01001000:
- Street: Praça da Sé
- Neighborhood: Sé
- City: São Paulo
- State: SP
- Complement: none
```

## Example Queries

```
cep 30140-110
What are the details for CEP 20040-020
```

## Notes

- The skill only works with valid Brazilian CEPs.
- Ensure your OpenClaw instance has internet access to reach the ViaCEP API.
- No authentication is required to use the ViaCEP service.
- The trigger pattern supports both Portuguese (`cep XXXXX-XXX`) and English (`details for CEP XXXXX-XXX`).

## Dependencies

- [axios](https://www.npmjs.com/package/axios) – for HTTP requests.

Install dependencies with:

```bash
npm install
```

## Contributing

Feel free to fork the repository, improve the skill, or add additional features for Brazilian address lookup.

## License

MIT License


path: package.json
content: {
    "name": "cep-skill",
    "version": "1.0.0",
    "main": "index.js",
    "author": "Guilherme Funchal",
    "license": "MIT",
    "dependencies": {
      "axios": "^1.6.0"
    }
}


Security scan verdicts — ClawScan: clean | static analysis: clean | VirusTotal: clean | SkillSpector: clean (LOW)