# Shell Wallpaper

In this tutorial, you'll create a wallpaper that runs shell commands and displays their output using a terminal emulator.

## Prerequisites

Complete the [Getting Started](/en/studio/developer/tutorials/getting-started.md) tutorial first.

## Declare Shell Commands

Add a `shell` section to your `fluxlay.yaml`:

```yaml title="fluxlay.yaml"
schemaVersion: 1
name: System Monitor
slug: system-monitor
version: 0.1.0
kind: web
description: A wallpaper that displays live system information.

shell:
  macchina:
    run: macchina
    reason: Displays system information in a styled format.
    required:
      - macchina
  fetch-ip:
    run: curl -s https://httpbin.org/ip | jq -r '.origin'
    reason: Retrieves the public IP address.
    required:
      - curl
      - jq

network:
  - origin: https://httpbin.org
    reason: Used to fetch the public IP address.
```

Each command must declare `reason` (why it's needed) and `required` (the programs it depends on). Users are prompted to approve commands before they run.

## Display Terminal Output

Install Tailwind CSS for styling:

<PackageManagerCommand type="add" dev packages="tailwindcss @tailwindcss/vite" />

Register the Tailwind plugin in `vite.config.ts`:

```ts title="vite.config.ts"
import tailwindcss from "@tailwindcss/vite";
import react from "@vitejs/plugin-react";
import { defineConfig } from "vite";

import { fluxlay } from "@fluxlay/vite";

export default defineConfig({
  plugins: [react(), tailwindcss(), fluxlay()]
});
```

Update `src/main.tsx`:

```tsx title="src/main.tsx"
import { StrictMode } from "react";
import { createRoot } from "react-dom/client";
import { useTerminal, useShell, TerminalThemes } from "@fluxlay/react";
import "./index.css";

function SystemMonitor() {
  const { terminalRef, instance } = useTerminal({
    fontSize: 13,
    theme: TerminalThemes.tokyoNight
  });

  const { error } = useShell("macchina", {
    terminal: instance,
    refreshInterval: 60000
  });

  return (
    <main className="h-screen w-screen bg-zinc-900 p-8">
      <div className="h-full w-full rounded-xl overflow-hidden border border-zinc-700">
        {error && <p className="p-4 text-red-400 text-sm">{error}</p>}
        <div ref={terminalRef} className="h-full w-full" />
      </div>
    </main>
  );
}

createRoot(document.getElementById("root")!).render(
  <StrictMode>
    <SystemMonitor />
  </StrictMode>
);
```

Create `src/index.css`:

```css title="src/index.css"
@import "tailwindcss";

* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}
```

## Using runShell for Custom Display

For commands where you want to control the display yourself, use `runShell`:

```tsx
import { useEffect, useState } from "react";
import { runShell } from "@fluxlay/react";

function IpAddress() {
  const [ip, setIp] = useState<string>("...");

  useEffect(() => {
    const fetchIp = async () => {
      const result = await runShell("fetch-ip");
      if (result.success) setIp(result.stdout.trim());
    };
    fetchIp();
    const id = setInterval(fetchIp, 30000);
    return () => clearInterval(id);
  }, []);

  return <p className="text-zinc-400 text-sm">Public IP: {ip}</p>;
}
```

## Next Steps

Task-focused guides:

- [Run Shell Commands](/en/studio/developer/how-to/development/use-shell.md) — Practical `useShell` patterns.
- [Run Shell Commands Imperatively](/en/studio/developer/how-to/development/run-shell.md) — Event-driven execution with `runShell`.
- [Display Terminal Output](/en/studio/developer/how-to/development/use-terminal.md) — Terminal emulator rendering details.
- [Customize Terminal Theme](/en/studio/developer/how-to/development/customize-theme.md) — Change the colors.

When you're ready:

- [Publish Your Wallpaper](/en/studio/developer/tutorials/publish-wallpaper.md) — Share it on the Fluxlay Store.

API reference:

- [useShell](/en/studio/developer/reference/sdk/use-shell.md) / [runShell](/en/studio/developer/reference/sdk/run-shell.md) / [useTerminal](/en/studio/developer/reference/sdk/use-terminal.md)
- [Manifest (fluxlay.yaml)](/en/studio/developer/reference/cli/manifest.md)
