# Setup

> Use when the user installs organic-os, says "set up organic-os", "onboard my site", "connect my website", "add another website", "switch site", "organic-os status", or runs /organic-os:setup or /organic-os:sites. Reads the enable-time install form first (anything filled there is never re-asked), audits the site URL and proposes a pre-filled profile before asking, scaffolds the per-site brain repo…

- **Type:** Skill
- **Install:** `agentstack add skill-shalintripathi-organic-os-setup`
- **Verified:** Yes — security-reviewed for prompt injection and unsafe behavior
- **Seller:** [shalintripathi](https://agentstack.voostack.com/s/shalintripathi)
- **Installs:** 0
- **Category:** [AI & ML](https://agentstack.voostack.com/c/ai-and-ml)
- **Latest version:** 0.1.0
- **License:** MIT
- **Upstream author:** [shalintripathi](https://github.com/shalintripathi)
- **Source:** https://github.com/shalintripathi/organic-os/tree/main/plugin/skills/setup
- **Website:** https://organicos.shivaatripathi.com

## Install

```sh
agentstack add skill-shalintripathi-organic-os-setup
```

Requires the [AgentStack CLI](https://agentstack.voostack.com/docs/cli). Works with Claude Code, Cursor, and any MCP-compatible agent.

## About

# organic-os setup

You are onboarding or managing sites in organic-os. Everything site-specific
comes from this interview or the audit that opens it - never invent a value
without surfacing it for the user to approve or edit, and never ask a
question the audit already answered. One question at a time, AskUserQuestion
with options where possible.

Two claims matter and they are not the same: "configured" (an answer was
recorded) and "verified working" (a live probe proved it). Setup collects
both, but only ends on the second - see Postflight scorecard.

## Interview style (every mode, every question)

- **One question at a time.** Never present a wall of questions. Ask, wait
  for the answer, then ask the next one.
- **Offer a default with every question.** State it plainly ("default: none
  - press enter to skip") so the user can move fast when they do not care.
- **Choice questions are chips.** Every question with a finite option set -
  quick-start vs full setup, approval channel, runtime, brain mode, every
  connector wizard decision - goes through the AskUserQuestion tool with
  options, which renders native multiple-choice chips in both Claude Code
  and Cowork (free-text "Other" included automatically). Mark the
  recommended option "(Recommended)" in its label so the sensible default
  is one click. Free text is reserved for values that are genuinely free
  text: the site URL when the install form did not carry it, brand voice
  notes, operator knowledge.
- **Install-form answers are pre-answered questions.** Anything Step 0.75
  found is never re-asked, in any mode - state where the value came from
  and move on.
- **Secrets are referenced, never echoed.** Confirm a form-provided
  credential as "found the WordPress Application Password from the install
  form" - the value itself never appears in chat, in a summary table, or
  in any file except the site env file.
- **Show progress.** Prefix each question with where the user is - e.g.
  "question 3 of roughly 10" for the full setup interview (count whatever
  this run will actually ask: reviewing/editing the proposed profile,
  operator knowledge, editorial rules, Google Ads, WordPress, approval
  channel, runtime, brain path, brain mode - the connector wizard runs as its own probe-and-
  verify flow and is not counted in this total), "question 2 of 3" for
  quick-start, "question 1 of 2" for a targeted update-mode re-ask.
- **End with a summary table.** After the last question and the scaffold/
  write actions, print a table of what was written and where (file path,
  field, value) so the user can see the whole result of the interview in one
  place before they move on. The postflight scorecard (below) comes after
  this table, not instead of it.

## Step 0: environment checks

- Confirm `python3` is on PATH.
- Confirm PyYAML is importable: `python3 -c "import yaml"`. If this fails,
  tell the user to run `python3 -m pip install --user pyyaml` before
  continuing - both `core.contracts` and `core.registry` require it.

## Step 0.5: where am I, where will routines run

Setup may be running in a different environment than the one routines will
execute in - most commonly a cloud Cowork session setting up a `local`
runtime that lives on the user's Mac. Work this out before touching any
file, because it changes where almost everything below gets written.

1. **Determine the setup environment.** No single signal is proof by
   itself; weigh them together, and ask if still unsure:
   - `ls ~/.config/organic-os 2>/dev/null` and `test -f ~/.claude.json` -
     a fresh cloud sandbox rarely carries config from a prior local run.
   - `gh auth status 2>&1` - a cloud sandbox is almost always
     unauthenticated; a local CLI session the user has used before usually
     is not.
   - macOS Keychain probe (local-only signal): `security find-generic-
     password -s "Claude Code-credentials" 2>&1` - a cloud sandbox has no
     keychain, so this errors immediately or the command is unavailable.
   - If the signals disagree or nothing is conclusive: ask plainly, "Are
     you running this in a local terminal on your own machine, or a
     cloud / Cowork session?"
2. **Ask which runtime will execute routines** (unless the caller already
   established this): claude-scheduled | local | ci | manual - same
   options as the full setup interview's runtime question below. If
   answered here, do not re-ask it later; carry it forward.
3. **If setup environment and runtime location match** (e.g. a local CLI
   session setting up a local runtime), continue normally - every step
   below writes directly where it says it does.
4. **If they differ**, say so out loud to the user before continuing, then
   hold to these three rules for the rest of the session:
   - **Registry and brain scaffold target the runtime location, not the
     setup session.** If setup has no way to write files on the runtime
     machine directly (no bridge shell reaching it), do not fake success.
     Emit a ready-to-run snippet - one bash block covering
     `init_site_repo.py`, `core.registry.register(...)`, and `git init` -
     for the user to paste into a terminal on the runtime machine. Record
     this row in the summary table as "handed off, not yet confirmed" and
     let the postflight scorecard be the thing that actually confirms it
     landed.
   - **Connector probes are labeled with the context that actually ran
     them.** Every `core.contracts.record_connector(...)` call passes the
     real context - `cowork-cloud` for a probe this session ran itself,
     `local-cli` for one the user ran locally and reported back, `ci` for
     a CI runner. A connector reachable from the setup session is not
     "available" for a runtime that cannot reach it - never blur the two.
     Say plainly that the runtime-side probe (which the postflight
     scorecard runs, or asks the user to run and report) is the one that
     actually matters for routines.
   - **Never run git through a device bridge.** If setup is bridging
     commands into the user's local machine, use the bridge only to
     scaffold files. `git init`, the first commit, and `gh repo create`
     happen natively - hand the user the exact commands and let them run
     in their own terminal. A bridge-proxied git init tends to write with
     the wrong identity or permissions, and it proves nothing about
     whether the runtime machine can push on its own.

## Step 0.75: read the install form

Claude Code and Cowork can render a native configuration form when the
plugin is enabled, declared in `plugin.json`'s `userConfig` block: site
URL, brand name, approval channel, Telegram bot token, WordPress
Application Password, WordPress username. Every field is optional and the
form may never have been shown or filled - design for both cases, and
treat every value as possibly absent.

Where the values land at runtime:

- **Sensitive fields** (`telegram_bot_token`, `wp_app_password`) are
  stored in the OS keychain and reach this session only as environment
  variables: `CLAUDE_PLUGIN_OPTION_TELEGRAM_BOT_TOKEN` and
  `CLAUDE_PLUGIN_OPTION_WP_APP_PASSWORD`. Probe presence without printing:
  `[ -n "$CLAUDE_PLUGIN_OPTION_WP_APP_PASSWORD" ] && echo found` - never
  `echo` the variable itself.
- **Non-sensitive fields** substitute as `${user_config.site_url}`,
  `${user_config.brand_name}`, `${user_config.approval_channel}`, and
  `${user_config.wp_username}` in plugin files, and may also be present as
  `CLAUDE_PLUGIN_OPTION_SITE_URL`, `CLAUDE_PLUGIN_OPTION_BRAND_NAME`,
  `CLAUDE_PLUGIN_OPTION_APPROVAL_CHANNEL`, and
  `CLAUDE_PLUGIN_OPTION_WP_USERNAME`. List names only, never values:
  `env | grep '^CLAUDE_PLUGIN_OPTION_' | cut -d= -f1`.
- **Defensive rule:** a value that is empty, unset, or still a literal
  unsubstituted `${user_config....}` string counts as "not provided" -
  fall through to the normal question for that field. Never fail or stall
  because the form was skipped; the interview covers everything the form
  covers.

What each present value pre-answers (never re-ask any of these):

- `site_url` - the URL question in both modes; the audit starts from it
  directly.
- `brand_name` - replaces the domain-label guess.
- `approval_channel` - the approval-channel question (validate it is one
  of in-session | telegram | slack | email | pr-merge; anything else
  falls back to asking, with the form's text shown as context).
- `wp_username` + the Application Password - the WordPress question:
  confirm the endpoint from the audited URL instead of asking blind.
- `telegram_bot_token` - the Telegram credential ask in Credentials
  below; only the chat id still needs asking.

Sensitive values are referenced, never echoed back in chat: confirm as
"found the WordPress Application Password from the install form" and
nothing more. The audit-first flow below then fills what it can from the
URL; the interview asks only the remainder.

## Step 1: read the registry, pick a mode

Read `PYTHONPATH="$CLAUDE_PLUGIN_ROOT/lib" python3 -c "..."` calling
`core.registry.load()` (default path `~/.config/organic-os/sites.yaml`,
resolved at the runtime location per Step 0.5 when it differs from the
setup session).

- **Registry empty** (no sites): if the caller (e.g. `start`) already
  established which mode the user picked, go straight to that mode below.
  Otherwise ask first, AskUserQuestion with options:
  - `Quick start (~2 minutes) (Recommended)` - go to the quick-start
    interview below. With a filled install form this is one click; with
    no form it is the URL plus 2 more questions.
  - `Full setup (audit the site, then review the proposal)` - go to the
    full setup interview below.
- **Sites exist**: ask the user what they want, AskUserQuestion with options:
  - `update ` - refresh the currently active site's profile
  - `add another website` - onboard a new site (full setup interview, own
    brain path)
  - `switch active site` - change which site routines/commands act on
  - `show status` - print the registry (all sites, which is active) plus the
    active site's site-profile.yaml summary, and the latest postflight
    scorecard summary line if one exists (see Postflight scorecard); no
    writes

### Update mode

1. READ the existing `site-profile.yaml` for the active site first. Present
   the current values back to the user.
2. Schema check: run `core.contracts.check_schema(brain_path)`. If
   `action: "stamp"`, the profile predates versioning - add
   `schema_version: 1` at the top of the file, unchanged otherwise, before
   doing anything else, and tell the user this is the migration entry
   point (this is where a future major version's migration steps would run
   too). If `compatible: false` for any other reason, relay the action
   string and stop before re-asking anything.
3. Re-ask **only** the sections the user picks (site, brand, editorial
   rules, audience, keywords, competitors, connectors, Google Ads,
   WordPress, approval channel, runtime). Do not re-run the full setup interview. If the user
   picks "connectors," run the Connector wizard below rather than a plain
   available/absent question. If the user picks "WordPress" or "approval
   channel" and it needs a new secret, run it through Credentials below.
   Update mode re-asks these sections directly - it does not re-run the
   audit-and-propose flow, since a returning user already has a profile to
   edit from.
4. Rewrite `site-profile.yaml` with just those changes.
5. Skillbook: NEVER re-append an operator note unless its text is new - read
   `skillbook.md` first, skip anything that already matches an existing
   entry's text.
6. NEVER touch `signals/`, `decisions/`, `reflections/`, or existing
   skillbook entries beyond the dedup check above - those are memory, not
   config, and setup does not rewrite memory.
7. Do not re-register routines unless the user explicitly asks to change
   cadence or runtime.
8. If any of connectors, WordPress, approval channel, or runtime changed,
   re-run just those rows of the Postflight scorecard (below) and show the
   updated table - do not force a full scorecard re-run for an update that
   only touched brand voice or keywords.
9. **Rule of thumb to state to the user: config is editable, memory is not.**
   `site-profile.yaml` and the registry are safe to change anytime; anything
   already written under signals/decisions/reflections/outcomes/skillbook
   stays as a historical record.

### Add mode

Run the full setup interview below with a fresh brain path (never reuse
another site's brain). After scaffolding, call `core.registry.register(url,
name, brain_path)` - this both records the site and makes it the active
one.

### Switch mode

Ask which registered site (list slugs + names + urls from the registry), then
`core.registry.set_active(slug)`. No file other than the registry changes.

### Show status

Print, without writing anything: every registered site (slug, name, url,
brain path), which one is active, and - for the active site - whether its
site-profile.yaml, skillbook.md, and approvals/queue.md exist, a one-line
summary of each, and the latest postflight scorecard summary line (see
Postflight scorecard) if a `runs/*-setup-scorecard/REPORT.md` exists.

## URL first, audit before asking (shared by quick-start and full setup)

Both modes below start the same way: get the URL, then let organic-os do
the looking instead of the asking. Ask only what an audit genuinely cannot
answer - this is the "audit-and-propose" model: enter a URL, get a
pre-filled profile to approve, instead of a wall of questions the plugin
could have answered itself.

1. **Ask for the site URL** - unless Step 0.75 already found `site_url`
   on the install form, in which case state it ("using
   https://example.com from the install form") and skip straight to the
   audit. When asking: no default - this is the one thing neither mode
   can guess. If the brand name is not obviously derivable from the
   domain label (a generic domain, or one that plainly does not match the
   brand), ask for it in the same turn; otherwise guess it from the domain
   label and let the user correct it during proposal review. A
   `brand_name` from the install form replaces the guess and is not
   re-asked either way.
2. **Audit before asking anything else.** Fetch the homepage and
   `/sitemap.xml` (or whatever sitemap the homepage's `` tag or `robots.txt` points at instead).
   - **Detect the CMS**: look for `wp-content`/`wp-includes` paths, a
     `generator` meta tag, and Yoast/RankMath fingerprints - a
     `post-sitemap.xml`/`page-sitemap.xml` sitemap-index shape usually
     means Yoast, a `sitemap-pt-*` shape usually means RankMath, plus
     either plugin's characteristic HTML comments. Record what was
     detected; this seeds the WordPress question later instead of asking
     blind.
   - **Read 3-5 representative pages**: the homepage plus whatever the
     sitemap or homepage nav suggests matters most - an about/product
     page, a couple of the most prominent content pages.
   - **Propose, from what was actually read** (never invent a value - if
     the audit could not reach enough pages to support a field, leave it
     blank and say so in the proposal rather than guessing):
     - Brand voice descriptors, grounded in the actual copy (e.g. "short
       sentences," "second person," "numbers up front" - whatever the
       fetched pages actually show, not a generic default list).
     - Audience segments, from who the copy is visibly written for.
     - 5-9 seed keywords, pulled from titles, headings, and repeated
       topics across the fetched pages.
     - 3-5 content-SERP competitors: run WebSearch on the top 2-3 proposed
       keywords and take the sites that actually rank for them. State the
       distinction to the user plainly - these are sites competing for
       the same search queries, which is not the same list as business

…

## Source & license

This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.

- **Author:** [shalintripathi](https://github.com/shalintripathi)
- **Source:** [shalintripathi/organic-os](https://github.com/shalintripathi/organic-os)
- **License:** MIT
- **Homepage:** https://organicos.shivaatripathi.com

Install and usage instructions live in the source repository linked above.

## Pricing

- **Free** — Free

## Security capabilities

Automated source analysis of v0.1.0 — what this tool can access:

- **Network access:** yes
- **Filesystem access:** no
- **Shell / process execution:** no
- **Environment & secrets:** yes
- **Dynamic code execution:** no

*"Yes" means the capability is present in the source — more access means more to trust, not that it is unsafe.*


## Versions

- **0.1.0** — security scan: passed — Imported from the upstream source.

## Links

- Listing page: https://agentstack.voostack.com/l/skill-shalintripathi-organic-os-setup
- Seller: https://agentstack.voostack.com/s/shalintripathi
- Browse the marketplace: https://agentstack.voostack.com/browse

---
Listed on AgentStack — the marketplace for AI agent skills and MCP servers. Every listing is security-reviewed. Creators keep 70%.
