Skip to content

feat: add scripts/quickstart.sh for one-command setup - #572

Draft
Marc-cn wants to merge 4 commits into
darnitdevorg:mainfrom
Marc-cn:feat/quickstart-script
Draft

Marc-cn wants to merge 4 commits into
darnitdevorg:mainfrom
Marc-cn:feat/quickstart-script

Conversation

@Marc-cn

@Marc-cn Marc-cn commented Oct 9, 2026 •

Copy link
Copy Markdown
Collaborator

Summary

Adds scripts/quickstart.sh, a one-command setup from source.

What it does:

  1. Checks for git. Offers to install uv and zizmor if they are missing. Warns if gh is missing or not logged in.
  2. Uses the darnit checkout the script lives in, or clones one into ~/.local/share/darnit.
  3. Installs with uv sync --frozen, so users get the dependency versions in uv.lock, and links darnit into ~/.local/bin if nothing is there already.
  4. Runs an OpenSSF Baseline level 1 audit on the given repository (--all-levels for everything).
  5. If Claude Code is installed, offers to register the MCP server with darnit install --from-source.

It asks before installing anything or writing ~/.claude.json; --yes skips the questions. With no terminal and no --yes it installs nothing. It changes nothing in the audited repository.

Docs: a "One-command setup" section in docs/install/from-source.md, a pointer in the README, and a CHANGELOG entry.

Depends on #571. This branch is stacked on it, so the diff shows that commit too until it merges. A run without a checkout clones main, and main needs --from-source for step 5 to work.

Type of Change

  • Bug fix (non-breaking change fixing an issue)
  • New feature (non-breaking change adding functionality)
  • Breaking change (fix or feature causing existing functionality to change)
  • Documentation update
  • Refactoring (no functional changes)

Testing

  • Tests pass locally (uv run pytest tests/ -v): 5141 passed, 26 skipped
  • Added tests for new functionality (the script has no automated tests; see the manual runs below)
  • Linting passes (uv run ruff check .); shellcheck is clean on the script

Manual runs on RHEL 10.2 (x86_64), against a toy repository with one README and no remote:

  • From a checkout: installs, audits (26 level 1 controls), exit 0.
  • Piped through stdin with --dir: clones, installs, audits.
  • Empty HOME with no uv: installs uv after a yes at the prompt; same with --yes; a second run reuses the clone.
  • Empty HOME, no terminal, no --yes: refuses with exit 1 and writes nothing.
  • An existing ~/.local/bin/darnit that points elsewhere is left alone, with a warning.
  • Registration, using a stub claude on PATH: the entry is the checkout's .venv/bin/darnit serve; a second run does not stop on the overwrite prompt.

Also run on WSL (Ubuntu 24.04) with Claude Code 2.1.168: the script registered the server, and Claude Code ran a level 1 audit of a real repository through it (the /darnit-audit skill, audit_openssf_baseline, three judgments submitted). The repository's working tree stayed clean.

Not tested: macOS and the wget fallback. Windows is supported only through WSL (bash).

AI assistance

  • No AI assistance was used
  • AI assistance was used

Claude wrote the script and the doc edits. I ran every test above myself on the VM. The commit carries an Assisted-by: Claude:claude-fable-5-1 trailer.

Additional Notes

Two choices worth a look in review:

  • uv sync --frozen and not uv tool install --editable (the "Quick install" in from-source.md). The tool install resolves without the lockfile and today picks tree-sitter-language-pack 1.6.3, with which darnit audit crashes. uv sync also installs the dev group; I kept it so that running the script inside a contributor's checkout does not remove pytest from their environment.
  • The audit uses --tags level=1, because darnit audit --profile level1_quick currently returns all 66 controls.

I will file these as separate issues: the uv tool install crash, --profile having no effect on darnit audit, and a repository with no remote producing platform API calls with an empty owner that are reported as ERROR.

darnit install always registers 'uvx --from darnit-mcp darnit serve' as the MCP server command. From a source checkout that runs the PyPI package, not the code that was installed.

--from-source registers the darnit executable of the running installation instead: the console script next to the running interpreter, falling back to darnit on PATH. The default entry is unchanged.

Signed-off-by: Marc-cn <130138935+Marc-cn@users.noreply.github.com>
Assisted-by: Claude:claude-fable-5-1
A source checkout installs every workspace plugin, and darnit serve without --framework takes the first one it finds (community-spec). Claude Code then connected to a server that had no OpenSSF Baseline tools.

Register 'serve --framework openssf-baseline', the same arguments as the manual command in docs/install/from-source.md. Found by running the registered server from Claude Code.

Signed-off-by: Marc-cn <130138935+Marc-cn@users.noreply.github.com>
Assisted-by: Claude:claude-fable-5-1
Installs uv and zizmor if they are missing (asking first), uses the darnit checkout the script lives in or clones one, installs from uv.lock, runs an OpenSSF Baseline level 1 audit, and offers to register the MCP server with Claude Code through darnit install --from-source.

Signed-off-by: Marc-cn <130138935+Marc-cn@users.noreply.github.com>
Assisted-by: Claude:claude-fable-5-1
@Marc-cn
Marc-cn force-pushed the feat/quickstart-script branch from 3a0b395 to afe345a Compare October 9, 2026 21:45

@mlieberman85 mlieberman85 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, the script is careful in a lot of places (tty handling, leaving a foreign ~/.local/bin/darnit alone, nothing written to the audited repo; I confirmed that last one). A few things before merge:

  1. The uv bootstrap (quickstart.sh:109-111) is curl | sh of an unpinned installer, which by default edits the user's shell rc files. Please run it with UV_NO_MODIFY_PATH=1 and print the PATH hint, or say in the prompt that it will modify the profile. Pinning the installer version would be a bonus.
  2. Please drop the curl … | bash -s -- usage from the header (lines 7-8). The docs rightly say download and read first.
  3. The registration prompt (line 203) mentions only ~/.claude.json, but darnit install --force without --mcp-only also reinstalls ~/.claude/skills/darnit-* and rmtrees the existing ones. Please mention the skills in the prompt, or don't force them.
  4. uv sync --frozen (line 141) in a checkout synced with --all-extras (our CI/runbook default) uninstalls 33 packages (sigstore, pytest-cov, pre-commit, claude-agent-sdk, …). --inexact would avoid that.
  5. Smaller: I'd move the README pointer below the published channels, since 0.2.0 is about to make PyPI the default. Consider [y/N] for the install prompts, and a shellcheck + --help CI step.

This will need a rebase once #571 is squash-merged.

Drafted with Claude Code; reviewed and posted by me.

- Install a pinned uv with UV_NO_MODIFY_PATH=1, so the installer does not edit shell profiles; print the PATH line instead, and say so in the prompt.
- Remove the curl-pipe-bash usage from the header. The docs say to read the script first.
- The registration prompt now says that the darnit skills in ~/.claude/skills are reinstalled, not only that ~/.claude.json changes.
- uv sync --inexact, so a checkout synced with --all-extras keeps its packages (116 before and after; it lost 33 without it).
- Prompts default to no.
- Move the README pointer below the published channels.
- CI: shellcheck and --help on the script in the Lint job.

Signed-off-by: Marc-cn <130138935+Marc-cn@users.noreply.github.com>
Assisted-by: Claude:claude-fable-5-1
@Marc-cn

Marc-cn commented Oct 10, 2026

Copy link
Copy Markdown
Collaborator Author

Thanks, pushed one commit

  1. uv is installed from a pinned installer (0.13.0, the version I tested with) with UV_NO_MODIFY_PATH=1. The prompt says the shell profile is not changed, and the script prints the export PATH=... line itself. Checked in an empty HOME: no .bashrc, .profile or .zshrc is created.
  2. The curl | bash usage is goner from the header.
  3. The registration prompt now says it replaces the darnit entry in ~/.claude.json and reinstalls the darnit skills in ~/.claude/skills/. I kept --force, because without it darnit install stops on its own overwrite prompt.
  4. uv sync --frozen --inexact. In a checkout synced with --all-extras: 116 packages before and after.
  5. All three prompts default to no. The README pointer is below the published channels. The Lint job runs shellcheck and --help on the script.

I will rebase once #571 is squash-merged.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants