Skip to content

Latest commit

 

History

42 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation


░██           ░██████     ░██████  ░██     ░██    ░███    ░██     ░██ 
░██          ░██   ░██   ░██   ░██ ░██    ░██    ░██░██    ░██   ░██  
░██         ░██     ░██ ░██        ░██   ░██    ░██  ░██    ░██ ░██   
░██         ░██     ░██ ░██        ░███████    ░█████████    ░████    
░██         ░██     ░██ ░██        ░██   ░██   ░██    ░██     ░██     
░██          ░██   ░██   ░██   ░██ ░██    ░██  ░██    ░██     ░██     
░██████████   ░██████     ░██████  ░██     ░██ ░██    ░██     ░██     v0.1.0
  

chmod for lines of code  |  sudo for autonomous agents


lockay is a capability layer for the agent era.
It controls what code an agent can change and what commands an agent can run.
No FUSE. No kernel modules. Just a small, auditable C binary.

[ Chinese / 中文 ]


What it does

lockay architecture

Agent can read files. Agent cannot write files directly. Agent can propose edits. lockay validates them. Agent can propose commands. cmdlock gates them.

Two enforcement layers, one binary:

Layer Problem Solution
linelock Agent rewrites wrong code Lock file regions by content hash
cmdlock Agent runs destructive commands Policy gate with risk levels L0-L4

Install

Note: Windows is not supported natively. lockay relies on POSIX APIs. Use WSL on Windows.

npm:

npm install -g lockayy
lockay init

Install script (Linux / macOS / BSD):

curl -fsSL https://raw.githubusercontent.com/Steven-ZN/lockay/main/install.sh | sh

Build from source (gcc + make required):

git clone https://github.com/Steven-ZN/lockay.git
cd lockay && make
sudo make install          # system-wide
make install-local          # user-local (~/.local/bin)

Zero library dependencies beyond a C11 compiler.


Quick start (60 seconds)

cd /your/project

# Initialize lockay (creates .lockay/ and .linelock/)
lockay init

# Generate command policy
lockay policy

# Lock a range of lines by line number
lockay lock src/api.py 40 80 you "public contract"
# Format: lockay lock <file> <start_line> <end_line> [owner] [reason]

# View what is locked
lockay status                  # all files
lockay status src/api.py       # one file

# Show file with lock marks (locked lines are marked)
lockay show src/api.py

# Unlock by lock ID (the 6-char ID shown in status)
lockay unlock a1b2c3

# Edit with lock enforcement
lockay edit src/model.py

# Run commands through the gate
lockay run "pytest tests/"
lockay run "rm -rf build/"          # prompts for approval
lockay run "git push origin main"   # denied by default

Lock vs unlock at a glance:

Action Command Notes
Lock lines lockay lock <file> <start> <end> [owner] [reason] Returns a 6-char lock ID
See locks lockay status [file] Lists all locks with their IDs
See content lockay show <file> Locked lines show visual markers
Unlock lockay unlock <lock_id> Use the ID from status
Verify lockay check <file> Checks no lock content has been modified
Restore lockay restore <file> Auto-restore tampered locked lines from the recorded git commit
Watch lockay watch [interval] Daemon: monitor and auto-restore on changes

How linelock works

Locks are stored in .linelock/locks (plain text, git-trackable):

src/api.py|a1b2c3|40|80|sha256:abc123...|sha256:def456...|sha256:ghi789...|you|2026-06-07|public contract

Each lock records three SHA-256 hashes:

Hash Content
content_hash Locked region content
before_hash 3 lines before the lock
after_hash 3 lines after the lock

When line numbers shift (inserts/deletes elsewhere in the file), lockay re-anchors the lock by finding its content hash. The lock protects content, not position.

Before edit:                    After edit:
  1: import sys                  1: import sys
  2: import os                   2: import os       (new)
  3:                             3: import re       (new)
  4: [LOCKED] def api():         4:
  5: [LOCKED]     return 42      5: [LOCKED] def api():    <-- re-anchored
  6: [LOCKED]                    6: [LOCKED]     return 42
                                 7: [LOCKED]

How cmdlock works

Command lock does not use a CLI subcommand like file lock. Instead, you edit the policy file directly:

Step What Command
Generate Create default policy file lockay policy
Edit Add your rules Edit .lockay/policy
Enforce Run commands through the gate lockay run "..."
Monitor Review all decisions Check .lockay/audit.log

Policy format: <command_pattern> <allow|ask|deny> — first match wins.

Commands are classified into 5 risk levels:

   L0  SAFE ........ ls, cat, grep, echo, find, wc, diff
   L1  EXEC ........ python, make, gcc, node, pytest
   L2  WRITE ....... touch, mkdir, cp, mv, git add
   L3  DESTRUCT .... rm, pip install, curl, git commit
   L4  PUBLISH ..... git push, ssh, sudo, chmod, kill

Policy rules in .lockay/policy:

ls *              allow      # L0: always safe
pytest *          allow      # L1: always safe
pip install *     ask        # L3: ask the user
rm -rf *          ask        # L3: ask the user
git push *        deny       # L4: never allowed
ssh *             deny       # L4: never allowed
sudo *            deny       # L4: never allowed

When a command hits an ask rule, lockay prompts interactively:

--- lockay: command gate ---
Command : rm -rf ./checkpoints
Risk    : L3 (DESTRUCT)
Policy  : ASK
-----------------------------
This command requires approval.
Options: [A]llow once  [D]eny

All decisions are written to .lockay/audit.log.


Agent-facing CLI

Designed for LLM tool-calling. Structured exit codes:

lockay show   src/main.c 100 180           # view with lock annotations
lockay set    src/main.c 150 "new text"    # change a line
lockay insert src/main.c 100 "new line"    # insert before line
lockay delete src/main.c 100 105           # delete range
lockay apply  src/main.c /tmp/patch.diff   # apply unified diff
lockay run    "pytest tests/"              # run through policy gate
Exit code Meaning
0 Success
1 Denied (outside editable region, or blocked by policy)
2 Error (file not found, parse error)

Security model

  .---------------.         .---------------.
  |   agent user   |         |  codeguard     |
  |  (read only)   |         |  (owns files)  |
  '-------^-------'         '-------^-------'
          |                          |
          |   agent invokes          |   lockay validates
          |   lockay CLI             |   then writes
          |                          |
  .-------'--------------------------'-------.
  |              lockay binary                |
  |                                           |
  |   load file -> validate locks -> atomic   |
  |   write (temp + fsync + rename)           |
  |                                           |
  |   Trusted mutation core never calls:       |
  |     system() popen() exec() shell()       |
  |   Git-based restore is isolated in the    |
  |   restore path.                           |
  '-------------------------------------------'

For production: chown codeguard:codeguard repo/ + chmod 755 repo/. Agents run as a different user with read-only access. All writes go through lockay.

For local dev: lockay enforces policy at the application level. No privilege separation needed.


TUI Editor

lockay edit <file>

Opens a nano-style terminal editor with lock enforcement. Locked lines show a visual marker and cannot be modified.

 GNU linelock 0.1                  demo.py
──────────────────────────────────────────────────
     1  class Model(nn.Module):
█    2      def __init__(self, dim):     [lock-id]
█    3          super().__init__()
     4          self.encoder = nn.Linear(dim, 64)
     5
     6      def forward(self, x):
     7          x = self.encoder(x)
     8          return x
──────────────────────────────────────────────────
^G Help  ^O Write  ^X Exit  ^L Lock  ^U Unlock
Key Action
^O Save (validates all locks before writing)
^X Exit
^L Lock the current line
^U Unlock the current line
^K Cut current line (clears content)
^A / ^E Jump to start / end of line
Arrows Move cursor
Type Insert characters (rejected on locked lines)
Backspace / Delete Delete characters (rejected on locked lines)
Enter Line break (rejected on locked lines)

If you try to edit a locked line, it prints: Line N is locked (lock-id) and rejects the change. Save validates all lock content hashes before writing to disk.


Project layout

lockay/
  src/
    main.c          CLI dispatch (16 subcommands)
    tui.c           nano-style terminal editor
    filebuf.c       line buffer + char-level editing
    lockdb.c        lock metadata store
    validate.c      content-hash validation + re-anchoring
    apply.c         secure write path (atomic)
    cmdlock.c       command gate (policy engine + audit)
    sha256.c        embedded SHA-256 (public domain)
  tests/
    test_runner.c   55 test cases
  install.sh        interactive installer (EN/ZH)
  Makefile

lockay — A simple, auditable, zero-dependency Linux tool.
Not a platform. Not a service. Just a binary that enforces boundaries.

MIT License  |  github.com/Steven-ZN/lockay

About

Agents should not have unlimited write and execution authority. Lockay locks code lines and gates commands, making every risky agent action reviewable by the user. Lockay可以精确控制 agent 修改哪些代码,执行哪些命令。

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages