Skip to content

feat(cli): add darnit install --from-source - #571

Open
Marc-cn wants to merge 3 commits into
darnitdevorg:mainfrom
Marc-cn:fix/install-from-source
Open

Marc-cn wants to merge 3 commits into
darnitdevorg:mainfrom
Marc-cn:fix/install-from-source

Conversation

@Marc-cn

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

Copy link
Copy Markdown
Collaborator

Summary

darnit install always writes uvx --from darnit-mcp darnit serve as the MCP server command. From a source checkout, that registers the PyPI package and not the code that was just installed. docs/install/from-source.md recommends that command.

This adds darnit install --from-source. It registers the darnit executable of the running installation: the console script next to the running interpreter, falling back to darnit on PATH. Without the flag, the entry is unchanged.

The entry names the framework because a source checkout installs every workspace plugin, and darnit serve without --framework takes the first one it finds (community-spec).

  • cli.py: the flag and a small _local_darnit_executable() helper.
  • Tests: three new cases in tests/darnit/test_cli.py (registers the local executable, falls back to PATH, fails cleanly with exit 1 and no settings file when nothing is found).
  • Docs: docs/install/from-source.md and docs/getting-started/using-skills.md now show the flag. CHANGELOG entry under Added.

I found this while building a quick-start script (follow-up PR): the audit used the checkout, but the server registered for Claude Code was the PyPI one.

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)

Framework Changes Checklist

  • Updated framework spec (docs/architecture/framework-design.md) if behavior changed (the spec does not mention the install command, so nothing to change)
  • Ran uv run python scripts/validate_sync.py --verbose and it passes

Testing

  • Tests pass locally (uv run pytest tests/ -v): 5141 passed, 26 skipped (main: 5138)
  • Added tests for new functionality (if applicable)
  • Linting passes (uv run ruff check .)

Also run by hand on RHEL 10, with HOME pointed at an empty directory:

  • darnit install --mcp-only still writes the uvx entry.
  • darnit install --mcp-only --force --from-source writes <checkout>/.venv/bin/darnit with args ["serve", "--framework", "openssf-baseline"], both when started from the venv path and through a ~/.local/bin/darnit symlink.
  • The registered command runs (--version).

Tested with Claude Code 2.1.168 on WSL (Ubuntu 24.04): the registered server connects, and Claude Code ran a level 1 audit of a real repository through it. An earlier version of this PR registered serve with no framework; that test is what showed Claude Code getting only the CSL tools.

Not tested: Windows (the helper looks for darnit.exe there).

AI assistance

  • No AI assistance was used
  • AI assistance was used

Claude Fable 5.1 wrote the code change, the tests. I ran every step and checked the results myself. The commit carries an Assisted-by: Claude:claude-fable-5-1 trailer.

Additional Notes

Open question for review: the flag name. --from-source describes the common case, but it also fits any non-PyPI install (for example uv tool install --editable). We can rename.

@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.

Nice, this works end to end for me. I registered via the tool-bin symlink and the server comes up as openssf-baseline with the full tool set. A few things:

  1. The reason you name the framework applies to the default entry too. With darnit-mcp from PyPI the installed frameworks are gittuf, openssf-baseline and reproducibility, and serve without --framework picks the first sorted one, which is gittuf. Could you add --framework openssf-baseline to the uvx entry as well, or an --framework option on install defaulting to it? A follow-up issue is fine if you'd rather keep this PR narrow.
  2. from-source.md:66 suggests install --project --from-source, which commits a machine-specific absolute path into a shared .mcp.json, and SECURITY_GUIDE.md already discourages --project. I'd drop that line or point it at the security guide.
  3. On naming: since this registers "the running installation" whatever it is, something like --local might age better once 0.2.0 is on PyPI. Your call.
  4. Nit: resolve the executable before the backup/mkdir in cmd_install, so the failure path doesn't touch the settings dir.

Drafted with Claude Code; reviewed and posted by me.

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
Review on darnitdevorg#577: the uvx entry runs the darnit-mcp release on PyPI, and
releases before 0.2.0 serve the first installed framework by name. Pass
--framework openssf-baseline there as well, so clients set up the
documented way get the Baseline tools whatever version uvx resolves.

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

Marc-cn commented Oct 13, 2026

Copy link
Copy Markdown
Collaborator Author

@mlieberman85 rebased onto main, and added your point 1 from #577 here: the plain darnit install entry now also passes --framework openssf-baseline, so clients set up the documented way get the Baseline tools with the 0.1.x release on PyPI too. Test updated.

@Marc-cn
Marc-cn force-pushed the fix/install-from-source branch from 5c0485f to 01d73c1 Compare October 13, 2026 20:08
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