GreenAsh
A keyboard-driven, green-screen LiveView console — reminiscent of AS/400-style terminal screens — generated by introspection from your Ash resources. Zero UI code.
Prerequisites
An existing Phoenix + Ash project. Starting from scratch:
mix archive.install hex igniter_new
mix archive.install hex phx_new
mix igniter.new my_app --with phx.new --yes
cd my_app
mix igniter.install ash,ash_phoenix,ash_postgres --yes
(Two separate steps rather than one combined command: more reliable in practice.) See Ash's own Getting Started guide for details.
Installation
With Igniter (recommended — a single command):
mix igniter.install green_ash
This adds the dependency and patches your router. Nothing else to write.
If you'd rather run
mix green_ash.installdirectly (skippingmix igniter.install), your project must already have{:igniter, "~> 0.5", only: [:dev, :test]}in its own dependencies — Mix doesn't propagate a library'sonly:dependencies to its consumers.mix igniter.install green_ashtakes care of that for you.
Manually
If you'd rather not use Igniter, or want to see exactly what the installer does:
Add the dependency in
mix.exs:{:green_ash, "~> 0.3"}Mount the console in your router, inside a scope going through the
:browserpipeline (session required), and behind a dev-only guard:if Application.compile_env(:my_app, :dev_routes) doimport GreenAsh.Routerscope "/" dopipe_through :browsergreen_ash "/cli"endend
Gate it. The console has no access control of its own.
It lists, creates, updates and deletes any record of any exposed resource, and its
:actorcommand loads any record as the current actor to exercise your policies — that impersonation is the whole point of the tool. Reachable in production, it is an unauthenticated admin panel over your whole domain.The Igniter installer wraps the mount in the
:dev_routescheck above, which is why it is repeated here: mounting by hand is the one path where nothing stops the console shipping. If you need it somewhere other than dev, put it behind your own authentication pipeline.
That's it. /cli lists your Ash resources, and for each one: create,
list (filter + sort + pagination), business-action update/destroy (with
confirmation), record inspection, and a session-based "actor" for exercising
your policies — all derived by introspecting your actions.
Exposed domains are read dynamically, on every request, from
Application.get_env(:my_app, :ash_domains, []) — the same config key
mix ash.setup/mix ash.codegen already rely on. Add a new Ash domain later
(including via Ash's own generators, which maintain that config) and it shows
up immediately — no need to touch the router or re-run the installer.
Need to expose only a subset, or domains not registered under the standard
key? Pass domains: explicitly to override the default:
green_ash "/cli", domains: [MyApp.Bank, MyApp.Sales]
Whichever you pass, keep the route behind the dev-only guard shown under Installation — the console carries no access control of its own.
Using the console
- Navigation: digits + Enter on menus,
j/k/Enter/Escin lists. - Vim-style
:command line::list <resource>,:new <resource>,:cols <field...>(choose and order a list's columns;:cols allto restore),:actor <resource> <id>/:actor none(to exercise your policies),:tenant <value>/:tenant none(to browse multitenant resources),:whoami,:debug(raw inspection),:menu,:help. - A list's filter, sort, columns and page live in the URL, so a screen can be bookmarked or pasted to someone else.
Adding a resource
Any Ash resource declared in an exposed domain shows up on its own in /cli,
with no UI code. A few descriptions on the resource and its actions improve
the labels shown (optional).
Developing the library
mix test # no Postgres required: Ash.DataLayer.Ets harness
See examples/bank/ and examples/library/ (in the monorepo) for full
Postgres-backed examples.