Weave Code
Code Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

There There Cli Laravel Package

spatie/there-there-cli

Command-line client for There There. Authenticate with profiles per workspace, then browse, search, and manage tickets from your terminal—list and filter tickets, view details, reply/forward, add internal notes, and update status or assignee via API-backed commands.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Install globally (run once):

    composer global require spatie/there-there-cli
    

    Ensure the global bin directory is in your PATH:

    composer global config bin-dir --absolute
    
  2. Authenticate (run once per workspace):

    there-there login
    
  3. First command (list all tickets):

    there-there list-tickets
    
    • Output: Paginated JSON of tickets (e.g., data: [{id: "ULID", subject: "..."}]).

First Use Case: Ticket Triage Script

Create a Laravel Artisan command to auto-close stale tickets:

# In `app/Console/Commands/CloseStaleTickets.php`
use Spatie\ThereThereCli\ThereThereCli;

public function handle() {
    $cli = new ThereThereCli();
    $tickets = $cli->listTickets([
        'filter_status' => 'open',
        'filter_created_before' => now()->subDays(30)->format('Y-m-d'),
    ]);

    foreach ($tickets['data'] as $ticket) {
        $cli->updateTicketStatus($ticket['id'], ['status' => 'closed']);
        $this->info("Closed ticket {$ticket['id']}");
    }
}

Run it:

php artisan close-stale-tickets

Implementation Patterns

1. Laravel Integration Workflows

A. Artisan Commands

Wrap CLI calls in Laravel commands for reusability:

// app/Console/Commands/ThereThereCommand.php
protected $signature = 'there-there:reply {ticket} {--body= : Reply body}';
public function handle() {
    $cli = new \Spatie\ThereThereCli\ThereThereCli();
    $cli->replyToTicket($this->argument('ticket'), [
        'body' => $this->option('body')
    ]);
}

Run:

php artisan there-there:reply TICKET_ULID --body="Thanks for your message!"

B. Event Listeners

Trigger Laravel jobs on ticket events (e.g., via a cron job polling for changes):

// app/Listeners/ProcessNewTickets.php
public function handle() {
    $cli = new \Spatie\ThereThereCli\ThereThereCli();
    $tickets = $cli->listTickets(['filter_status' => 'open', 'filter_created_after' => now()->subMinutes(5)]);

    foreach ($tickets['data'] as $ticket) {
        ProcessTicketJob::dispatch($ticket);
    }
}

C. Service Classes

Encapsulate CLI logic in a service for testability:

// app/Services/ThereThereService.php
class ThereThereService {
    public function __construct(protected ThereThereCli $cli) {}

    public function assignTicketToTeam(string $ticketId, string $teamUlid): void {
        $this->cli->updateTicketTeam($ticketId, ['team_ulid' => $teamUlid]);
    }
}

2. Multi-Workspace Management

Use profiles to switch between workspaces dynamically:

// Switch profile in code
$cli = new \Spatie\ThereThereCli\ThereThereCli();
$cli->setProfile('acme-eu'); // Overrides default
$tickets = $cli->listTickets();

Laravel Config Example:

// config/there-there.php
'default_profile' => env('THERE_THERE_PROFILE', 'default'),
'profiles' => [
    'acme-us' => ['token' => env('THERE_THERE_US_TOKEN')],
    'acme-eu' => ['token' => env('THERE_THERE_EU_TOKEN')],
],

3. Data Export/Import

Export tickets to JSON for analytics:

there-there list-tickets --filter-created-after=2024-01-01 > tickets.json

Laravel Example:

// Export tickets to a Laravel collection
$cli = new \Spatie\ThereThereCli\ThereThereCli();
$tickets = collect($cli->listTickets()['data'])
    ->map(fn ($ticket) => [
        'id' => $ticket['id'],
        'subject' => $ticket['subject'],
        'created_at' => $ticket['created_at'],
    ]);

4. Attachment Processing

Download ticket attachments (e.g., screenshots):

// app/Services/AttachmentService.php
public function downloadAttachments(string $ticketId): array {
    $ticket = $cli->showTicket($ticketId);
    $attachments = [];

    foreach ($ticket['messages'][0]['inline_images'] ?? [] as $image) {
        $response = Http::withHeaders([
            'Authorization' => 'Bearer ' . $cli->getToken(),
        ])->get($image['download_url']);

        $attachments[$image['name']] = $response->body();
    }

    return $attachments;
}

5. AI-Assisted Workflows

Use the agent skill to generate Laravel code:

# Ask an AI agent to write a script
there-there install-skill
# Then prompt:
# "Write a Laravel script to list all unassigned tickets and assign them to the 'support' team."

Gotchas and Tips

1. Authentication Pitfalls

  • Token Scoping: Ensure your API token has the correct workspace scope (add X-Workspace-Id header automatically via profiles).
    • Fix: Use --profile to target the right workspace:
      there-there list-tickets --profile=acme-eu
      
  • 401 Errors: If you see Invalid API token, regenerate the token in There There settings.
  • Profile Conflicts: Avoid naming profiles after Laravel config keys (e.g., default). Use explicit names like acme-staging.

2. API Quirks

  • Data Wrapping: Responses are wrapped in a data key (e.g., {"data": {...}}). Handle this in Laravel:
    $ticket = $cli->showTicket($id)['data'];
    
  • Pagination: Always check meta.pagination for total pages:
    $totalPages = $cli->listTickets()['meta']['pagination']['total_pages'];
    
  • ULIDs: Use the full ULID (e.g., 01HX9F3K2M...), not shortened IDs.
  • Date Formats: Use Y-m-d for filters (e.g., --filter-created-after=2024-01-01).

3. Performance Tips

  • Batch Processing: Use --per-page=100 to reduce API calls:
    there-there list-tickets --per-page=100 > all_tickets.json
    
  • Caching: Cache responses in Laravel’s cache:
    $tickets = Cache::remember('there_there_tickets', now()->addHour(), function () {
        return $cli->listTickets();
    });
    
  • Rate Limiting: There There’s API has limits (~60 requests/minute). Add delays:
    sleep(1); // Between batches
    

4. Debugging

  • Verbose Output: Enable debug mode:
    there-there list-tickets --verbose
    
  • HTTP Errors: Check the raw response for non-2xx errors:
    there-there show-ticket TICKET_ULID --verbose
    
  • Profile Issues: List profiles to debug:
    there-there profiles
    

5. Extension Points

  • Custom Commands: Extend the CLI by creating a Laravel package with new commands:
    // app/Console/Commands/CustomThereThereCommand.php
    use Spatie\ThereThereCli\ThereThereCli;
    
    protected $signature = 'there-there:custom {action}';
    public function handle() {
        $cli = new ThereThereCli();
        // Custom logic...
    }
    
  • Mocking for Tests: Use Laravel’s HTTP mocking:
    Http::fake([
        'api.there-there.app/*' => Http::response(['data' => []]),
    ]);
    
  • Webhook Alternative: For real-time updates, pair with There There’s webhooks (not CLI-based).

6. Security

  • Token Storage: Credentials are stored in ~/.there-there/config.json (permissions: 0600).
  • Environment Variables: For Laravel, store tokens in .env:
    THERE_THERE_US_TOKEN=your_token_here
    THERE_THERE_EU_TOKEN=another_token
    
  • Logging: Log sensitive actions (e.g., ticket
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
hamzi/corewatch
minionfactory/raw-hydrator
hexters/coinpayment
rjcodes/rjcms
act-training/laravel-permissions-manager
alimarchal/laravel-chart-of-accounts
babenkoivan/elastic-scout-driver
mkwebdesign/filament-watchdog-v5
renatomarinho/laravel-page-speed
zedmagdy/filament-business-hours
renatovdemoura/blade-elements-ui
devgeek/beacon-admin
benjamin-rqt/data-watcher-bundle
atriumphp/atrium
sandermuller/package-boost-laravel
sandermuller/boost-skills
redaxo/core
yusufgenc/filament-api-forge
l3aro/rating-star-for-filament
leek/filament-subtenant-scope