Luca is a lightweight and decentralised tool manager with support for agentic skills and building local pipelines. It supports both macOS and Linux. It helps developers install, manage, and activate specific versions of development tools in their projects, install agentic skills for AI coding agents (Claude Code, Cursor, GitHub Copilot, and more), and run ordered sequences of shell tasks via a built-in pipeline engine. It creates project-specific tool environments without polluting your global PATH.
- Version-specific installations: Install specific versions of tools needed for your project
- Project isolation: Each project can have its own set of active tools
- Simple specification: Define required tools in a simple YAML file (Lucafile)
- Zero configuration: Just create a Lucafile and run
luca install - No PATH pollution: Tools are symlinked locally in your project directory
- Idempotent operations: Safe to run multiple times
- Skill management: Install and manage agentic skills for AI coding agents (Claude Code, Cursor, GitHub Copilot, and more)
- Pipeline runner: Define and execute ordered sequences of shell tasks with parameters, conditions, and env-file support
Install the latest version with
curl -fsSL https://luca.tools/install.sh | bashOptionally define per-project .luca-version files containing the desired version before running the above command
echo "0.15.0" > .luca-versiongit clone https://github.com/LucaTools/Luca.git
cd Luca
swift build -c release
cp -f .build/release/luca /usr/local/bin/lucaOn Linux, you can build a portable binary that doesn't require the Swift runtime:
swift build -c release -Xswiftc -static-stdlibTwo companion repositories make it easy to use Luca in CI:
- setup-luca — a GitHub Action (also on the Marketplace) that installs Luca and optionally install tools as part of your workflow.
- LucaWorkflows — ready-to-use workflow templates to build, package, and publish Luca-compatible releases from Swift, Go, Rust, Python, C#, and Zig projects.
- Create a
Lucafilein your project directory:
---
tools:
- name: FirebaseCLI
version: 14.12.1
url: https://github.com/firebase/firebase-tools/releases/download/v14.12.1/firebase-tools-macos
- name: SwiftLint
binaryPath: SwiftLintBinary.artifactbundle/swiftlint-0.61.0-macos/bin/swiftlint
version: 0.61.0
url: https://github.com/realm/SwiftLint/releases/download/0.61.0/SwiftLintBinary.artifactbundle.zip
- name: Tuist
binaryPath: tuist
version: 4.80.0
url: https://github.com/tuist/tuist/releases/download/4.80.0/tuist.zip- Install the tools:
luca installYou can also install tools directly from GitHub releases by specifying the organization, repository, and version:
luca install TogglesPlatform/ToggleGen@1.0.0Specify the name of the release asset if the naming is not clear enough for Luca to work it out:
luca install krzysztofzablocki/sourcery@2.2.7 --asset sourcery-2.2.7.zipSymlinks will be created in the current directory at .luca/tools.
- Use your tools:
tuist --help
swiftlint --helpUninstall a specific tool version:
luca uninstall SwiftLint
# Prompts to select a version to uninstallOr specify the version directly:
luca uninstall SwiftLint@0.61.0List all tools and versions installed:
luca installed
FirebaseCLI:
- 14.12.1
Sourcery:
- 2.2.5
SwiftLint:
- 0.53.0
- 0.62.0
tuist:
- 4.78.0List the tools linked in a project:
luca linked
FirebaseCLI:
version: 14.12.1
binary: firebasee
location: /Users/alberto/.luca/tools/FirebaseCLI/14.12.1/firebasee
Sourcery:
version: 2.2.5
binary: sourcery
location: /Users/alberto/.luca/tools/Sourcery/2.2.5/bin/sourcery
tuist:
version: 4.78.0
binary: tuist
location: /Users/alberto/.luca/tools/tuist/4.78.0/tuistRemove a symlink from the current project's .luca/tools directory:
luca unlink swiftlintSkills are agentic plugins for AI coding agents (Claude Code, Cursor, GitHub Copilot, and others). Add a skills: section to your Lucafile:
---
skills:
- name: swift-testing-expert # Install a specific skill by name
repository: AvdLee/Swift-Testing-Agent-Skill
- name: web-design-guidelines
repository: vercel-labs/agent-skills
- repository: https://github.com/AvdLee/Swift-Testing-Agent-Skill # Omit 'name' to install all skills from a repository
agents: # Optional — omit to target all supported agents
- claude-code
- cursorThen run:
luca installSkills are installed into .luca/skills/ in the current project and symlinked into agent-specific directories (e.g. .claude/skills/, .cursor/skills/).
Install skills directly from a repository without a Lucafile:
# Install all skills from a repository
luca install vercel-labs/agent-skills
# Install specific skills by name
luca install vercel-labs/agent-skills --skill web-design-guidelines --skill deploy-to-vercel
# Target specific agents only
luca install vercel-labs/agent-skills --agent claude-code --agent cursorIf you prefer to use Vercel Labs' skills tool instead of Luca's native pipeline, pass --use-npx (requires Node.js and npx):
luca install vercel-labs/agent-skills --use-npxluca installed --skills
web-design-guidelines
swift-testing-expertluca uninstall swift-testing-expertSome skills are useful across all projects and shouldn't require a per-project Lucafile to install. The --global flag installs skills to your home directory, making them available in any project.
Install globally:
# Install all skills from your global Lucafile (~/.config/luca/Lucafile)
luca install --global
# Install a specific skill globally from a repository
luca install org/repo --skill my-skill --global
# Use a custom global Lucafile instead of ~/.config/luca/Lucafile
luca install --global --spec ~/my-global-skills.yamlUninstall a global skill:
luca uninstall my-skill --globalList globally installed skills:
luca installed --skills --globalGlobal paths:
| Resource | Path |
|---|---|
| Global Lucafile | ~/.config/luca/Lucafile |
| Global skill cache | ~/.luca/skills/ |
| Global agent dirs | Per agent (e.g. ~/.claude/skills/, ~/.config/opencode/skills/) — run luca agents for full list |
Notes:
- Running
luca install --globalagain fetches the latest version of all skills (no separate update command needed) - Project-local skills take precedence over global skills when both exist for the same agent
repos:aliases in the globalLucafileare supported — the same spec parser is used--globalis skills-only; tools already install globally to~/.luca/tools/and don't need this flag
A Lucafile can define both tools: and skills: together. By default, luca install installs everything. Use --only-tools or --only-skills to install only one category:
luca install --only-tools # Install binary tools, skip skills
luca install --only-skills # Install skills, skip binary toolsPipelines let you define an ordered sequence of shell tasks in a YAML file and run them with a single command. Tasks execute sequentially; Luca stops at the first failure unless continue-on-error is set.
- Create a pipeline file — either in the current directory or in a
pipelines/subdirectory:
---
parameters:
- name: configuration
description: Build configuration
default: debug
- name: upload
description: Upload the build artifact after building
default: "false"
tasks:
- name: Build
command: swift build --configuration ${configuration}
- name: Test
command: swift test
when: ${configuration} == debug
- name: Upload artifact
command: ./scripts/upload.sh
when: ${upload} == true
continue-on-error: true- Run it by name (no path or extension needed):
luca run buildOr provide an explicit path:
luca run --file pipelines/release.ymlPass parameter values at runtime with --param:
luca run build --param configuration=release --param upload=truePreview what would happen without executing anything:
luca run build --dry-run --param configuration=releaseDeclare parameters in the parameters: block. Reference them in any task command with ${name}. Parameters with a default: are optional; those without one are required — Luca exits with an error if no value is supplied via --param.
Store parameter values in a YAML file and pass it with --params-file:
# build.params.yml
params:
- key: configuration
value: release
- key: upload
value: "true"luca run build --params-file build.params.ymlLuca also looks for a params file automatically by convention (<name>.params.yml, <name>.params, pipelines/<name>.params.yml, pipelines/<name>.params). Values from --param override values from the params file.
Inject environment variables into every task from a dotenv file:
# .env
CI=true
DEVELOPER_DIR=/Applications/Xcode.appluca run build --env-file .envLuca loads .env from the current directory automatically when it exists. Use --env-file to point to a different file.
Use when: on any task to skip it conditionally. Supported forms:
| Expression | Behaviour |
|---|---|
${name} == value |
Run if the parameter equals value |
${name} != value |
Run if the parameter does not equal value |
${name} |
Run if the parameter is truthy (non-empty, not false or 0) |
| Field | Level | Description |
|---|---|---|
tasks |
pipeline | Ordered list of tasks (required) |
parameters |
pipeline | Declared input parameters |
env |
pipeline | Environment variables applied to every task |
working-directory |
pipeline | Default working directory for all tasks |
name |
task | Human-readable label (required) |
command |
task | Shell command to execute (required) |
tools |
task | Explicit list of tools to validate before execution |
env |
task | Per-task environment variables (merged on top of pipeline-level env) |
working-directory |
task | Overrides the pipeline-level working directory |
when |
task | Condition expression; task is skipped when it evaluates to false |
continue-on-error |
task | When true, a non-zero exit is logged as a warning and execution continues |
Luca performs the following steps:
- Reads the tool specifications from your Lucafile
- Downloads the specified zip files if they're not already installed
- Extracts the binaries to
~/.luca/tools/{tool-name}/{version}/ - Creates symlinks in
.luca/tools/in your current directory - Tools can then be accessed via
.luca/tools/{binary-name}
For skills, Luca:
- Reads the skill specifications from your Lucafile (or accepts a repository directly)
- Clones or pulls the skill repository
- Stores skill files in
.luca/skills/in the current project and symlinks them into agent-specific directories (e.g..claude/skills/,.cursor/skills/) - Skills are immediately available to the configured AI coding agents
Luca looks for a spec file in the current directory using the following priority: Lucafile, Lucafile.yml, Toolfile, Toolfile.yml, Skillfile, Skillfile.yml. The alternative names are convenient when you want to keep tool and skill definitions in separate files, but the format is the same regardless of the file name — any spec file can contain both tools: and skills: sections.
The spec file is a YAML file with the following structure:
---
tools:
- name: ToolName # Logical name for the tool
version: 1.2.3 # Version to install
url: https://example.com/tool-1.2.3.zip # Remote URL to an archive containing the tool or an executable file.
binaryPath: path/to/binary # Path to the binary within the archive file, if the release comes as an archive (optional)
desiredBinaryName: toolname # Name of the binary stored locally. Requires `url` to point to an executable file, ignored otherwise. (optional)
checksum: e0a6540d01434f436335a9... # The checksum hash of asset associated with the tool (optional)
algorithm: (md5|sha1|sha256|sha512) # The algorithm used to generate the checksum (optional)
skills:
- name: skill-name # Name of the specific skill to install (optional — omit to install all skills from the repository)
repository: owner/repo # GitHub shorthand (owner/repo) or full HTTPS/Git URL
agents: # Agent identifiers to install skills for (optional — omit to target all supported agents)
- claude-code
- cursor
- github-copilotCompletely uninstall the tool from the system:
curl -fsSL https://luca.tools/uninstall.sh | bash- macOS 13.0 or later, or Linux (x86_64, arm64)
- Swift 5.7 or later (for building from source)
Contributions are welcome! Please feel free to submit a Pull Request.
- Fork the repository
- Create your feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add some amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
Find me on X / Bluesky / LinkedIn
This project is licensed under the Apache 2.0 License - see the LICENSE file for details.