DEV Community

flisk
flisk

Posted on

Drive flisk.sh with the Goose Agent Without Letting It Edit Generated Files

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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.
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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.
Enter fullscreen mode Exit fullscreen mode

Then you start the stack yourself:

flisk up shop
curl -fsS http://api.shop.localhost/api/billing/health
Enter fullscreen mode Exit fullscreen mode

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 configure does not exist.
  • Wrong Flisk binary. tdk vs flisk in older docs. Use the command your package.json / install script actually put on PATH.
  • 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 next flisk up or config regenerate overwrites it. Your fix disappears, or worse, fights the generator.

Top comments (0)