A config driven occlusion framework for your CLIs and APIs
  • Go 98.9%
  • Shell 0.8%
  • Python 0.2%
  • Makefile 0.1%
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
coilyco-ops eea7b26348
All checks were successful
ci / secrets (push) Successful in 12s
ci / lint (push) Successful in 42s
ci / test (push) Successful in 58s
promote / gate-and-promote (push) Successful in 1m1s
release / release (push) Successful in 1m7s
Let a grant declare its own value-taking flags (#335)
2026-08-29 11:26:07 +00:00
.agents/skills/repo-umbra chore(skills): regenerate the repo pointer skill from Forgejo metadata 2026-08-20 00:37:51 -07:00
.forgejo/workflows ci: clear every blocker and advance the pin to aos-precommit-v0.54.0 2026-08-27 21:19:28 -07:00
.github ci: clear every blocker and advance the pin to aos-precommit-v0.54.0 2026-08-27 21:19:28 -07:00
.ward docs(agents): declare the lane in frontmatter, not the retired ward.yaml 2026-08-27 01:12:42 -07:00
assets docs: add umbra banner 2026-08-21 15:35:21 -07:00
cli Let a grant declare its own value-taking flags (#335) 2026-08-29 11:26:07 +00:00
cmd chore!: rename the Go module path to umbra 2026-08-13 19:55:30 -07:00
docs Let a grant declare its own value-taking flags (#335) 2026-08-29 11:26:07 +00:00
examples chore!: rename the Go module path to umbra 2026-08-13 19:55:30 -07:00
http fix(codegen): set the placement hint on every command, not just the root 2026-08-29 01:17:42 -07:00
internal/specgencli chore!: rename the Go module path to umbra 2026-08-13 19:55:30 -07:00
pkg ci: clear every blocker and advance the pin to aos-precommit-v0.54.0 2026-08-27 21:19:28 -07:00
scripts ci: clear every blocker and advance the pin to aos-precommit-v0.54.0 2026-08-27 21:19:28 -07:00
.agentic-os.toml chore!: rename the Go module path to umbra 2026-08-13 19:55:30 -07:00
.gitattributes ci: clear every blocker and advance the pin to aos-precommit-v0.54.0 2026-08-27 21:19:28 -07:00
.gitignore Repository hygiene sweep: tier-A + CONTRIBUTING + godoc-current + auto-merge 2026-05-13 05:47:10 -07:00
.golangci.yaml ci: clear every blocker and advance the pin to aos-precommit-v0.54.0 2026-08-27 21:19:28 -07:00
.pre-commit-config.yaml ci: clear every blocker and advance the pin to aos-precommit-v0.54.0 2026-08-27 21:19:28 -07:00
_typos.toml ci: clear every blocker and advance the pin to aos-precommit-v0.54.0 2026-08-27 21:19:28 -07:00
AGENTS.md ci: clear every blocker and advance the pin to aos-precommit-v0.54.0 2026-08-27 21:19:28 -07:00
CLAUDE.md chore(pre-commit): adopt context-load-points hook (v0.11.1) 2026-05-29 22:45:41 -07:00
CODE_OF_CONDUCT.md Adopt Contributor Covenant 2.1 as Code of Conduct 2026-05-13 05:31:35 -07:00
CONTRIBUTING.md chore!: rename the Go module path to umbra 2026-08-13 19:55:30 -07:00
go.mod feat(tokenmint): mint OAuth client_credentials tokens as a value provider 2026-08-19 02:47:58 -07:00
go.sum feat(tokenmint): mint OAuth client_credentials tokens as a value provider 2026-08-19 02:47:58 -07:00
godoc-current.txt Let a grant declare its own value-taking flags (#335) 2026-08-29 11:26:07 +00:00
LICENSE chore: use the full name Kai Ase Siren in attribution 2026-08-28 23:23:56 -07:00
Makefile feat(specgen): publish Homebrew and Scoop packages 2026-07-23 11:37:00 -07:00
mkdocs-requirements.txt Add mkdocs (urfave palette) + docs CI verification 2026-05-13 05:28:44 -07:00
mkdocs.yml docs(band): finish the small-band migration 2026-08-16 20:47:37 -07:00
pyproject.toml ci: clear every blocker and advance the pin to aos-precommit-v0.54.0 2026-08-27 21:19:28 -07:00
README.md docs: give umbra a reader-task front door and a getting-started page 2026-08-26 20:31:07 -07:00
SECURITY.md feat!: remove the namespace sandbox 2026-08-13 22:25:10 -07:00
staticcheck.conf Adopt urfave-shaped README + trifecta + staticcheck.conf 2026-05-13 05:23:19 -07:00

umbra

config driven occlusion framework

umbra - a config driven occlusion framework

Occlusion is the idea. umbra sits between semi-trusted automation and the host system, and what you did not declare does not get through. The boundary lives in a KDL guardfile rather than in code, so it is one artifact a reviewer reads in a sitting. umbra ships no denylist and knows nothing about your tools: policy is yours, and umbra enforces it across two surfaces, cli/ around subprocess exec and http/ around outbound requests.

It validates argv before execve, checks a scope token per verb, refuses repo-shaped verbs on a dirty tree, gates egress through a per-invocation CONNECT proxy, and appends every call to a rotating JSONL audit log. A public exit-code taxonomy separates a policy refusal from a tool failure. Full documentation in docs/index.md.

umbra is not a sandbox. It performs no execution isolation, and that is deliberate rather than unfinished. Validating argv, gating egress, and auditing every call does nothing to contain a process that is already running. Isolation is a container's job, and umbra is the gate in front of it.

Two ways in

Generate the CLI. specgen reads KDL policy plus committed locks out of a .specgen/ directory and builds a standalone guarded CLI with no hand-written Go. --skills-out also renders a native agent skill and a lazy command index.

Import the primitives. Every package stands alone if you are adding a boundary to an existing urfave/cli v3 app. Nothing consumer-shaped leaks into the API.

GOPRIVATE=forgejo.coilysiren.me go get forgejo.coilysiren.me/coilyco-flight-deck/umbra

Install specgen

brew tap coilyco-flight-deck/tap https://forgejo.coilysiren.me/coilyco-flight-deck/homebrew-tap
brew install coilyco-flight-deck/tap/specgen
scoop bucket add coilyco-flight-deck https://forgejo.coilysiren.me/coilyco-flight-deck/scoop-bucket
scoop install coilyco-flight-deck/specgen

Tagged releases also publish raw binaries and SHA256SUMS for Linux, macOS, and Windows on amd64 and arm64. specgen --version reports both the driver and the umbra ref lock freezes by default. It shells out to the Go toolchain to resolve locks and build, so Go has to be present.

Try it

examples/ holds one runnable app per primitive, and docs/getting-started.md walks the first run. The shortest:

go run ./examples/policy unsafe 'foo; rm -rf /'

Status and development

v0.x. Minor API breaks land on main with a note in the commit body and no deprecation cycle, so pin a commit in your go.mod until v1.0.0. The API locks once a second consumer lands. Forgejo is canonical and the GitHub mirror is verified. umbra is deliberately unguarded, being the framework rather than a consumer of one, so its dev verbs run through the Makefile: make build test lint vet, and make docs-serve for the rendered docs.

See also

MIT. See LICENSE.