# Getting Started with lua-cli

A comprehensive step-by-step guide to building and deploying your first AI agent with lua-cli.

---

## Table of Contents

1. [Prerequisites](#prerequisites)
2. [Installation](#installation)
3. [Authentication](#authentication)
4. [Create Your First Agent](#create-your-first-agent)
5. [Add Your First Tool](#add-your-first-tool)
6. [Test Your Tool](#test-your-tool)
7. [Create a Skill](#create-a-skill)
8. [Chat with Your Agent](#chat-with-your-agent)
9. [Deploy to Production](#deploy-to-production)
10. [Add a Webhook](#add-a-webhook)
11. [Schedule a Job](#schedule-a-job)
12. [Next Steps](#next-steps)

---

## Prerequisites

Before starting, ensure you have:

- **Node.js 16+** installed ([download](https://nodejs.org/))
- **npm** or **yarn** package manager
- **TypeScript 5+** familiarity (basic knowledge)
- **Lua API key** (sign up at [admin.heylua.ai](https://admin.heylua.ai))

**Check your Node.js version:**
```bash
node --version
# Should output: v16.0.0 or higher
```

---

## Installation

### Global Installation (Recommended)

Install lua-cli globally to use the `lua` command anywhere:

```bash
npm install -g lua-cli
```

### Verify Installation

```bash
lua --version
# Output: lua-cli v3.5.0-alpha.3
```

If the command isn't found, ensure npm global bin is in your PATH:
```bash
npm config get prefix
# Add this to your PATH: /usr/local/bin or similar
```

---

## Authentication

### Step 1: Get Your API Key

1. Visit [admin.heylua.ai](https://admin.heylua.ai)
2. Sign up or log in
3. Navigate to **Settings → API Keys**
4. Copy your API key

### Step 2: Configure CLI

```bash
lua auth configure
```

When prompted, paste your API key:

```
? Enter your Lua API key: **********************
✅ API key configured successfully
```

**What just happened?**
Your API key is securely stored in:
- **macOS**: Keychain
- **Windows**: Credential Vault
- **Linux**: libsecret

**Alternative (CI/CD):**
```bash
export LUA_API_KEY=your-api-key
# Or add to .env file
```

---

## Create Your First Agent

### Step 1: Create Project Directory

```bash
mkdir my-assistant
cd my-assistant
```

### Step 2: Initialize Project

```bash
lua init
```

You'll be guided through setup:

```
? Select an agent:
❯ Create new agent
  my-existing-agent

? Agent name: my-assistant
? Persona: You are a helpful AI assistant that can help with weather, calculations, and general queries.
? Welcome message: Hello! I'm your AI assistant. How can I help you today?

✅ Project initialized successfully
```

### Step 3: Explore Project Structure

```bash
tree -L 3
```

Output:
```
my-assistant/
├── src/
│   ├── index.ts              # LuaAgent configuration
│   ├── skills/               # Tool collections
│   │   └── general.skill.ts  # Default skill
│   ├── webhooks/             # HTTP endpoints
│   ├── jobs/                 # Scheduled tasks
│   ├── preprocessors/        # Message filters
│   └── postprocessors/       # Response formatters
├── lua.skill.yaml           # Agent metadata
├── package.json
├── tsconfig.json
└── .env
```

### Step 4: Install Dependencies

```bash
npm install
```

**Key dependencies:**
- `zod` - Schema validation
- `lua-cli` - SDK and runtime APIs

---

## Add Your First Tool

Let's create a weather tool!

### Step 1: Create Tool File

```bash
mkdir -p src/skills/tools
```

Create `src/skills/tools/WeatherTool.ts`:

```typescript
import { LuaTool } from 'lua-cli/skill';
import { z } from 'zod';

export default class WeatherTool implements LuaTool {
  name = 'get_weather';
  description = 'Get current weather for any city';

  inputSchema = z.object({
    city: z.string().describe('City name'),
    units: z.enum(['metric', 'imperial']).optional().describe('Temperature units')
  });

  outputSchema = z.object({
    temperature: z.number(),
    condition: z.string(),
    city: z.string(),
    feelsLike: z.number().optional()
  });

  async execute(input: z.infer<typeof this.inputSchema>) {
    // For demo purposes, we'll return mock data
    // In production, you'd call a weather API
    const temp = Math.floor(Math.random() * 30) + 10;

    return {
      temperature: temp,
      condition: ['sunny', 'cloudy', 'rainy'][Math.floor(Math.random() * 3)],
      city: input.city,
      feelsLike: temp + Math.floor(Math.random() * 5) - 2
    };
  }
}
```

**Tool Anatomy:**
- `name` - Unique identifier (snake_case)
- `description` - What the tool does (AI uses this)
- `inputSchema` - Zod schema for input validation
- `outputSchema` - Zod schema for output validation
- `execute()` - Tool implementation

### Step 2: Add Tool to Skill

Open `src/skills/general.skill.ts`:

```typescript
import { LuaSkill } from 'lua-cli';
import WeatherTool from './tools/WeatherTool.js';

export default new LuaSkill({
  name: 'general-skill',
  description: 'General purpose tools',
  context: 'Use these tools for weather information and general queries',
  tools: [
    new WeatherTool()
  ]
});
```

### Step 3: Register Skill in Agent

Open `src/index.ts`:

```typescript
import { LuaAgent } from 'lua-cli';
import generalSkill from './skills/general.skill.js';

export const agent = new LuaAgent({
  name: 'my-assistant',
  persona: 'You are a helpful AI assistant that can help with weather, calculations, and general queries.',
  skills: [generalSkill]
});
```

---

## Test Your Tool

### Step 1: Compile

```bash
lua compile
```

Output:
```
⏳ Compiling agent...
✅ Compiled 1 tool, 1 skill
✅ Compilation complete
```

**What happened?**
- TypeScript compiled to JavaScript
- Tool validated (schema, name, structure)
- Artifacts saved to `.lua/artifacts/`
- Manifest generated

### Step 2: Interactive Testing

```bash
lua test
```

Interactive flow:
```
? Select type: Tool
? Select tool: get_weather
? Input (JSON): { "city": "London" }

⏳ Executing...
✅ Result:
{
  "temperature": 18,
  "condition": "cloudy",
  "city": "London",
  "feelsLike": 17
}

? Test again? No
```

**Testing Tips:**
- Use valid JSON for input
- Test edge cases (empty strings, invalid data)
- Tools run in sandbox with full API access

---

## Create a Skill

Skills group related tools together. Let's create a calculator skill.

### Step 1: Create Calculator Tools

`src/skills/tools/AddTool.ts`:
```typescript
import { LuaTool } from 'lua-cli/skill';
import { z } from 'zod';

export default class AddTool implements LuaTool {
  name = 'add';
  description = 'Add two numbers together';

  inputSchema = z.object({
    a: z.number().describe('First number'),
    b: z.number().describe('Second number')
  });

  async execute(input: z.infer<typeof this.inputSchema>) {
    return { result: input.a + input.b };
  }
}
```

`src/skills/tools/MultiplyTool.ts`:
```typescript
import { LuaTool } from 'lua-cli/skill';
import { z } from 'zod';

export default class MultiplyTool implements LuaTool {
  name = 'multiply';
  description = 'Multiply two numbers';

  inputSchema = z.object({
    a: z.number(),
    b: z.number()
  });

  async execute(input: z.infer<typeof this.inputSchema>) {
    return { result: input.a * input.b };
  }
}
```

### Step 2: Create Calculator Skill

`src/skills/calculator.skill.ts`:
```typescript
import { LuaSkill } from 'lua-cli';
import AddTool from './tools/AddTool.js';
import MultiplyTool from './tools/MultiplyTool.js';

export default new LuaSkill({
  name: 'calculator-skill',
  description: 'Mathematical calculation tools',
  context: 'Use these tools when the user asks to perform calculations or math operations',
  tools: [
    new AddTool(),
    new MultiplyTool()
  ]
});
```

### Step 3: Add to Agent

Update `src/index.ts`:
```typescript
import { LuaAgent } from 'lua-cli';
import generalSkill from './skills/general.skill.js';
import calculatorSkill from './skills/calculator.skill.js';

export const agent = new LuaAgent({
  name: 'my-assistant',
  persona: 'You are a helpful AI assistant that can help with weather, calculations, and general queries.',
  skills: [
    generalSkill,
    calculatorSkill  // ← Added
  ]
});
```

### Step 4: Compile and Test

```bash
lua compile
lua test
```

---

## Chat with Your Agent

Now let's have a real conversation with the agent!

### Step 1: Start Chat

```bash
lua chat
```

Output:
```
🤖 Hello! I'm your AI assistant. How can I help you today?

You:
```

### Step 2: Test Tools

Try these queries:

**Weather Query:**
```
You: What's the weather in Paris?
🔄 Calling tool: get_weather...
Agent: The current weather in Paris is 22°C and sunny. It feels like 23°C.
```

**Calculator Query:**
```
You: What's 15 + 27?
🔄 Calling tool: add...
Agent: 15 + 27 equals 42.
```

**Mixed Query:**
```
You: What's the weather in London, and what's 100 × 5?
🔄 Calling tool: get_weather...
🔄 Calling tool: multiply...
Agent: The weather in London is 14°C and rainy. Also, 100 × 5 equals 500.
```

### Step 3: Exit Chat

```
You: /exit
👋 Goodbye!
```

---

## Deploy to Production

Ready to make your agent live? Let's deploy!

### Step 1: Compile

```bash
lua compile
```

### Step 2: Push to Server

```bash
lua push all --force
```

Output:
```
⏳ Pushing all primitives...
✅ Pushed general-skill v1.0.0
✅ Pushed calculator-skill v1.0.0
? Deploy to production? Yes
✅ Deployed to production
```

**What happened?**
- Artifacts uploaded to server
- New versions created (1.0.0)
- Agent activated in production

### Step 3: Verify Production

```bash
lua production
```

Output:
```
📊 Production Status

Skills:
  ✅ general-skill v1.0.0
  ✅ calculator-skill v1.0.0

Webhooks: (none)
Jobs: (none)
```

### Step 4: Test Production

```bash
lua chat --production
```

Your agent is now live! 🎉

---

## Add a Webhook

Webhooks let external systems trigger actions in your agent.

### Step 1: Create Webhook

`src/webhooks/payment.webhook.ts`:
```typescript
import { LuaWebhook } from 'lua-cli';
import { z } from 'zod';
import { User } from 'lua-cli';

export default new LuaWebhook({
  name: 'payment-webhook',
  description: 'Handle payment notifications from Stripe',

  bodySchema: z.object({
    orderId: z.string(),
    amount: z.number(),
    status: z.enum(['succeeded', 'failed'])
  }),

  execute: async ({ body, headers, query }) => {
    console.log('Payment received:', body);

    // Send notification to user
    if (body.status === 'succeeded') {
      const user = await User.get();
      await user.send([{
        type: 'text',
        text: `✅ Payment of $${body.amount} for order ${body.orderId} succeeded!`
      }]);
    }

    return {
      status: 200,
      body: { received: true }
    };
  }
});
```

### Step 2: Register Webhook

Update `src/index.ts`:
```typescript
import paymentWebhook from './webhooks/payment.webhook.js';

export const agent = new LuaAgent({
  name: 'my-assistant',
  persona: '...',
  skills: [generalSkill, calculatorSkill],
  webhooks: [paymentWebhook]  // ← Added
});
```

### Step 3: Deploy

```bash
lua compile
lua push webhook --name payment-webhook --force
```

### Step 4: Get Webhook URL

```bash
lua webhooks url payment-webhook
```

Output:
```
🔗 Webhook URL:
https://api.heylua.ai/webhooks/hook_abc123xyz
```

Use this URL in your Stripe/Shopify/etc. webhook configuration!

---

## Schedule a Job

Jobs run automatically on a schedule or once at a specific time.

### Step 1: Create Job

`src/jobs/daily-summary.job.ts`:
```typescript
import { LuaJob } from 'lua-cli';
import { User, Data } from 'lua-cli';

export default new LuaJob({
  name: 'daily-summary',
  description: 'Send daily summary to user',

  schedule: {
    type: 'cron',
    pattern: '0 9 * * *'  // Every day at 9 AM
  },

  execute: async (job) => {
    const user = await job.user();

    // Fetch some data
    const activities = await Data.get('activities');

    await user.send([{
      type: 'text',
      text: `Good morning! You have ${activities.length} activities logged this week.`
    }]);

    return { success: true, sent: activities.length };
  }
});
```

**Schedule Types:**
- `cron` - Cron expression (e.g., `0 9 * * *`)
- `once` - Run once at specific time (`executeAt: Date`)
- `interval` - Run every X seconds (`interval: 3600`)

### Step 2: Register Job

Update `src/index.ts`:
```typescript
import dailySummaryJob from './jobs/daily-summary.job.js';

export const agent = new LuaAgent({
  name: 'my-assistant',
  persona: '...',
  skills: [generalSkill, calculatorSkill],
  webhooks: [paymentWebhook],
  jobs: [dailySummaryJob]  // ← Added
});
```

### Step 3: Deploy

```bash
lua compile
lua push job --name daily-summary --force
```

### Step 4: Test Immediately

```bash
lua jobs run daily-summary
```

---

## Next Steps

Congratulations! You've built and deployed your first AI agent. 🎉

### Learn More

**Core Concepts:**
- [API Reference](./API_REFERENCE.md) - All available APIs
- [CLI Reference](./CLI_REFERENCE.md) - All commands and options

**Advanced Topics:**
- [PreProcessors](../docs/api/PreProcessor.md) - Filter incoming messages
- [PostProcessors](../docs/api/PostProcessor.md) - Format responses
- [User API](../docs/api/User.md) - Access user data
- [Products API](../docs/api/Products.md) - Manage product catalog
- [Data API](../docs/api/Data.md) - Custom data storage

**Integrations:**
- [Marketplace](./CLI_REFERENCE.md#marketplace) - Install community skills
- [Integrations](./CLI_REFERENCE.md#lua-integrations) - Connect Linear, Discord, etc.

### Common Patterns

**Real-time Weather API:**
```typescript
import axios from 'axios';

async execute(input: z.infer<typeof this.inputSchema>) {
  const response = await axios.get('https://api.openweathermap.org/data/2.5/weather', {
    params: {
      q: input.city,
      appid: process.env.OPENWEATHER_API_KEY,
      units: input.units || 'metric'
    }
  });

  return {
    temperature: response.data.main.temp,
    condition: response.data.weather[0].main,
    city: input.city
  };
}
```

**User Data Access:**
```typescript
import { User } from 'lua-cli';

async execute() {
  const user = await User.get();
  console.log('User:', user.name, user.email);

  await user.update({ preferences: 'dark-mode' });

  return { success: true };
}
```

**Custom Data Storage:**
```typescript
import { Data } from 'lua-cli';

async execute(input) {
  // Create
  await Data.create('notes', {
    title: input.title,
    content: input.content,
    timestamp: new Date()
  });

  // Search
  const results = await Data.search('notes', input.query);

  return { results };
}
```

### Development Workflow

**Iterative Development:**
```bash
# 1. Make changes
vim src/skills/tools/MyTool.ts

# 2. Test
lua test

# 3. Chat test
lua chat

# 4. Deploy
lua compile
lua push skill --name my-skill --force
```

**CI/CD Deployment:**
```yaml
# .github/workflows/deploy.yml
name: Deploy Agent

on:
  push:
    branches: [main]

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v2
      - uses: actions/setup-node@v2
        with:
          node-version: '18'

      - run: npm install
      - run: npm install -g lua-cli

      - name: Deploy
        run: lua push all --ci --force --auto-deploy
        env:
          LUA_API_KEY: ${{ secrets.LUA_API_KEY }}
```

### Troubleshooting

**Compilation Errors:**
```bash
lua compile --debug
# Shows detailed AST parsing and validation
```

**Authentication Issues:**
```bash
lua auth configure
# Re-enter API key
```

**Test Failures:**
```bash
lua test
# Test tools interactively to debug
```

**Production Debugging:**
```bash
lua logs --follow
# Watch real-time logs
```

### Get Help

- **Documentation**: [docs.heylua.ai](https://docs.heylua.ai)
- **Email**: support@heylua.ai
- **GitHub Issues**: [github.com/lua-ai-global/lua-cli/issues](https://github.com/lua-ai-global/lua-cli/issues)

---

## Example: Full E-commerce Agent

Here's a complete example showing an e-commerce agent with tools, webhooks, and jobs:

```typescript
// src/index.ts
import { LuaAgent } from 'lua-cli';
import productSkill from './skills/product.skill.js';
import orderSkill from './skills/order.skill.js';
import orderWebhook from './webhooks/order.webhook.js';
import inventoryJob from './jobs/inventory.job.js';

export const agent = new LuaAgent({
  name: 'ecommerce-assistant',
  persona: 'You are an e-commerce assistant helping customers browse products, place orders, and track shipments.',

  skills: [productSkill, orderSkill],
  webhooks: [orderWebhook],
  jobs: [inventoryJob],

  preProcessors: [],  // Add message filters
  postProcessors: []   // Add response formatters
});
```

**Tools:**
- `search_products` - Search product catalog
- `get_product_details` - Get product info
- `add_to_cart` - Add items to basket
- `place_order` - Checkout and create order
- `track_order` - Get order status

**Webhook:**
- `order-webhook` - Receive payment notifications

**Job:**
- `inventory-job` - Daily inventory check and alerts

This demonstrates a production-ready agent architecture!

---

**Happy building! 🚀**

---

**Version:** 3.5.0-alpha.3
**Last Updated:** February 2026
