There are two Gooses and one Flisk, and mixing them up wastes an afternoon. This post is about Goose the open-source agent (desktop, CLI, MCP). It is not the Goose programming language, and it is not a value you pass to --language.
Flisk is a local dev CLI. You describe a service in service.json, run flisk up, and it generates Docker and Tilt so that service starts on your machine. Goose is a reasonable way to run those commands, if you fence what it is allowed to rewrite.
Install both, then point Goose at the repo
# Goose CLI (macOS/Linux). Desktop app is fine too.
curl -fsSL [https://github.com/aaif-goose/goose/releases/download/stable/download_cli.sh](https://github.com/aaif-goose/goose/releases/download/stable/download_cli.sh) | bash
goose configure
npm install -g @flisk-sh/flisk
goose --version
flisk --version
Pin both. Flisk's public comparison is honest that the community is small, and the README has used both flisk and tdk for the same package. Check --help on the binary you actually installed before you paste a blog command into a recipe.
Tell Goose what not to touch
Flisk writes a plain Dockerfile beside service.json, and a second tree under .autogenerated/ (Tilt, nginx or Traefik, generated configs, a short AGENTS.md). The rule from Flisk's own docs: your agent should not edit either generated Dockerfile to "fix" the stack. Change service.json, then regenerate.
Add a .gooseignore next to the repo root:
.autogenerated/
**/.autogenerated/**
.env
.env.*
*.pem
And a .goosehints so the session starts with the contract:
This repo uses Flisk (flisk.sh) for local Docker + Tilt only.
- Create services with `flisk resource`, do not hand-write Dockerfiles.
- Never edit files under `.autogenerated/`.
- Backend languages today: python, go, rust, node. Default is Bun + Hono.
- Do not pass --language goose. That id is not registered.
- After a change, run `flisk doctor` and then the health URL `flisk up` prints.
- Do not deploy. Production is out of scope.
A recipe that scaffolds, it does not improvise
Goose recipes are YAML: instructions, extensions, and a prompt. Keep the prompt boring.
# .goose/recipes/flisk-backend.yaml
version: 1.0.0
title: Add a Flisk backend
description: Scaffold one backend in an existing Flisk project and report the health URL.
instructions: |
You are in a Flisk repository. Follow .goosehints.
Allowed languages: python, go, rust, node.
If the user asks for any other language, stop and say it needs
--type bring-your-own. Do not invent a provider.
Do not edit .autogenerated or any Dockerfile Flisk generated.
prompt: |
Add a backend named {{ name }} to stack {{ stack }} using language {{ language }}.
Run flisk doctor. If it fails, stop and paste the error.
Do not run flisk up unless {{ start }} is yes.
parameters:
- key: name
input_type: string
requirement: required
- key: stack
input_type: string
requirement: required
- key: language
input_type: string
requirement: required
- key: start
input_type: string
requirement: optional
default: "no"
extensions:
- type: builtin
name: developer
Run it with values, not a pasted multi-line blob. Goose substitutes --params as text before it parses the YAML. Newlines in a param break the file. Pass short tokens:
goose run --recipe .goose/recipes/flisk-backend.yaml --params name=orders-api --params stack=shop --params language=go --params start=no
If Goose tries --language goose, the CLI fails before it writes files. That is the behavior you want. Do not "fix" it by hand-creating a Goose-language scaffold inside a Bun resource.
Modes, in the order I actually use them
| Mode | Use it when |
|---|---|
| Chat | You are deciding Python vs Go vs a BYO image |
/plan |
The task touches more than one service |
| Smart approval | Goose may run flisk resource and flisk doctor
|
| Autonomous | Only after a green doctor, and not against a dirty tree |
A session that starts with "just run flisk up and fix whatever breaks" will edit a generated file. I have watched agents do that in other stacks. The ignore file is the mitigation, not a guarantee. Review the diff.
What a good session looks like
You: Use the flisk-backend recipe. name=billing, stack=shop, language=python, start=no.
Goose:
1. flisk resource billing --type backend --language python --stack shop --yes
2. flisk doctor
3. Stops. Prints the health path it expects after flisk up shop.
Does not open .autogenerated/Dockerfile.app.autogenerated.
Then you start the stack yourself:
flisk up shop
curl -fsS http://api.shop.localhost/api/billing/health
CI is a different recipe
Flisk documents a CI shape: flisk config verify, then flisk up, then wait on the health URL. If you put Goose in that job, keep the same fence. A review recipe should be read-only on the repo and must not "repair" generated files to make the wait pass.
Goose in CI is useful for release notes and draft PRs. It is a bad place to let an agent rewrite Tiltfiles until the health check goes green.
Failure modes worth naming
-
Wrong Goose. Someone installs the compiler, or the pressly migration CLI, and then wonders why
goose configuredoes not exist. -
Wrong Flisk binary.
tdkvsfliskin older docs. Use the command yourpackage.json/ install script actually put onPATH. -
Params with newlines. Pass a filename (
context_path=/tmp/task.md) if the task text is long. Let the agent read the file. -
Editing
.autogenerated/. The nextflisk upor config regenerate overwrites it. Your fix disappears, or worse, fights the generator.
Top comments (0)