Skip to content
jack-workPublic

About

🎭β™ͺ Figaro, a coding agent. Pronto prontissimo.

Topics

Resources

Stars

4 stars

Watchers

0 watching

Forks

Latest commit

Β 

History

2,356 Commits

Folders and files

Repository files navigation

Figaro

Figaro

Largo al factotum della calcolatore.

figar.org is the site. Docs coming soon.

A coding agent with few opinions, firmly held. Supports multi-agent, context forking, fully persistent structured metadata, and terminal-native semantics out of box. One binary: CLI, supervisor daemon, agent runtime. JSON-RPC over unix sockets. Tutto pulito, bravo bravissimo.

Supported Providers

  • Anthropic, via API key or Max Subscription OAuth
  • Copilot, personal or enterprise (GPT 5.6, Opus 4.5-5 and Sonnet 4.5-5 tested)
  • More to come (file an issue if you want to see another provider supported)

Install

One static binary, no runtime deps. Pick a line.

curl -fsSL https://figar.org/install.sh | sh
irm https://figar.org/install.ps1 | iex
brew install jack-work/tap/figaro     # macOS
nix profile install github:jack-work/figaro
go install github.com/jack-work/figaro/cmd/figaro@latest

The shell installer takes --version and --dir, which under a pipe go after --: curl -fsSL https://figar.org/install.sh | sh -s -- --dir /usr/local/bin. It installs to ~/.local/bin by default, verifies the release sha256, and writes shell completions.

Also reachable as fig. Every path above installs the alias except go install, which needs one line: ln -s figaro $(go env GOPATH)/bin/fig.

Config lives at ~/.config/figaro/.

First run

figaro login copilot        # or: figaro login anthropic
figaro -- buongiorno

The first prompt triggers a setup wizard (provider, model, outfit). After that, figaro -- is all you need.

Run figaro -- :skills.howto! to start the interactive tutorial (the howto skill walks you through arias, forking, the form, and outfits in character).

Copilot models

The copilot provider routes models by the capability advertised in the Copilot catalog. Claude-compatible models use the Anthropic Messages transport; Responses-capable models such as gpt-5.6-terra use Figaro's native WebSocket Responses transport. Figaro does not start a Copilot CLI process.

figaro models

For noninteractive use, Copilot credentials are read in this order: COPILOT_GITHUB_TOKEN, GH_TOKEN, then GITHUB_TOKEN.

Choose a catalog model in an outfit:

[system]
provider = "copilot"
model = "gpt-5.6-terra"
context_tier = "long_context"
thinking_effort = "high"
reasoning_context = "all_turns"
reasoning_summary = "auto"
verbosity = "low"
max_tokens = 16000

Responses settings can change between turns on a live aria:

figaro set system.model '"gpt-5.6-luna"'
figaro set system.context_tier '"default"'
figaro set system.reasoning_context '"current_turn"'
figaro set system.reasoning_summary '"auto"'
figaro set system.max_context_tokens 120000
figaro set system.parallel_tool_calls false
figaro set system.temperature 0.4

system.context_tier selects the catalog's default or long-context replay budget; system.max_context_tokens can impose a smaller cap. Figaro rejects a turn that would exceed that budget rather than dropping cached history. system.reasoning_context maps to the Responses API's auto, current_turn, or all_turns mode. system.reasoning_summary accepts "auto", "concise", or "detailed" and requests a readable reasoning summary; it does not expose raw private chain-of-thought. system.temperature and system.top_p are mutually exclusive. A model switch starts a new Responses cache lineage so opaque reasoning is never replayed under a different model.

For headless or container use, Copilot accepts credentials in this order: COPILOT_GITHUB_TOKEN, GH_TOKEN, then GITHUB_TOKEN.

Context accounting

figaro status and the CTX column in figaro list report context used: the last turn's prompt plus that turn's output, i.e.

input_tokens + cache_read_input_tokens + cache_creation_input_tokens + output_tokens

All three input buckets count: with prompt caching on (the default) most of the prompt comes back as a cache read, so summing only input_tokens would under-report a long aria by orders of magnitude. Messages appended after the last metered turn are estimated at chars/4 and the figure is prefixed ~.

The window it is measured against comes from the provider (Anthropic reports max_input_tokens on /v1/models; figaro models shows the same numbers). system.max_context_tokens overrides it in either direction:

figaro set system.max_context_tokens 200000   # pin the window
figaro unset system.max_context_tokens        # back to the provider's number

Unknown models report no window rather than a guessed one, and status then prints a bare token count.

Core concepts

  • Arias: persistent conversations, append-only IR log, fork-tree storage in internal/store (originally the separate figwal module, merged in-tree 2026-08-19).
  • Forking: branch at a turn boundary; both sides share the canonical IR prefix. attend is your cd.
  • Form: per-aria key-value state, travels as patches, surfaces as system reminders.
  • Outfits: TOML profiles (provider, model, credo, skills) inherited by new arias.
  • Tools: bash, read, write, edit, process. Parallel dispatch.
  • Providers: Anthropic (direct + SDK), GitHub Copilot. Registry-driven, no switches.

Commands

figaro -- <prompt>              prompt the bound aria
figaro send -r -- <prompt>      raw output (pipe-friendly)
figaro list                     show arias
figaro attend <id>              bind to an aria
figaro fork                     branch at head
figaro fork <id>:12 -- <p>      branch at a turn and prompt the branch
figaro show <id> -n 5           last 5 turns
figaro listen <id>              follow an aria without prompting it
figaro set <key> <value>        patch form state
figaro status                   current aria info
figaro --help                   full command list

Alternate frontends

Each aria exposes a semantic, turn-shaped UI stream over local NDJSON JSON-RPC: figaro.read pulls aria.Page snapshots/pages and figaro.aria pushes the same shape as nodes change; turn.done carries completion/idle control state. The stock send, listen, inline view, and transcript pager are clients of that stream. See skills/figaro/reference/ui-stream.md and skills/figaro/reference/turns.md.

The socket surface is currently trusted-local and revision-coupled, not yet a stable public API. Protocol versioning, capability negotiation, public client packages/schema, slow-subscriber isolation, and a browser-safe bridge are tracked in the UI-stream protocol TODO.

The skill that ships inside the binary

figaro carries one first-party skill, figaro, embedded in the executable. On first use it is unpacked to a directory named by its content hash under the state dir (~/.local/state/figaro/bundled-skills/<hash>/), because a skill is only navigable if it has a path: the model gets a filePath and follows the links to the deeper chapters beside it.

figaro doctor skills            # where it unpacked, and every file in it

That is why installing figaro is one file and no directory layout. It also means an upgrade CORRECTS the skill: a bundled skill outranks a same-named copy in ~/.config/figaro/skills, so a copy cannot silently fall behind the binary it documents. If you would rather maintain your own, take the wheel:

# ~/.config/figaro/config.toml
bundled_skills = false

The other skills in this repo's skills/ directory (figscript, figla, parallel-arias, inquire-figaro, and the rest) are not bundled. Copy the ones you want into ~/.config/figaro/skills/.

Updates

figaro update                   # check for newer release
figaro update --apply           # go install the latest tag

update reports the channel it was installed through and the command that upgrades it: the installers drop a .figaro-channel marker beside the binary so that answer is read rather than guessed.

Releasing

grep -n '^replace' go.mod && echo "strip before tagging" || echo ok
scripts/release.sh patch        # flake.nix version -> tag -> GitHub release

The version lives in flake.nix and nowhere else; the tag is minted to match. Pushing the tag wakes .github/workflows/release.yml, which runs GoReleaser: it builds the linux/darwin/windows archives, uploads them plus checksums.txt to the release the script already created (mode: keep-existing, so the hand-written notes survive), and pushes the Homebrew cask to jack-work/homebrew-tap.

# smoke test:
go install github.com/jack-work/figaro/cmd/figaro@vX.Y.Z
# then bump flake.nix vendorHash if needed

Nix flake

nix build                       # produces result/bin/figaro + fig symlink
nix develop                     # dev shell with Go, tools, isolated hush

Tips

The primary supported user interface for figaro is provided by the CLI. It is designed such that context may be viewed live or snapshot quickly to avoid context switching overhead demanded by one-stop-shop coding agent applications, such as Claude Code, Codex, or Pi Agent. Rather than running a binary and typing a message in a chatbox, figaro wants to be passed messages shell using CLI verbs. Messaging verbs (i.e. send, new, fork) will bind the caller shell to the TUI LLM transcript if the response outgrows available terminal scrollback. The --forget flag will prevent that bind, allowing for multi agent communication within a single shell and without leaving standard shell REPL or blocking it for any period of time.

Idiomatically, a shell alias or binary q may be defined which aliases to fig send --. The single character alias makes the standard use case, messaging figaro and binding to shell, easier to type. The project author uses this alias and several others to avoid CLI verbiage. Other aliases, however, may naturally be defined to support emergent or alternative use cases. Figaro is in the service of the user; figaro-specific shell configurations are idiomatic.

The form is the internal name for structured state which serves both to expose structured state as agent context, and to configure figaro runtime. Set values with fig set key value. The system prefix is not natively shown to the model.

On Isolation

Figaro has only filesystem based isolation. It is currently used with full userspace privileges. It inherits the permissions of its user caller. While figaro can be run in a sandbox, a gateway is necessary to broker sandbox ingress. Furthermore, figaro is not prevented from calling any other figaro aria in its instance. Native sandboxing via first party gateway and permission modeling is a TODO. File an issue if you want to see it sooner rather than later.

License

NON-AI MPL-2.0. Copylot, source available for human use. Not for AI/ML training (LICENSE section 3.6).

About

🎭β™ͺ Figaro, a coding agent. Pronto prontissimo.

Topics

Resources

Stars

4 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages