aos-project-init · git:20260913.9ff238a · 2026-09-13 · sha256 5825e677ea14d281

aos-project-init git:20260913.9ff238aA

Immutable. This exact content is served forever at /api/v1/blob/5825e677ea14d281.

---
name: aos-project-init
description: >-
  Interview a project folder into AOS and write the result: a stable slug and
  domain in .aos/project.json, an OpenWiki wiki that is actually watched and
  does not index junk, memB memory bound to the slug, a Synapse map, AGENTS.md
  with its harness symlinks, and optionally CI and issue triage.
category: bdb-core
risk: low
source: bdb
date_added: "2026-09-13"
---

# AOS Project Init — Per Workspace

`/aos-setup` prepares the machine. This prepares one folder in it — and unlike
the machine skill, **this one writes**. It asks what it cannot know, shows what
it intends to write, and writes it once you agree.

Everything it decides lands in `.aos/project.json`, so a second run knows what
was already settled and changes only what you ask it to.

---

## 1. Preconditions

```bash
aos-config show    # is this machine's vocabulary present?
```

If it reports *unvollständig*, stop and run `/aos-setup` first. The domain list
is per-machine and nothing ships with one — guessing here would invent a
vocabulary the user never chose.

Then measure this folder:

```bash
node ~/.claude/skills/aos-project-init/scripts/aos-project-doctor.mjs
```

Report the failing rows before touching anything. On an existing repo some
failures are deliberate: a repo public on purpose, a scratch folder with no
remote, a project nobody wants the wiki daemon to visit. Ask rather than
"fixing" those.

---

## 2. The interview

One question at a time, each with a proposal the user can accept in a word.
Skip anything already settled in `.aos/project.json` unless asked to change it.

**Name and slug.** Propose the folder name for both. The slug becomes the memB
`project_id`, and it is written down precisely so it survives a rename: a
binding derived from the basename orphans every memory the day the folder
moves, and two folders sharing a basename share one memory scope.

**Domain.** Offer the list from `aos-config`, preselected by what the path
implies — the first segment under the workspace root. If the project sits
outside that root, ask instead of guessing.

**Wiki.** Three separate questions, because they are three separate things:
initialise a wiki here at all · **watch it**, so the daemon refreshes it every
2h · write `.openwikiignore`.

Watching is not free. Every watched project with changes costs an LLM call per
cycle, and a free-tier key hits quota on a handful. Recommend watching repos
under active work and leaving archives out.

**memB.** Bind the slug; offer a one-time ingest of the folder. Ingest reads a
lot — offer it, never assume it.

**Synapse.** A spatial map earns its keep on a codebase too large to hold in
your head. Ask; do not default it on.

**AGENTS.md.** If missing, offer the template. If a real `CLAUDE.md` already
holds content, merge it into `AGENTS.md` first and only then replace it with a
symlink. Never silently overwrite it.

**With a GitHub remote, two more.** Skip both entirely without a remote — a
local-only repo has nowhere to put them, and a skipped question is clearer than
one answered "no".

- **CI:** none · a gate (lint, typecheck, test — matched to the project type) ·
  gate plus `release-please`.
- **Triage:** none · GitHub labels (`needs-triage`, `needs-info`,
  `ready-for-agent`, `ready-for-human`, `wontfix`) · local markdown in
  `.scratch/`.

`release-please` computes the version from Conventional Commits and nothing
else: an unprefixed subject is invisible to it, and one `feat:` forces a minor
bump however small the change. Offering it imposes that rule on the project, so
write the rule into `AGENTS.md` in the same breath — and ask what the version
policy is. Some repos here move in patch steps only, where `feat:` needs
explicit permission.

---

## 3. Write

Show every intended write as one list, then write on agreement.

```json
{
  "name": "<Project Name>",
  "slug": "<stable-slug>",
  "domain": "<from aos-config>",
  "openwiki": { "enabled": true, "watch": true },
  "memb": { "projectId": "<stable-slug>" },
  "synapse": false,
  "ci": "gate",
  "triage": "github"
}
```

Then, only for what the interview enabled:

```bash
cp ~/.claude/skills/aos-project-init/assets/openwikiignore.template .openwikiignore
openwiki --init                # needs `openwiki auth <provider>` from /aos-setup
```

When the user chose to watch it, add the absolute path to `projects` in
`~/.openwiki/projects.json` — that file is the daemon's watch list. Merge into
it; never rewrite it.

For memB, write decisions through the MCP with the slug as `project_id` and the
domain as `category`:

```
add_memory({ text: "…", category: "<domain>", project_id: "<slug>" })
```

Never write credentials or high-entropy strings into memory.

---

## 4. Confirm

```bash
node ~/.claude/skills/aos-project-init/scripts/aos-project-doctor.mjs
```

Report the doctor's own count, and name anything left failing on purpose. Then
commit: `chore:` for wiring, `docs:` for `AGENTS.md`. Check the project's
version policy before reaching for `feat:`.

---

## Red flags

- Inventing a domain because `aos-config` has none. Send the user to
  `/aos-setup` instead.
- Deriving the memB binding from the folder name once a slug exists.
- Treating "has a wiki" as "is watched". They are different, and that gap is
  why wikis sit stale for months.
- Turning watching on for every repo. Quota is real.
- Committing an `AGENTS.md` still full of template placeholders.
- Asking about CI or GitHub triage in a repo with no remote.
- Offering `release-please` without writing the Conventional Commits rule into
  `AGENTS.md` — it is a trap otherwise.