One command instead of a fragile wall of setup instructions.
Tali is an AI-friendly command manifest runner. It gives coding agents a safe, auditable way to hand work to a human:
tali 03Instead of pasting this into terminal:
cd app
npm install
cp .env.example .env
npm run db:migrate
npm run deployan agent writes a Tali manifest, registers it, and tells the user to run one short command. Tali shows the plan, asks for approval, collects inputs and secrets, executes the steps, masks sensitive output, and stores complete logs for repair.
Tali is intentionally boring in the best way: it is a runtime, not a planner. The agent decides what should happen. Tali runs the manifest predictably.
macOS and Linux:
curl -fsSL https://github.com/hjun1052/tali/releases/latest/download/install.sh | shWindows PowerShell:
irm https://github.com/hjun1052/tali/releases/latest/download/install.ps1 | iexThe installer verifies checksums, runs tali self-test, and installs the
bundled tali-agent skill into detected agent skill directories when possible.
Useful installer options:
TALI_VERSION=0.1.5 curl -fsSL https://github.com/hjun1052/tali/releases/latest/download/install.sh | sh
TALI_INSTALL_DIR="$HOME/.local/bin" curl -fsSL https://github.com/hjun1052/tali/releases/latest/download/install.sh | sh
TALI_INSTALL_SKILL=0 curl -fsSL https://github.com/hjun1052/tali/releases/latest/download/install.sh | sh
TALI_SKILL_DIRS="$HOME/.codex/skills:$HOME/.agents/skills" curl -fsSL https://github.com/hjun1052/tali/releases/latest/download/install.sh | shUpdate later with:
tali update$ tali 03
Manifest: nextjs-blog
Plan:
1. Shell: npm install
2. Write file: .env
3. Shell: npm run dev
Inputs required:
- project_name
- database_url [secret]
Okay to proceed? [y/N] y
Project name [my-app]:
Database URL:
Running step 1/3: Install dependencies
...
Run succeeded.
Logs saved to:
/Users/you/Library/Application Support/tali/runs/run-20260615071629-g42VzkQrIf something fails:
Run failed.
Failed step: 3 / 3
Step name: Start dev server
Exit code: 1
Logs saved to:
...
For AI repair, share:
tali logs latest
Coding agents are getting good at planning local changes, but the handoff to a human is still clumsy. The usual pattern is a long checklist of commands, manual edits, copied secrets, and "if this fails, try..." notes.
Tali turns that into a small contract:
- The agent writes exactly what should happen.
- The user sees the plan before it runs.
- Secrets are prompted at runtime and masked everywhere.
- Every run gets structured logs, stdout, stderr, live events, and a manifest copy.
- A failed run can be inspected by an agent and repaired with a new manifest.
That makes Tali useful for setup scripts, local dev bootstraps, one-off deploys, project migrations, test runs, environment creation, and anything else where "please run these 12 commands" would normally appear in chat.
Create a manifest:
version = 1
name = "nextjs-blog"
description = "Install dependencies, write .env, and start dev."
[[inputs]]
name = "database_url"
prompt = "Database URL"
secret = true
required = true
[[inputs]]
name = "project_name"
prompt = "Project name"
required = true
default = "my-app"
[[steps]]
name = "Install dependencies"
type = "shell"
cmd = "npm install"
[[steps]]
name = "Write env file"
type = "write_file"
path = ".env"
content = """
DATABASE_URL={{database_url}}
PROJECT_NAME={{project_name}}
"""
[[steps]]
name = "Start dev server"
type = "shell"
cmd = "npm run dev"Register it:
tali add setup.toml --jsonTell the user only:
tali 03Watch progress while the user runs it:
tali logs follow latestIf it fails, collect repair context:
tali logs latest --for-aiTali supports five MVP step types.
[[steps]]
name = "Deploy"
type = "shell"
cmd = "npm run deploy"
cwd = "."
[steps.env]
OPENAI_API_KEY = "{{openai_key}}"Shell commands run through sh -lc on macOS/Linux and PowerShell on Windows
(pwsh when available, then powershell). Tali streams stdout/stderr to the
user and stores masked logs.
[[steps]]
name = "Write env"
type = "write_file"
path = ".env"
content = "OPENAI_API_KEY={{openai_key}}"
overwrite = true
create_dirs = trueBefore overwriting a file, Tali stores a lightweight backup under the run directory so future rollback support has the data it needs.
[[steps]]
name = "Create config directory"
type = "mkdir"
path = "config"[[steps]]
name = "Copy env template"
type = "copy"
from = ".env.example"
to = ".env"
overwrite = falseUse replace_in_file when a project already has placeholders and Tali should
fill only those positions:
[[steps]]
name = "Fill API key"
type = "replace_in_file"
path = ".env"
expected_matches = 1
[steps.replacements]
"__OPENAI_API_KEY__" = "{{openai_key}}"Given this existing file:
OPENAI_API_KEY=__OPENAI_API_KEY__Tali prompts for openai_key, replaces the placeholder, stores a backup, and
logs only the number of replacements. It does not log the rendered file content.
Fields:
path: required file pathreplacements: required table ofplaceholder = replacementrequire_match: optional bool, defaulttrueexpected_matches: optional total replacement count
Steps can be conditional with when:
[[steps]]
name = "Install macOS tools"
type = "shell"
cmd = "brew bundle"
when = "os_is('macos') && file_exists('Brewfile')"Supported helpers:
os_is("macos" | "linux" | "windows")file_exists("path")dir_exists("path")env_exists("NAME")input_exists("name")input_equals("name", "value")
Use not, &&, ||, and parentheses for boolean logic.
tali add <path>
tali add <path> --json
tali list
tali run <id-or-name>
tali <id-or-name>
tali inspect <id-or-name>
tali run <id-or-name> --dry-run
tali run <id-or-name> --yes
tali run <id-or-name> --no-update-check
tali run <id-or-name> --input key=value
tali run <id-or-name> --input-env secret_name=ENV_VAR
tali logs latest
tali logs latest --json
tali logs latest --for-ai
tali logs follow latest
tali logs <run-id>
tali cleanup --dry-run
tali cleanup --older-than 30d
tali cleanup --older-than 30d --yes
tali skill install <skill-dir>
tali skill install <skill-dir> --no-overwrite
tali update --check
tali update
tali doctor
tali self-test
tali completions zshTali keeps full run logs because they are valuable for repair. Over time, that can take space. Use cleanup when old runs are no longer useful:
tali cleanup --dry-runPreview output:
Cleanup preview:
Runs older than 30d: 12
Cache entries older than 30d: 38
Estimated space to free: 84.0 MB
Nothing deleted. Run with:
tali cleanup --older-than 30d --yes
Cleanup is conservative:
tali cleanuppreviews by default.--yesis required to delete.runs/andcache/are eligible.manifests/andsecrets/are never deleted by cleanup.- A currently running run is skipped.
- If the latest run is deleted,
logs/latestis moved to the newest remaining run.
Supported ages: 60s, 15m, 12h, 30d.
Global manifests are temporary or semi-temporary handoffs created by agents. Project manifests can be private local conveniences or explicit shared project assets:
project/
└─ .tali/
├─ setup.toml
├─ build.toml
├─ deploy.toml
└─ share/
└─ ci.toml
Run them by name:
tali setup
tali build
tali deployPrivate project manifests live directly under .tali/. Because those files can
contain local paths or workflow details, Tali checks after a project-local run
whether .tali/ is ignored by git. If it is not ignored, interactive runs ask
before adding this recommended block:
# Tali private manifests and runtime files
.tali/
!.tali/share/
!.tali/share/*.tomlRuns with --yes or non-interactive stdin never modify .gitignore
automatically; they print the suggested block instead. If you want a manifest
to be committed and shared, put it under .tali/share/<name>.toml. tali <name> resolves .tali/<name>.toml first, then .tali/share/<name>.toml,
then global manifests.
Check manually:
tali update --checkUpdate in place:
tali updateAfter tali run, tali doctor, and tali self-test, Tali may perform a
passive update check at most once every 24 hours. Network failures are ignored
and never change the command result. Disable passive checks with:
tali run setup --no-update-check
TALI_NO_UPDATE_CHECK=1 tali run setupTali uses platform-correct app data directories:
- macOS:
~/Library/Application Support/tali/ - Linux:
$XDG_DATA_HOME/tali/or~/.local/share/tali/ - Windows:
%APPDATA%\tali\
Layout:
tali/
├─ manifests/
├─ runs/
├─ logs/
├─ cache/
└─ secrets/
Each run stores:
runs/<run-id>/
├─ run.json
├─ events.jsonl
├─ stdout.log
├─ stderr.log
├─ manifest.toml
└─ backups/
Tali is not a sandbox and does not try to prove shell commands are safe.
It does provide practical guardrails:
- The plan is shown before execution.
- Approval is required unless
--yesis passed. --yesapproves the manifest run, not repository policy changes such as editing.gitignore.- Secret inputs use hidden prompts.
- Secret values are masked in commands, env values, stdout, stderr, live events, and JSON logs.
- File operations cannot escape the working directory by default.
allow_outside_cwd = trueis required for file writes/copies/replacements/mkdir outside the working directory.- Persistent encrypted secrets are not implemented yet;
secrets/exists for future use.
Tali does not guess where secrets should go. The manifest author must decide where to interpolate them.
cargo test
cargo run -- doctor
cargo run -- self-testRust version is 1.85. Maintainer release tags match the Cargo version, for
example v0.1.5.
Release checks:
./scripts/release-check.shTali is early, practical infrastructure for AI-assisted development workflows. The core loop is already here: manifest, approval, execution, live logs, repair logs, agent skill installation, update, and cleanup.
If you build with coding agents and are tired of turning chat instructions into terminal chores, Tali is for you.