Skip to content

Techopolis/PerspectiveCLI

Repository files navigation

PerspectiveCLI

GitHub Release GitHub Stars License: MIT Platform Apple Silicon

A lightweight, open-source Swift CLI for running Apple Foundation Models and MLX models on your Mac.

Perspective CLI showing the user asking Foundation Models to give some quick information about iOS

Requirements

  • macOS 26+ (Tahoe)
  • Apple Silicon (M1 or later)
  • Xcode 26+
  • Swift 6.0+

Foundation Models requires Apple Intelligence to be enabled. MLX mode works on any Apple Silicon Mac.

Install

Homebrew

brew install techopolis/tap/perspective

Shell Script

The quickest way to install without Homebrew:

curl -fsSL https://raw.githubusercontent.com/techopolis/PerspectiveCLI/main/scripts/remote-install.sh | bash

Manual Download

Download the latest release archive from Releases, then:

tar xzf perspective-cli-*.tar.gz
cd perspective-cli-*
sudo ./install.sh

This installs to /usr/local/bin (requires sudo because the directory is owned by root on macOS). If /usr/local/bin isn't on your PATH, the script will tell you how to add it.

To uninstall:

sudo ./install.sh --uninstall

Build from Source

git clone https://github.com/your-username/PerspectiveCLI.git
cd PerspectiveCLI
./build.sh
swift run PerspectiveCLI

To create a release archive:

./build.sh dist

Usage

Command-Line Arguments

Run with --prompt for one-shot mode (no REPL, clean output for piping):

perspective --fm --prompt "What is Swift?"
perspective --mlx --prompt "Hello"
perspective --mlx --mlx-model mlx-community/gemma-3-4b-it-4bit --prompt "Hi"
perspective --temperature 0.5 --system "Be brief" --prompt "Explain recursion"
Argument Short Value Description
--fm Use Foundation Models backend
--mlx Use MLX backend
--model -m <model-id> Set MLX model
--prompt -p <text> Send prompt and exit (one-shot mode)
--temperature -t <float> Set temperature (FM: 0.0-1.0, MLX: 0.0-2.0)
--stream -s Enable streaming output (FM)
--system <text> Set a custom system prompt
--tools Enable tool calling (FM)
--help -h Show usage help

Without --prompt, arguments pre-configure the interactive REPL:

perspective --mlx                # enter REPL with MLX pre-selected
perspective --fm --tools         # enter REPL with FM + tools enabled

Interactive REPL

Type messages to chat. Use slash commands to control the CLI:

Backend Commands

Command Description
/fm Switch to Foundation Models backend
/mlx Switch to MLX backend
/mlx-model <id> Set MLX model (e.g. mlx-community/gemma-3-4b-it-4bit)
/temperature <n> Set temperature (FM: 0.0-1.0, MLX: 0.0-2.0, default: 0.7)
/stream Toggle streaming (FM only)
/reset Reset conversation

Tool Commands

Tools are disabled by default. Enable them for the FM backend:

Command Description
/tools Show tool status and list registered tools
/tools enable Enable tool calling (FM only)
/tools disable Disable tool calling

System Prompt Commands

Command Description
/system <prompt> Set a custom system prompt
/system Show current custom system prompt
/system default Show the built-in default system prompt
/system clear Clear custom system prompt

Other

Command Description
/help Show help
/quit, /exit Exit

Example

[FM] You: What is iOS?
[FM] Assistant: iOS is Apple's mobile operating system...

[FM] You: /tools enable
[OK] Tools enabled

[FM] You: What's the weather in San Francisco?
  [Tool] getWeather: San Francisco
[FM] Assistant: The current weather in San Francisco is 72°F and sunny.

[FM] You: /mlx
[OK] Switched to MLX backend

[MLX:gemma-3-1b-it-qat-4bit] You: Tell me a joke
[MLX] Assistant: Why do programmers prefer dark mode? ...

Adding Your Own Tools

  1. Create a tool in Sources/PerspectiveCLI/Tools/:
import Foundation
import FoundationModels

struct MyCustomTool: Tool {
    let name = "myTool"
    let description = "Description of what your tool does."

    @Generable
    struct Arguments {
        @Guide(description: "Parameter description.")
        var query: String
    }

    func call(arguments: Arguments) async throws -> String {
        return "Result for: \(arguments.query)"
    }
}
  1. Register it in Sources/PerspectiveCLI/Tools/ToolRegistry.swift:
private init() {
    register(ExampleWeatherTool())
    register(MyCustomTool())
}
  1. Build and run. Enable tools with /tools enable to use them.

Architecture

Sources/PerspectiveCLI/
├── PerspectiveCLI.swift               # Entry point + chat loop + commands
├── Backends/
│   ├── FoundationModelsBackend.swift  # Apple FM with native tool calling
│   └── MLXBackend.swift               # MLX open-weight models via mlx-swift
├── Tools/
│   ├── ToolRegistry.swift             # Central tool registry
│   └── ExampleWeatherTool.swift       # Example tool (mock weather data)
└── Models/
    ├── CLIModels.swift                # In-memory conversation tracking
    └── FoundationModelCoordinator.swift
  • FM backend: Tools are passed to LanguageModelSession which handles calling them natively. Only active when tools are enabled.
  • MLX backend: Runs open-weight models from HuggingFace via mlx-swift. Models are downloaded and cached on first use. Supports both LLM and VLM models.
  • ToolRegistry: Register a tool once, it's available to both backends.

License

MIT License. See LICENSE for details.

About

A CLI for running Foundation Models and MLX models based on Perspective Intelligence

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors